diff --git a/applications/utilities/mesh/generation/cvMesh/Allwmake b/applications/utilities/mesh/generation/cvMesh/Allwmake
index eb453138ce529dfcf03af180f64350cd034726af..d88e8cee4afe888e82031a710e39bd9db82a578d 100755
--- a/applications/utilities/mesh/generation/cvMesh/Allwmake
+++ b/applications/utilities/mesh/generation/cvMesh/Allwmake
@@ -4,7 +4,8 @@ set -x
 
 wmake libso conformalVoronoiMesh
 wmake
-wmake cvMeshBackgroundMesh
+#wmake cvMeshBackgroundMesh
 (cd cvMeshSurfaceSimplify && ./Allwmake)
+wmake cellSizeAndAlignmentGrid
 
 # ----------------------------------------------------------------- end-of-file
diff --git a/applications/utilities/mesh/generation/cvMesh/Make/options b/applications/utilities/mesh/generation/cvMesh/Make/options
index 27241b29656f8f37f263f53f2697d4b8251cabda..9461fa3725d8b76cc7cdce5cc102b5aa1933bdbf 100644
--- a/applications/utilities/mesh/generation/cvMesh/Make/options
+++ b/applications/utilities/mesh/generation/cvMesh/Make/options
@@ -2,7 +2,7 @@ EXE_DEBUG = -DFULLDEBUG -g -O0
 EXE_FROUNDING_MATH = -frounding-math
 EXE_NDEBUG = -DNDEBUG
 
-CGAL_EXACT =
+CGAL_EXACT = /*-DCGAL_DONT_USE_LAZY_KERNEL*/
 CGAL_INEXACT = -DCGAL_INEXACT
 
 include $(GENERAL_RULES)/CGAL
@@ -19,7 +19,9 @@ EXE_INC = \
     -I$(LIB_SRC)/edgeMesh/lnInclude \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
-    -I$(LIB_SRC)/triSurface/lnInclude
+    -I$(LIB_SRC)/triSurface/lnInclude \
+    -I$(LIB_SRC)/sampling/lnInclude \
+    -IvectorTools
 
 EXE_LIBS = \
     $(CGAL_LIBS) \
@@ -32,4 +34,5 @@ EXE_LIBS = \
     -ledgeMesh \
     -lfileFormats \
     -ltriSurface \
-    -ldynamicMesh
+    -ldynamicMesh \
+    -lsampling
diff --git a/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/files b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..83b77fdc77ee07fc46cfc37752b42d613bce8154
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/files
@@ -0,0 +1,2 @@
+cellSizeAndAlignmentGrid.C
+EXE = $(FOAM_USER_APPBIN)/cellSizeAndAlignmentGrid
diff --git a/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/options b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..31d0d80858fad570a1809d938b72a86a074ab71b
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/Make/options
@@ -0,0 +1,40 @@
+EXE_DEBUG = -DFULLDEBUG -g -O0
+EXE_FROUNDING_MATH = -frounding-math
+EXE_NDEBUG = -DNDEBUG
+
+CGAL_EXACT = /*-DCGAL_DONT_USE_LAZY_KERNEL*/
+CGAL_INEXACT = -DCGAL_INEXACT
+
+include $(GENERAL_RULES)/CGAL
+
+
+EXE_INC =  \
+    ${EXE_FROUNDING_MATH} \
+    ${EXE_NDEBUG} \
+    ${CGAL_INEXACT} \
+    ${CGAL_INC} \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/dynamicMesh/lnInclude \
+    -I$(LIB_SRC)/triSurface/lnInclude \
+    -I$(LIB_SRC)/fileFormats/lnInclude \
+    -I$(LIB_SRC)/sampling/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
+    -I$(LIB_SRC)/edgeMesh/lnInclude \
+    -I$(HOME)/OpenFOAM/OpenFOAM-dev/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/lnInclude \
+    -I$(HOME)/OpenFOAM/OpenFOAM-dev/applications/utilities/mesh/generation/cvMesh/vectorTools
+
+EXE_LIBS =  \
+    $(CGAL_LIBS) \
+    -lmpfr \
+    -lboost_thread \
+    -lconformalVoronoiMesh \
+    -lfiniteVolume    \
+    -lmeshTools \
+    -ldecompositionMethods \
+    -L$(FOAM_LIBBIN)/dummy -lptscotchDecomp \
+    -ledgeMesh \
+    -ltriSurface \
+    -ldynamicMesh \
+    -lsampling \
+    -lfileFormats
diff --git a/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/cellSizeAndAlignmentGrid.C b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/cellSizeAndAlignmentGrid.C
new file mode 100644
index 0000000000000000000000000000000000000000..27cc47f823f28099c7b0f30f0319d1893449ab73
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/cellSizeAndAlignmentGrid/cellSizeAndAlignmentGrid.C
@@ -0,0 +1,711 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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
+    Test-distributedDelaunayMesh
+
+Description
+
+\*---------------------------------------------------------------------------*/
+
+#include "CGALTriangulation3DKernel.H"
+
+#include "indexedVertex.H"
+#include "indexedCell.H"
+
+#include "argList.H"
+#include "Time.H"
+#include "DistributedDelaunayMesh.H"
+#include "backgroundMeshDecomposition.H"
+#include "searchableSurfaces.H"
+#include "conformationSurfaces.H"
+#include "PrintTable.H"
+#include "Random.H"
+#include "boundBox.H"
+#include "point.H"
+#include "cellShapeControlMesh.H"
+#include "triadField.H"
+#include "scalarIOField.H"
+#include "pointIOField.H"
+#include "triadIOField.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+template <class Triangulation, class Type>
+Foam::tmp<Foam::Field<Type> > filterFarPoints
+(
+    const Triangulation& mesh,
+    const Field<Type>& field
+)
+{
+    tmp<Field<Type> > tNewField(new Field<Type>(field.size()));
+    Field<Type>& newField = tNewField();
+
+    label added = 0;
+    label count = 0;
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            newField[added++] = field[count];
+        }
+
+        count++;
+    }
+
+    newField.resize(added);
+
+    return tNewField;
+}
+
+
+template <class T>
+autoPtr<mapDistribute> buildMap
+(
+    const T& mesh,
+    labelListList& pointPoints
+)
+{
+    pointPoints.setSize(mesh.vertexCount());
+
+    globalIndex globalIndexing(mesh.vertexCount());
+
+    for
+    (
+        typename T::Finite_vertices_iterator vit = mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        std::list<typename T::Vertex_handle> adjVerts;
+        mesh.finite_adjacent_vertices(vit, std::back_inserter(adjVerts));
+
+        DynamicList<label> indices(adjVerts.size());
+
+        for
+        (
+            typename std::list<typename T::Vertex_handle>::const_iterator
+                adjVertI = adjVerts.begin();
+            adjVertI != adjVerts.end();
+            ++adjVertI
+        )
+        {
+            typename T::Vertex_handle vh = *adjVertI;
+
+            if (!vh->farPoint())
+            {
+                indices.append
+                (
+                    globalIndexing.toGlobal(vh->procIndex(), vh->index())
+                );
+            }
+        }
+
+        pointPoints[vit->index()].transfer(indices);
+    }
+
+    List<Map<label> > compactMap;
+
+    return autoPtr<mapDistribute>
+    (
+        new mapDistribute
+        (
+            globalIndexing,
+            pointPoints,
+            compactMap
+        )
+    );
+}
+
+
+template <class T>
+Foam::tmp<Foam::triadField> buildAlignmentField(const T& mesh)
+{
+    tmp<triadField> tAlignments
+    (
+        new triadField(mesh.vertexCount(), triad::unset)
+    );
+    triadField& alignments = tAlignments();
+
+    for
+    (
+        typename T::Finite_vertices_iterator vit = mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        alignments[vit->index()] = triad
+        (
+            vit->alignment().x(),
+            vit->alignment().y(),
+            vit->alignment().z()
+        );
+    }
+
+    return tAlignments;
+}
+
+
+template <class T>
+Foam::tmp<Foam::pointField> buildPointField(const T& mesh)
+{
+    tmp<pointField> tPoints
+    (
+        new pointField(mesh.vertexCount(), point(GREAT, GREAT, GREAT))
+    );
+    pointField& points = tPoints();
+
+    for
+    (
+        typename T::Finite_vertices_iterator vit = mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        points[vit->index()] = topoint(vit->point());
+    }
+
+    return tPoints;
+}
+
+
+int main(int argc, char *argv[])
+{
+    #include "setRootCase.H"
+    #include "createTime.H"
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    label maxRefinementIterations = 0;
+    label maxSmoothingIterations = 200;
+    scalar minResidual = 0;
+    scalar defaultCellSize = 0.0004;
+    scalar nearFeatDistSqrCoeff = 1e-8;
+
+
+    // Need to decouple vertex and cell type from this class?
+    // Vertex must have:
+    // + index
+    // + procIndex
+    // - type should be optional
+    cellShapeControlMesh mesh(runTime);
+
+    IOdictionary cvMeshDict
+    (
+        IOobject
+        (
+            "cvMeshDict",
+            runTime.system(),
+            runTime,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE
+        )
+    );
+
+    Random rndGen(64293*Pstream::myProcNo());
+
+    searchableSurfaces allGeometry
+    (
+        IOobject
+        (
+            "cvSearchableSurfaces",
+            runTime.constant(),
+            "triSurface",
+            runTime,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE
+        ),
+        cvMeshDict.subDict("geometry")
+    );
+
+    conformationSurfaces geometryToConformTo
+    (
+        runTime,
+        rndGen,
+        allGeometry,
+        cvMeshDict.subDict("surfaceConformation")
+    );
+
+    autoPtr<backgroundMeshDecomposition> bMesh;
+    if (Pstream::parRun())
+    {
+        bMesh.set
+        (
+            new backgroundMeshDecomposition
+            (
+                runTime,
+                rndGen,
+                geometryToConformTo,
+                cvMeshDict.subDict("backgroundMeshDecomposition")
+            )
+        );
+    }
+
+    // Nice to have IO for the delaunay mesh
+    // IO depend on vertex type.
+    //
+    // Define a delaunay mesh as:
+    // + list of points of the triangulation
+    // + optionally a list of cells
+
+    Info<< nl << "Loop over surfaces" << endl;
+
+    forAll(geometryToConformTo.surfaces(), sI)
+    {
+        const label surfI = geometryToConformTo.surfaces()[sI];
+
+        const searchableSurface& surface =
+            geometryToConformTo.geometry()[surfI];
+
+        Info<< nl << "Inserting points from surface " << surface.name()
+            << " (" << surface.type() << ")" << endl;
+
+        const tmp<pointField> tpoints = surface.points();
+        const pointField& points = tpoints();
+
+        Info<< "    Number of points = " << points.size() << endl;
+
+        forAll(points, pI)
+        {
+            // Is the point in the extendedFeatureEdgeMesh? If so get the
+            // point normal, otherwise get the surface normal from
+            // searchableSurface
+
+            pointIndexHit info;
+            label infoFeature;
+            geometryToConformTo.findFeaturePointNearest
+            (
+                points[pI],
+                nearFeatDistSqrCoeff,
+                info,
+                infoFeature
+            );
+
+
+            autoPtr<triad> pointAlignment;
+
+            if (info.hit())
+            {
+                const extendedFeatureEdgeMesh& features =
+                    geometryToConformTo.features()[infoFeature];
+
+                vectorField norms = features.featurePointNormals(info.index());
+
+                // Create a triad from these norms.
+                pointAlignment.set(new triad());
+                forAll(norms, nI)
+                {
+                    pointAlignment() += norms[nI];
+                }
+
+                pointAlignment().normalize();
+                pointAlignment().orthogonalize();
+            }
+            else
+            {
+                geometryToConformTo.findEdgeNearest
+                (
+                    points[pI],
+                    nearFeatDistSqrCoeff,
+                    info,
+                    infoFeature
+                );
+
+                if (info.hit())
+                {
+                    const extendedFeatureEdgeMesh& features =
+                        geometryToConformTo.features()[infoFeature];
+
+                    vectorField norms = features.edgeNormals(info.index());
+
+                    // Create a triad from these norms.
+                    pointAlignment.set(new triad());
+                    forAll(norms, nI)
+                    {
+                        pointAlignment() += norms[nI];
+                    }
+
+                    pointAlignment().normalize();
+                    pointAlignment().orthogonalize();
+                }
+                else
+                {
+                    pointField ptField(1, points[pI]);
+                    scalarField distField(1, nearFeatDistSqrCoeff);
+                    List<pointIndexHit> infoList(1, pointIndexHit());
+
+                    surface.findNearest(ptField, distField, infoList);
+
+                    vectorField normals(1);
+                    surface.getNormal(infoList, normals);
+
+                    pointAlignment.set(new triad(normals[0]));
+                }
+            }
+
+            if (Pstream::parRun())
+            {
+                if (bMesh().positionOnThisProcessor(points[pI]))
+                {
+                    CellSizeDelaunay::Vertex_handle vh = mesh.insert
+                    (
+                        points[pI],
+                        defaultCellSize,
+                        pointAlignment()
+                    );
+                }
+            }
+            else
+            {
+                CellSizeDelaunay::Vertex_handle vh = mesh.insert
+                (
+                    points[pI],
+                    defaultCellSize,
+                    pointAlignment()
+                );
+            }
+        }
+    }
+
+
+    for (label iter = 0; iter < maxRefinementIterations; ++iter)
+    {
+        DynamicList<point> ptsToInsert;
+
+        for
+        (
+            CellSizeDelaunay::Finite_cells_iterator cit =
+                mesh.finite_cells_begin();
+            cit != mesh.finite_cells_end();
+            ++cit
+        )
+        {
+            const point newPoint =
+                topoint
+                (
+                    CGAL::centroid
+                    (
+                        cit->vertex(0)->point(),
+                        cit->vertex(1)->point(),
+                        cit->vertex(2)->point(),
+                        cit->vertex(3)->point()
+                    )
+                );
+
+            if (geometryToConformTo.inside(newPoint))
+            {
+                ptsToInsert.append(newPoint);
+            }
+        }
+
+        Info<< "    Adding " << returnReduce(ptsToInsert.size(), sumOp<label>())
+            << endl;
+
+        forAll(ptsToInsert, ptI)
+        {
+            mesh.insert
+            (
+                ptsToInsert[ptI],
+                defaultCellSize,
+                triad::unset
+            );
+        }
+    }
+
+
+    if (Pstream::parRun())
+    {
+        mesh.distribute(bMesh);
+    }
+
+    labelListList pointPoints;
+    autoPtr<mapDistribute> meshDistributor = buildMap(mesh, pointPoints);
+
+    triadField alignments = buildAlignmentField(mesh);
+    pointField points = buildPointField(mesh);
+
+    mesh.printInfo(Info);
+
+
+    // Setup the sizes and alignments on each point
+    triadField fixedAlignments(mesh.vertexCount(), triad::unset);
+
+    for
+    (
+        CellSizeDelaunay::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            const tensor& alignment = vit->alignment();
+
+            fixedAlignments[vit->index()] = triad
+            (
+                alignment.x(),
+                alignment.y(),
+                alignment.z()
+            );
+        }
+    }
+
+
+    Info<< nl << "Smoothing alignments" << endl;
+
+    for (label iter = 0; iter < maxSmoothingIterations; iter++)
+    {
+        Info<< "Iteration " << iter;
+
+        meshDistributor().distribute(points);
+        meshDistributor().distribute(alignments);
+
+        scalar residual = 0;
+
+        triadField triadAv(alignments.size(), triad::unset);
+
+        forAll(pointPoints, pI)
+        {
+            const labelList& pPoints = pointPoints[pI];
+
+            if (pPoints.empty())
+            {
+                continue;
+            }
+
+            const triad& oldTriad = alignments[pI];
+            triad& newTriad = triadAv[pI];
+
+            forAll(pPoints, adjPointI)
+            {
+                const label adjPointIndex = pPoints[adjPointI];
+
+                scalar dist = mag(points[pI] - points[adjPointIndex]);
+
+                dist = max(dist, SMALL);
+
+                triad tmpTriad = alignments[adjPointIndex];
+
+                for (direction dir = 0; dir < 3; dir++)
+                {
+                    if (tmpTriad.set(dir))
+                    {
+                        tmpTriad[dir] *= (1.0/dist);
+                    }
+                }
+
+                newTriad += tmpTriad;
+            }
+
+            newTriad.normalize();
+            newTriad.orthogonalize();
+            newTriad = newTriad.sortxyz();
+
+            // Enforce the boundary conditions
+            const triad& fixedAlignment = fixedAlignments[pI];
+
+            label nFixed = 0;
+
+            forAll(fixedAlignment, dirI)
+            {
+                if (fixedAlignment[dirI] != triad::unset[dirI])
+                {
+                    nFixed++;
+                }
+            }
+
+            if (nFixed == 1)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad.align(fixedAlignment[dirI]);
+                    }
+                }
+            }
+            else if (nFixed == 2)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad[dirI] = fixedAlignment[dirI];
+                    }
+                    else
+                    {
+                        newTriad[dirI] = triad::unset[dirI];
+                    }
+                }
+
+                newTriad.orthogonalize();
+            }
+            else if (nFixed == 3)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad[dirI] = fixedAlignment[dirI];
+                    }
+                }
+            }
+
+            if (newTriad.set(vector::X) && oldTriad.set(vector::X))
+            {
+                scalar dotProd = (oldTriad.x() & newTriad.x());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+            if (newTriad.set(vector::Y) && oldTriad.set(vector::Y))
+            {
+                scalar dotProd = (oldTriad.y() & newTriad.y());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+            if (newTriad.set(vector::Z) && oldTriad.set(vector::Z))
+            {
+                scalar dotProd = (oldTriad.z() & newTriad.z());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+        }
+
+        forAll(alignments, pI)
+        {
+            alignments[pI] = triadAv[pI].sortxyz();
+        }
+
+        reduce(residual, sumOp<scalar>());
+
+        Info<< ", Residual = " << residual << endl;
+
+        if (residual <= minResidual)
+        {
+            break;
+        }
+    }
+
+
+    // Write alignments to a .obj file
+    OFstream str(runTime.path()/"alignments.obj");
+
+    forAll(alignments, pI)
+    {
+        const triad& tri = alignments[pI];
+
+        if (tri.set())
+        {
+            forAll(tri, dirI)
+            {
+                meshTools::writeOBJ(str, points[pI], tri[dirI] + points[pI]);
+            }
+        }
+    }
+
+
+    // Remove the far points
+    pointIOField pointsIO
+    (
+        IOobject
+        (
+            "points",
+            runTime.constant(),
+            runTime,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        filterFarPoints(mesh, points)
+    );
+
+    scalarField sizes(points.size(), defaultCellSize);
+    scalarIOField sizesIO
+    (
+        IOobject
+        (
+            "sizes",
+            runTime.constant(),
+            runTime,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        filterFarPoints(mesh, sizes)
+    );
+
+    triadIOField alignmentsIO
+    (
+        IOobject
+        (
+            "alignments",
+            runTime.constant(),
+            runTime,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        filterFarPoints(mesh, alignments)
+    );
+
+    pointsIO.write();
+    sizesIO.write();
+    alignmentsIO.write();
+
+    Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
+        << "  ClockTime = " << runTime.elapsedClockTime() << " s"
+        << nl << endl;
+
+    Info<< "\nEnd\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/checkCvMesh/meshQualityDict b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/meshQualityDict
new file mode 100644
index 0000000000000000000000000000000000000000..fa5319e087c5e36fe7c3cd93d3a69d5ebc75463e
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/meshQualityDict
@@ -0,0 +1,73 @@
+/*--------------------------------*- 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          meshQualityDict;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- Maximum non-orthogonality allowed. Set to 180 to disable.
+maxNonOrtho         65;
+
+//- Max skewness allowed. Set to <0 to disable.
+maxBoundarySkewness 50;
+maxInternalSkewness 10;
+
+//- Max concaveness allowed. Is angle (in degrees) below which concavity
+//  is allowed. 0 is straight face, <0 would be convex face.
+//  Set to 180 to disable.
+maxConcave          80;
+
+//- Minimum quality of the tet formed by the face-centre
+//  and variable base point minimum decomposition triangles and
+//  the cell centre. This has to be a positive number for tracking
+//  to work. Set to very negative number (e.g. -1E30) to
+//  disable.
+//     <0 = inside out tet,
+//      0 = flat tet
+//      1 = regular tet
+minTetQuality       1e-30;
+
+//- Minimum pyramid volume. Is absolute volume of cell pyramid.
+//  Set to a sensible fraction of the smallest cell volume expected.
+//  Set to very negative number (e.g. -1E30) to disable.
+minVol              1e-20;
+
+//- Minimum face area. Set to <0 to disable.
+minArea             -1;
+
+//- Minimum face twist. Set to <-1 to disable. dot product of face normal
+//- and face centre triangles normal
+minTwist            0.001;
+
+//- minimum normalised cell determinant
+//- 1 = hex, <= 0 = folded or flattened illegal cell
+minDeterminant      0.001;
+
+//- minFaceWeight (0 -> 0.5)
+minFaceWeight       0.02;
+
+//- minVolRatio (0 -> 1)
+minVolRatio         0.01;
+
+//must be >0 for Fluent compatibility
+minTriangleTwist    -1;
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..a0327ce04f9b5e7b7cc622a0190115b6d21f7be7
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.C
@@ -0,0 +1,233 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "DelaunayMesh.H"
+#include "labelPair.H"
+#include "PrintTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+Foam::DelaunayMesh<Triangulation>::DelaunayMesh()
+:
+    Triangulation(),
+    vertexCount_(0),
+    cellCount_(0)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+Foam::DelaunayMesh<Triangulation>::~DelaunayMesh()
+{}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::reset()
+{
+    Info<< "Clearing triangulation" << endl;
+
+    this->clear();
+
+    resetVertexCount();
+    resetCellCount();
+}
+
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::insertPoints(const List<Vb>& vertices)
+{
+    rangeInsertWithInfo
+    (
+        vertices.begin(),
+        vertices.end(),
+        true
+    );
+}
+
+
+template<class Triangulation>
+bool Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_x_3::
+operator()
+(
+    const Point_3& p,
+    const Point_3& q
+) const
+{
+    return typename Gt::Less_x_3()(*(p.first), *(q.first));
+}
+
+template<class Triangulation>
+bool Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_y_3::
+operator()
+(
+    const Point_3& p,
+    const Point_3& q
+) const
+{
+    return typename Gt::Less_y_3()(*(p.first), *(q.first));
+}
+
+template<class Triangulation>
+bool Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_z_3::
+operator()
+(
+    const Point_3& p,
+    const Point_3& q
+) const
+{
+    return typename Gt::Less_z_3()(*(p.first), *(q.first));
+}
+
+template<class Triangulation>
+typename Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_x_3
+Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::less_x_3_object()
+const
+{
+    return Less_x_3();
+}
+
+template<class Triangulation>
+typename Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_y_3
+Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::less_y_3_object()
+const
+{
+    return Less_y_3();
+}
+
+template<class Triangulation>
+typename Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::Less_z_3
+Foam::DelaunayMesh<Triangulation>::Traits_for_spatial_sort::less_z_3_object()
+const
+{
+    return Less_z_3();
+}
+
+
+template<class Triangulation>
+template<class PointIterator>
+void Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
+(
+    PointIterator begin,
+    PointIterator end,
+    bool printErrors
+)
+{
+    typedef DynamicList
+    <
+        std::pair
+        <
+            const typename Triangulation::Point*,
+            label
+        >
+    > vectorPairPointIndex;
+
+    vectorPairPointIndex points;
+
+    label count = 0;
+    for (PointIterator it = begin; it != end; ++it)
+    {
+        points.append
+        (
+            std::make_pair(&(it->point()), count++)
+        );
+    }
+
+    std::random_shuffle(points.begin(), points.end());
+
+    spatial_sort
+    (
+        points.begin(),
+        points.end(),
+        Traits_for_spatial_sort()
+    );
+
+    Vertex_handle hint;
+
+    for
+    (
+        typename vectorPairPointIndex::const_iterator p = points.begin();
+        p != points.end();
+        ++p
+    )
+    {
+        const size_t checkInsertion = Triangulation::number_of_vertices();
+
+        hint = this->insert(*(p->first), hint);
+
+        const Vb& vert = *(begin + p->second);
+
+        if (checkInsertion != Triangulation::number_of_vertices() - 1)
+        {
+            if (printErrors)
+            {
+                Vertex_handle nearV =
+                    Triangulation::nearest_vertex(*(p->first));
+
+                Pout<< "Failed insertion : " << vert.info()
+                    << "         nearest : " << nearV->info();
+            }
+        }
+        else
+        {
+            hint->index() = getNewVertexIndex();
+            hint->type() = vert.type();
+            hint->procIndex() = vert.procIndex();
+            hint->targetCellSize() = vert.targetCellSize();
+            hint->alignment() = vert.alignment();
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "DelaunayMeshIO.C"
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..bdeee880e78e1b5bfc9fdf6b0ae7050c915453eb
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMesh.H
@@ -0,0 +1,238 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::DelaunayMesh
+
+Description
+    The vertex and cell classes must have an index defined
+
+SourceFiles
+    DelaunayMeshI.H
+    DelaunayMesh.C
+    DelaunayMeshIO.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef DelaunayMesh_H
+#define DelaunayMesh_H
+
+#include "Pair.H"
+#include "HashSet.H"
+#include "FixedList.H"
+#include "boundBox.H"
+#include "indexedVertex.H"
+#include "CGALTriangulation3Ddefs.H"
+#include "autoPtr.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class fvMesh;
+
+/*---------------------------------------------------------------------------*\
+                        Class DelaunayMesh Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Triangulation>
+class DelaunayMesh
+:
+    public Triangulation
+{
+public:
+
+        typedef typename Triangulation::Cell_handle Cell_handle;
+        typedef typename Triangulation::Vertex_handle Vertex_handle;
+        typedef typename Triangulation::Point Point;
+        typedef typename Triangulation::Facet Facet;
+
+        typedef typename Triangulation::Finite_vertices_iterator
+            Finite_vertices_iterator;
+        typedef typename Triangulation::Finite_cells_iterator
+            Finite_cells_iterator;
+        typedef typename Triangulation::Finite_facets_iterator
+            Finite_facets_iterator;
+
+        typedef HashSet
+        <
+           Pair<label>,
+           FixedList<label, 2>::Hash<>
+        > labelPairHashSet;
+
+
+private:
+
+    // Private data
+
+        //- Keep track of the number of vertices that have been added.
+        //  This allows a unique index to be assigned to each vertex.
+        mutable label vertexCount_;
+
+        //- Keep track of the number of cells that have been added.
+        //  This allows a unique index to be assigned to each cell.
+        mutable label cellCount_;
+
+        //- Spatial sort traits to use with a pair of point pointers and an int.
+        //  Taken from a post on the CGAL lists: 2010-01/msg00004.html by
+        //  Sebastien Loriot (Geometry Factory).
+        struct Traits_for_spatial_sort
+        :
+            public Triangulation::Geom_traits
+        {
+            typedef typename Triangulation::Geom_traits Gt;
+
+            typedef std::pair<const typename Triangulation::Point*, int>
+                Point_3;
+
+            struct Less_x_3
+            {
+                bool operator()(const Point_3& p, const Point_3& q) const;
+            };
+
+            struct Less_y_3
+            {
+                bool operator()(const Point_3& p, const Point_3& q) const;
+            };
+
+            struct Less_z_3
+            {
+                bool operator()(const Point_3& p, const Point_3& q) const;
+            };
+
+            Less_x_3 less_x_3_object() const;
+            Less_y_3 less_y_3_object() const;
+            Less_z_3 less_z_3_object() const;
+        };
+
+
+    // Private Member Functions
+
+        void sortFaces
+        (
+            faceList& faces,
+            labelList& owner,
+            labelList& neighbour
+        ) const;
+
+        void addPatches
+        (
+            const label nInternalFaces,
+            faceList& faces,
+            labelList& owner,
+            labelList& patchSizes,
+            labelList& patchStarts,
+            const List<DynamicList<face> >& patchFaces,
+            const List<DynamicList<label> >& patchOwners
+        ) const;
+
+        //- Disallow default bitwise copy construct
+        DelaunayMesh(const DelaunayMesh<Triangulation>&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const DelaunayMesh<Triangulation>&);
+
+
+public:
+
+    // Constructors
+
+        //- Construct from components
+        DelaunayMesh();
+
+
+    //- Destructor
+    ~DelaunayMesh();
+
+
+    // Member Functions
+
+        inline label getNewVertexIndex() const;
+
+        inline label getNewCellIndex() const;
+
+        inline label cellCount() const;
+
+        inline void resetCellCount();
+
+        inline label vertexCount() const;
+
+        inline void resetVertexCount();
+
+
+        //- Remove the entire triangulation
+        void reset();
+
+        void insertPoints(const List<Vb>& vertices);
+
+        //- Function inserting points into a triangulation and setting the
+        //  index and type data of the point in the correct order. This is
+        //  faster than inserting points individually.
+        //
+        //  Adapted from a post on the CGAL lists: 2010-01/msg00004.html by
+        //  Sebastien Loriot (Geometry Factory).
+        template<class PointIterator>
+        void rangeInsertWithInfo
+        (
+            PointIterator begin,
+            PointIterator end,
+            bool printErrors = true
+        );
+
+
+    // Queries
+
+        void printInfo(Ostream& os) const;
+
+        //- Create an fvMesh from the triangulation.
+        //  The mesh is not parallel consistent - only used for viewing
+        autoPtr<fvMesh> createMesh
+        (
+            const fileName& name,
+            const Time& runTime,
+            labelList& vertexMap,
+            labelList& cellMap
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "DelaunayMeshI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "DelaunayMesh.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshI.H
new file mode 100644
index 0000000000000000000000000000000000000000..841e5c9024b5954e80a897148c00e4c3bfea3e4e
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshI.H
@@ -0,0 +1,119 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Triangulation>
+inline Foam::label Foam::DelaunayMesh<Triangulation>::getNewVertexIndex() const
+{
+    label id = vertexCount_++;
+
+    if (id == labelMax)
+    {
+        WarningIn
+        (
+            "Foam::DelaunayMesh<Triangulation>::getNewVertexIndex() const"
+        )   << "Vertex counter has overflowed." << endl;
+    }
+
+    return id;
+}
+
+
+template<class Triangulation>
+inline Foam::label Foam::DelaunayMesh<Triangulation>::getNewCellIndex() const
+{
+    label id = cellCount_++;
+
+    if (id == labelMax)
+    {
+        WarningIn
+        (
+            "Foam::DelaunayMesh<Triangulation>::getNewCellIndex() const"
+        )   << "Cell counter has overflowed." << endl;
+    }
+
+    return id;
+}
+
+
+template<class Triangulation>
+Foam::label Foam::DelaunayMesh<Triangulation>::cellCount() const
+{
+    return cellCount_;
+}
+
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::resetCellCount()
+{
+    cellCount_ = 0;
+}
+
+
+template<class Triangulation>
+Foam::label Foam::DelaunayMesh<Triangulation>::vertexCount() const
+{
+    return vertexCount_;
+}
+
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::resetVertexCount()
+{
+    vertexCount_ = 0;
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * Ostream Operator  * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C
new file mode 100644
index 0000000000000000000000000000000000000000..4cf7077657d90395a70e2bb694098657dded95fe
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DelaunayMeshIO.C
@@ -0,0 +1,406 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "DelaunayMesh.H"
+#include "fvMesh.H"
+#include "pointConversion.H"
+#include "wallPolyPatch.H"
+#include "processorPolyPatch.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::sortFaces
+(
+    faceList& faces,
+    labelList& owner,
+    labelList& neighbour
+) const
+{
+    // Upper triangular order:
+    // + owner is sorted in ascending cell order
+    // + within each block of equal value for owner, neighbour is sorted in
+    //   ascending cell order.
+    // + faces sorted to correspond
+    // e.g.
+    // owner | neighbour
+    // 0     | 2
+    // 0     | 23
+    // 0     | 71
+    // 1     | 23
+    // 1     | 24
+    // 1     | 91
+
+    List<labelPair> ownerNeighbourPair(owner.size());
+
+    forAll(ownerNeighbourPair, oNI)
+    {
+        ownerNeighbourPair[oNI] = labelPair(owner[oNI], neighbour[oNI]);
+    }
+
+    Info<< nl
+        << "Sorting faces, owner and neighbour into upper triangular order"
+        << endl;
+
+    labelList oldToNew;
+
+    sortedOrder(ownerNeighbourPair, oldToNew);
+
+    oldToNew = invert(oldToNew.size(), oldToNew);
+
+    inplaceReorder(oldToNew, faces);
+    inplaceReorder(oldToNew, owner);
+    inplaceReorder(oldToNew, neighbour);
+}
+
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::addPatches
+(
+    const label nInternalFaces,
+    faceList& faces,
+    labelList& owner,
+    labelList& patchSizes,
+    labelList& patchStarts,
+    const List<DynamicList<face> >& patchFaces,
+    const List<DynamicList<label> >& patchOwners
+) const
+{
+    label nPatches = patchFaces.size();
+
+    patchSizes.setSize(nPatches, -1);
+    patchStarts.setSize(nPatches, -1);
+
+    label nBoundaryFaces = 0;
+
+    forAll(patchFaces, p)
+    {
+        patchSizes[p] = patchFaces[p].size();
+        patchStarts[p] = nInternalFaces + nBoundaryFaces;
+
+        nBoundaryFaces += patchSizes[p];
+    }
+
+    faces.setSize(nInternalFaces + nBoundaryFaces);
+    owner.setSize(nInternalFaces + nBoundaryFaces);
+
+    label faceI = nInternalFaces;
+
+    forAll(patchFaces, p)
+    {
+        forAll(patchFaces[p], f)
+        {
+            faces[faceI] = patchFaces[p][f];
+            owner[faceI] = patchOwners[p][f];
+
+            faceI++;
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+//template<class Triangulation>
+//Foam::DelaunayMesh<Triangulation>::DelaunayMesh(Istream& is)
+//:
+//    base1(is),
+//    base2(is),
+//    member1(is),
+//    member2(is)
+//{
+//    // Check state of Istream
+//    is.check("Foam::DelaunayMesh<Triangulation>::DelaunayMesh(Foam::Istream&)");
+//}
+
+
+// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+void Foam::DelaunayMesh<Triangulation>::printInfo(Ostream& os) const
+{
+    PrintTable<word, label> triInfoTable("Mesh Statistics");
+
+    triInfoTable.add("Points", Triangulation::number_of_vertices());
+    triInfoTable.add("Edges", Triangulation::number_of_finite_edges());
+    triInfoTable.add("Faces", Triangulation::number_of_finite_facets());
+    triInfoTable.add("Cells", Triangulation::number_of_finite_cells());
+
+    scalar minSize = GREAT;
+    scalar maxSize = 0;
+
+    for
+    (
+        Finite_vertices_iterator vit = Triangulation::finite_vertices_begin();
+        vit != Triangulation::finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->farPoint())
+        {
+            minSize = min(vit->targetCellSize(), minSize);
+            maxSize = max(vit->targetCellSize(), maxSize);
+        }
+    }
+
+    Info<< incrIndent;
+    triInfoTable.print(Info, true, true);
+
+    Info<< "Size (Min/Max) = "
+        << returnReduce(minSize, minOp<scalar>()) << " "
+        << returnReduce(maxSize, maxOp<scalar>()) << endl;
+
+    Info<< decrIndent;
+}
+
+
+template<class Triangulation>
+Foam::autoPtr<Foam::fvMesh>
+Foam::DelaunayMesh<Triangulation>::createMesh
+(
+    const fileName& name,
+    const Time& runTime,
+    labelList& vertexMap,
+    labelList& cellMap
+) const
+{
+    pointField points(Triangulation::number_of_vertices());
+    faceList faces(Triangulation::number_of_finite_facets());
+    labelList owner(Triangulation::number_of_finite_facets());
+    labelList neighbour(Triangulation::number_of_finite_facets());
+
+    wordList patchNames(1, "cvMesh_defaultPatch");
+    wordList patchTypes(1, wallPolyPatch::typeName);
+
+    labelList patchSizes(1, 0);
+    labelList patchStarts(1, 0);
+
+    List<DynamicList<face> > patchFaces(1, DynamicList<face>());
+    List<DynamicList<label> > patchOwners(1, DynamicList<label>());
+
+    vertexMap.setSize(Triangulation::number_of_vertices());
+    cellMap.setSize(Triangulation::number_of_finite_cells());
+
+    // Calculate pts and a map of point index to location in pts.
+    label vertI = 0;
+
+    for
+    (
+        Finite_vertices_iterator vit = Triangulation::finite_vertices_begin();
+        vit != Triangulation::finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->farPoint())
+        {
+            vertexMap[vit->index()] = vertI;
+            points[vertI] = topoint(vit->point());
+            vertI++;
+        }
+    }
+
+    points.setSize(vertI);
+
+    // Index the cells
+    label cellI = 0;
+
+    for
+    (
+        Finite_cells_iterator cit = Triangulation::finite_cells_begin();
+        cit != Triangulation::finite_cells_end();
+        ++cit
+    )
+    {
+        if
+        (
+            !cit->hasFarPoint()
+         && !Triangulation::is_infinite(cit)
+        )
+        {
+            cellMap[cit->cellIndex()] = cellI++;
+        }
+    }
+
+    label faceI = 0;
+    labelList verticesOnTriFace(3, -1);
+    face newFace(verticesOnTriFace);
+
+    for
+    (
+        Finite_facets_iterator fit = Triangulation::finite_facets_begin();
+        fit != Triangulation::finite_facets_end();
+        ++fit
+    )
+    {
+        const Cell_handle c1(fit->first);
+        const int oppositeVertex = fit->second;
+        const Cell_handle c2(c1->neighbor(oppositeVertex));
+
+        label c1I = Cb::ctFar;
+        bool c1Real = false;
+        if (!c1->hasFarPoint() && !Triangulation::is_infinite(c1))
+        {
+            c1I = cellMap[c1->cellIndex()];
+            c1Real = true;
+        }
+
+        label c2I = Cb::ctFar;
+        bool c2Real = false;
+        if (!c2->hasFarPoint() && !Triangulation::is_infinite(c2))
+        {
+            c2I = cellMap[c2->cellIndex()];
+            c2Real = true;
+        }
+
+        if (!c1Real && !c2Real)
+        {
+            // Both tets are outside, skip
+            continue;
+        }
+
+        label ownerCell = -1;
+        label neighbourCell = -1;
+
+        for (label i = 0; i < 3; i++)
+        {
+            verticesOnTriFace[i] = vertexMap
+            [
+                c1->vertex
+                (
+                    Triangulation::vertex_triple_index(oppositeVertex, i)
+                )->index()
+            ];
+        }
+
+        newFace = face(verticesOnTriFace);
+
+        if (!c1Real || !c2Real)
+        {
+            // Boundary face...
+            if (!c1Real)
+            {
+                //... with c1 outside
+                ownerCell = c2I;
+            }
+            else
+            {
+                // ... with c2 outside
+                ownerCell = c1I;
+
+                reverse(newFace);
+            }
+
+            patchFaces[0].append(newFace);
+            patchOwners[0].append(ownerCell);
+        }
+        else
+        {
+            // Internal face...
+            if (c1I < c2I)
+            {
+                // ...with c1 as the ownerCell
+                ownerCell = c1I;
+                neighbourCell = c2I;
+
+                reverse(newFace);
+            }
+            else
+            {
+                // ...with c2 as the ownerCell
+                ownerCell = c2I;
+                neighbourCell = c1I;
+            }
+
+            faces[faceI] = newFace;
+            owner[faceI] = ownerCell;
+            neighbour[faceI] = neighbourCell;
+            faceI++;
+        }
+    }
+
+    faces.setSize(faceI);
+    owner.setSize(faceI);
+    neighbour.setSize(faceI);
+
+    sortFaces(faces, owner, neighbour);
+
+    addPatches
+    (
+        faceI,
+        faces,
+        owner,
+        patchSizes,
+        patchStarts,
+        patchFaces,
+        patchOwners
+    );
+
+    autoPtr<fvMesh> meshPtr
+    (
+        new fvMesh
+        (
+            IOobject
+            (
+                name,
+                runTime.timeName(),
+                runTime,
+                IOobject::NO_READ,
+                IOobject::NO_WRITE
+            ),
+            xferMove(points),
+            xferMove(faces),
+            xferMove(owner),
+            xferMove(neighbour)
+        )
+    );
+
+    List<polyPatch*> patches(patchStarts.size());
+
+    label nValidPatches = 0;
+
+    forAll(patches, p)
+    {
+        patches[nValidPatches] = polyPatch::New
+        (
+            patchTypes[p],
+            patchNames[p],
+            patchSizes[p],
+            patchStarts[p],
+            nValidPatches,
+            meshPtr().boundaryMesh()
+        ).ptr();
+
+        nValidPatches++;
+    }
+
+    patches.setSize(nValidPatches);
+
+    meshPtr().addFvPatches(patches);
+
+    return meshPtr;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..ded70e9529954306363e32415d9cbd6d4f27e0eb
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.C
@@ -0,0 +1,932 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "DistributedDelaunayMesh.H"
+#include "meshSearch.H"
+#include "mapDistribute.H"
+#include "zeroGradientFvPatchFields.H"
+#include "pointConversion.H"
+#include "indexedVertexEnum.H"
+#include "IOmanip.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
+
+template<class Triangulation>
+Foam::autoPtr<Foam::mapDistribute>
+Foam::DistributedDelaunayMesh<Triangulation>::buildMap
+(
+    const List<label>& toProc
+)
+{
+    // Determine send map
+    // ~~~~~~~~~~~~~~~~~~
+
+    // 1. Count
+    labelList nSend(Pstream::nProcs(), 0);
+
+    forAll(toProc, i)
+    {
+        label procI = toProc[i];
+
+        nSend[procI]++;
+    }
+
+    // Send over how many I need to receive
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    labelListList sendSizes(Pstream::nProcs());
+
+    sendSizes[Pstream::myProcNo()] = nSend;
+
+    combineReduce(sendSizes, UPstream::listEq());
+
+    // 2. Size sendMap
+    labelListList sendMap(Pstream::nProcs());
+
+    forAll(nSend, procI)
+    {
+        sendMap[procI].setSize(nSend[procI]);
+
+        nSend[procI] = 0;
+    }
+
+    // 3. Fill sendMap
+    forAll(toProc, i)
+    {
+        label procI = toProc[i];
+
+        sendMap[procI][nSend[procI]++] = i;
+    }
+
+    // Determine receive map
+    // ~~~~~~~~~~~~~~~~~~~~~
+
+    labelListList constructMap(Pstream::nProcs());
+
+    // Local transfers first
+    constructMap[Pstream::myProcNo()] = identity
+    (
+        sendMap[Pstream::myProcNo()].size()
+    );
+
+    label constructSize = constructMap[Pstream::myProcNo()].size();
+
+    forAll(constructMap, procI)
+    {
+        if (procI != Pstream::myProcNo())
+        {
+            label nRecv = sendSizes[procI][Pstream::myProcNo()];
+
+            constructMap[procI].setSize(nRecv);
+
+            for (label i = 0; i < nRecv; i++)
+            {
+                constructMap[procI][i] = constructSize++;
+            }
+        }
+    }
+
+    return autoPtr<mapDistribute>
+    (
+        new mapDistribute
+        (
+            constructSize,
+            sendMap.xfer(),
+            constructMap.xfer()
+        )
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+Foam::DistributedDelaunayMesh<Triangulation>::DistributedDelaunayMesh()
+:
+    DelaunayMesh<Triangulation>(),
+    allBackgroundMeshBounds_()
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+Foam::DistributedDelaunayMesh<Triangulation>::~DistributedDelaunayMesh()
+{}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Triangulation>
+bool Foam::DistributedDelaunayMesh<Triangulation>::distributeBoundBoxes
+(
+    const boundBox& bb
+)
+{
+    allBackgroundMeshBounds_.reset(new List<boundBox>(Pstream::nProcs()));
+
+    // Give the bounds of every processor to every other processor
+    allBackgroundMeshBounds_()[Pstream::myProcNo()] = bb;
+
+    Pstream::gatherList(allBackgroundMeshBounds_());
+    Pstream::scatterList(allBackgroundMeshBounds_());
+
+    return true;
+}
+
+
+template<class Triangulation>
+bool Foam::DistributedDelaunayMesh<Triangulation>::isLocal
+(
+    const Vertex_handle& v
+) const
+{
+    return isLocal(v->procIndex());
+}
+
+
+template<class Triangulation>
+bool Foam::DistributedDelaunayMesh<Triangulation>::isLocal
+(
+    const label localProcIndex
+) const
+{
+    return localProcIndex == Pstream::myProcNo();
+}
+
+
+template<class Triangulation>
+Foam::labelList Foam::DistributedDelaunayMesh<Triangulation>::overlapProcessors
+(
+    const point& centre,
+    const scalar radiusSqr
+) const
+{
+    DynamicList<label> toProc(Pstream::nProcs());
+
+    forAll(allBackgroundMeshBounds_(), procI)
+    {
+        // Test against the bounding box of the processor
+        if
+        (
+            !isLocal(procI)
+         && allBackgroundMeshBounds_()[procI].overlaps(centre, radiusSqr)
+        )
+        {
+            toProc.append(procI);
+        }
+    }
+
+    return toProc;
+}
+
+
+template<class Triangulation>
+bool Foam::DistributedDelaunayMesh<Triangulation>::checkProcBoundaryCell
+(
+    const Cell_handle& cit,
+    Map<labelList>& circumsphereOverlaps
+) const
+{
+    const Foam::point& cc = cit->dual();
+
+    const scalar crSqr = magSqr
+    (
+        cc - topoint(cit->vertex(0)->point())
+    );
+
+    labelList circumsphereOverlap = overlapProcessors
+    (
+        cc,
+        sqr(1.01)*crSqr
+    );
+
+    cit->cellIndex() = this->getNewCellIndex();
+
+    if (!circumsphereOverlap.empty())
+    {
+        circumsphereOverlaps.insert(cit->cellIndex(), circumsphereOverlap);
+
+        return true;
+    }
+
+    return false;
+}
+
+
+template<class Triangulation>
+void Foam::DistributedDelaunayMesh<Triangulation>::findProcessorBoundaryCells
+(
+    Map<labelList>& circumsphereOverlaps
+) const
+{
+    // Start by assuming that all the cells have no index
+    // If they do, they have already been visited so ignore them
+
+    labelHashSet cellToCheck
+    (
+        Triangulation::number_of_finite_cells()
+       /Pstream::nProcs()
+    );
+
+    for
+    (
+        All_cells_iterator cit = Triangulation::all_cells_begin();
+        cit != Triangulation::all_cells_end();
+        ++cit
+    )
+    {
+        if (Triangulation::is_infinite(cit))
+        {
+            // Index of infinite vertex in this cell.
+            int i = cit->index(Triangulation::infinite_vertex());
+
+            Cell_handle c = cit->neighbor(i);
+
+            if (c->unassigned())
+            {
+                c->cellIndex() = this->getNewCellIndex();
+
+                if (checkProcBoundaryCell(c, circumsphereOverlaps))
+                {
+                    cellToCheck.insert(c->cellIndex());
+                }
+            }
+        }
+        else if (cit->parallelDualVertex())
+        {
+            if (cit->unassigned())
+            {
+                if (checkProcBoundaryCell(cit, circumsphereOverlaps))
+                {
+                    cellToCheck.insert(cit->cellIndex());
+                }
+            }
+        }
+    }
+
+    for
+    (
+        Finite_cells_iterator cit = Triangulation::finite_cells_begin();
+        cit != Triangulation::finite_cells_end();
+        ++cit
+    )
+    {
+        if (cellToCheck.found(cit->cellIndex()))
+        {
+            // Get the neighbours and check them
+            for (label adjCellI = 0; adjCellI < 4; ++adjCellI)
+            {
+                Cell_handle citNeighbor = cit->neighbor(adjCellI);
+
+                // Ignore if has far point or previously visited
+                if
+                (
+                    !citNeighbor->unassigned()
+                 || !citNeighbor->internalOrBoundaryDualVertex()
+                 || Triangulation::is_infinite(citNeighbor)
+                )
+                {
+                    continue;
+                }
+
+                checkProcBoundaryCell
+                (
+                    citNeighbor,
+                    circumsphereOverlaps
+                );
+            }
+        }
+    }
+}
+
+
+template<class Triangulation>
+void Foam::DistributedDelaunayMesh<Triangulation>::markVerticesToRefer
+(
+    const Map<labelList>& circumsphereOverlaps,
+    PtrList<labelPairHashSet>& referralVertices,
+    DynamicList<label>& targetProcessor,
+    DynamicList<Vb>& parallelInfluenceVertices
+)
+{
+    // Relying on the order of iteration of cells being the same as before
+    for
+    (
+        Finite_cells_iterator cit = Triangulation::finite_cells_begin();
+        cit != Triangulation::finite_cells_end();
+        ++cit
+    )
+    {
+        if (Triangulation::is_infinite(cit))
+        {
+             continue;
+        }
+
+        Map<labelList>::const_iterator iter =
+            circumsphereOverlaps.find(cit->cellIndex());
+
+        // Pre-tested circumsphere potential influence
+        if (iter != circumsphereOverlaps.cend())
+        {
+            const labelList& citOverlaps = iter();
+
+            forAll(citOverlaps, cOI)
+            {
+                label procI = citOverlaps[cOI];
+
+                for (int i = 0; i < 4; i++)
+                {
+                    Vertex_handle v = cit->vertex(i);
+
+                    if (v->farPoint())
+                    {
+                        continue;
+                    }
+
+                    label vProcIndex = v->procIndex();
+                    label vIndex = v->index();
+
+                    const labelPair procIndexPair(vProcIndex, vIndex);
+
+                    // Using the hashSet to ensure that each vertex is only
+                    // referred once to each processor.
+                    // Do not refer a vertex to its own processor.
+                    if (vProcIndex != procI)
+                    {
+                        if (referralVertices[procI].insert(procIndexPair))
+                        {
+                            targetProcessor.append(procI);
+
+                            parallelInfluenceVertices.append
+                            (
+                                Vb
+                                (
+                                    v->point(),
+                                    v->index(),
+                                    v->type(),
+                                    v->procIndex()
+                                )
+                            );
+
+                            parallelInfluenceVertices.last().targetCellSize() =
+                                v->targetCellSize();
+                            parallelInfluenceVertices.last().alignment() =
+                                v->alignment();
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template<class Triangulation>
+Foam::label Foam::DistributedDelaunayMesh<Triangulation>::referVertices
+(
+    const DynamicList<label>& targetProcessor,
+    DynamicList<Vb>& parallelVertices,
+    PtrList<labelPairHashSet>& referralVertices,
+    labelPairHashSet& receivedVertices
+)
+{
+    DynamicList<Vb> referredVertices(targetProcessor.size());
+
+    const label preDistributionSize = parallelVertices.size();
+
+    mapDistribute pointMap = buildMap(targetProcessor);
+
+    // Make a copy of the original list.
+    DynamicList<Vb> originalParallelVertices(parallelVertices);
+
+    pointMap.distribute(parallelVertices);
+
+    for (label procI = 0; procI < Pstream::nProcs(); procI++)
+    {
+        const labelList& constructMap = pointMap.constructMap()[procI];
+
+        if (constructMap.size())
+        {
+            forAll(constructMap, i)
+            {
+                const Vb& v = parallelVertices[constructMap[i]];
+
+                if
+                (
+                    v.procIndex() != Pstream::myProcNo()
+                 && !receivedVertices.found(labelPair(v.procIndex(), v.index()))
+                )
+                {
+                    referredVertices.append(v);
+
+                    receivedVertices.insert
+                    (
+                        labelPair(v.procIndex(), v.index())
+                    );
+                }
+            }
+        }
+    }
+
+    label preInsertionSize = Triangulation::number_of_vertices();
+
+    labelPairHashSet pointsNotInserted = rangeInsertReferredWithInfo
+    (
+        referredVertices.begin(),
+        referredVertices.end()
+    );
+
+    if (!pointsNotInserted.empty())
+    {
+        for
+        (
+            typename labelPairHashSet::const_iterator iter
+                = pointsNotInserted.begin();
+            iter != pointsNotInserted.end();
+            ++iter
+        )
+        {
+            if (receivedVertices.found(iter.key()))
+            {
+                receivedVertices.erase(iter.key());
+            }
+        }
+    }
+
+    boolList pointInserted(parallelVertices.size(), true);
+
+    forAll(parallelVertices, vI)
+    {
+        const labelPair procIndexI
+        (
+            parallelVertices[vI].procIndex(),
+            parallelVertices[vI].index()
+        );
+
+        if (pointsNotInserted.found(procIndexI))
+        {
+            pointInserted[vI] = false;
+        }
+    }
+
+    pointMap.reverseDistribute(preDistributionSize, pointInserted);
+
+    forAll(originalParallelVertices, vI)
+    {
+        const label procIndex = targetProcessor[vI];
+
+        if (!pointInserted[vI])
+        {
+            if (referralVertices[procIndex].size())
+            {
+                if
+                (
+                    !referralVertices[procIndex].unset
+                    (
+                        labelPair
+                        (
+                            originalParallelVertices[vI].procIndex(),
+                            originalParallelVertices[vI].index()
+                        )
+                    )
+                )
+                {
+                    Pout<< "*** not found "
+                        << originalParallelVertices[vI].procIndex()
+                        << " " << originalParallelVertices[vI].index() << endl;
+                }
+
+            }
+        }
+    }
+
+    label postInsertionSize = Triangulation::number_of_vertices();
+
+    reduce(preInsertionSize, sumOp<label>());
+    reduce(postInsertionSize, sumOp<label>());
+
+    label nTotalToInsert = referredVertices.size();
+
+    reduce(nTotalToInsert, sumOp<label>());
+
+    if (preInsertionSize + nTotalToInsert != postInsertionSize)
+    {
+        label nNotInserted =
+            returnReduce(pointsNotInserted.size(), sumOp<label>());
+
+        Info<< " Inserted = "
+            << setw(name(label(Triangulation::number_of_finite_cells())).size())
+            << nTotalToInsert - nNotInserted
+            << " / " << nTotalToInsert << endl;
+
+        nTotalToInsert -= nNotInserted;
+    }
+    else
+    {
+        Info<< " Inserted = " << nTotalToInsert << endl;
+    }
+
+    return nTotalToInsert;
+}
+
+
+template<class Triangulation>
+void Foam::DistributedDelaunayMesh<Triangulation>::sync
+(
+    const boundBox& bb,
+    PtrList<labelPairHashSet>& referralVertices,
+    labelPairHashSet& receivedVertices,
+    bool iterateReferral
+)
+{
+    if (!Pstream::parRun())
+    {
+        return;
+    }
+
+    if (allBackgroundMeshBounds_.empty())
+    {
+        distributeBoundBoxes(bb);
+    }
+
+    label nVerts = Triangulation::number_of_vertices();
+    label nCells = Triangulation::number_of_finite_cells();
+
+    DynamicList<Vb> parallelInfluenceVertices(0.1*nVerts);
+    DynamicList<label> targetProcessor(0.1*nVerts);
+
+    // Some of these values will not be used, i.e. for non-real cells
+    DynamicList<Foam::point> circumcentre(0.1*nVerts);
+    DynamicList<scalar> circumradiusSqr(0.1*nVerts);
+
+    Map<labelList> circumsphereOverlaps(nCells);
+
+    findProcessorBoundaryCells(circumsphereOverlaps);
+
+    Info<< "    Influences = "
+        << setw(name(nCells).size())
+        << returnReduce(circumsphereOverlaps.size(), sumOp<label>()) << " / "
+        << returnReduce(nCells, sumOp<label>());
+
+    markVerticesToRefer
+    (
+        circumsphereOverlaps,
+        referralVertices,
+        targetProcessor,
+        parallelInfluenceVertices
+    );
+
+    referVertices
+    (
+        targetProcessor,
+        parallelInfluenceVertices,
+        referralVertices,
+        receivedVertices
+    );
+
+    if (iterateReferral)
+    {
+        label oldNReferred = 0;
+        label nIterations = 1;
+
+        Info<< incrIndent << indent
+            << "Iteratively referring referred vertices..."
+            << endl;
+        do
+        {
+            Info<< indent << "Iteration " << nIterations++ << ":";
+
+            circumsphereOverlaps.clear();
+            targetProcessor.clear();
+            parallelInfluenceVertices.clear();
+
+            findProcessorBoundaryCells(circumsphereOverlaps);
+
+            nCells = Triangulation::number_of_finite_cells();
+
+            Info<< " Influences = "
+                << setw(name(nCells).size())
+                << returnReduce(circumsphereOverlaps.size(), sumOp<label>())
+                << " / "
+                << returnReduce(nCells, sumOp<label>());
+
+            markVerticesToRefer
+            (
+                circumsphereOverlaps,
+                referralVertices,
+                targetProcessor,
+                parallelInfluenceVertices
+            );
+
+            label nReferred = referVertices
+            (
+                targetProcessor,
+                parallelInfluenceVertices,
+                referralVertices,
+                receivedVertices
+            );
+
+            if (nReferred == 0 || nReferred == oldNReferred)
+            {
+                break;
+            }
+
+            oldNReferred = nReferred;
+
+        } while (true);
+
+        Info<< decrIndent;
+    }
+}
+
+
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+template<class Triangulation>
+bool Foam::DistributedDelaunayMesh<Triangulation>::distribute
+(
+    const boundBox& bb
+)
+{
+    notImplemented
+    (
+        "Foam::DistributedDelaunayMesh<Triangulation>::distribute"
+        "("
+        "    const boundBox& bb"
+        ")"
+    );
+
+    if (!Pstream::parRun())
+    {
+        return false;
+    }
+
+    distributeBoundBoxes(bb);
+
+    return true;
+}
+
+
+template<class Triangulation>
+Foam::autoPtr<Foam::mapDistribute>
+Foam::DistributedDelaunayMesh<Triangulation>::distribute
+(
+    const backgroundMeshDecomposition& decomposition
+)
+{
+    if (!Pstream::parRun())
+    {
+        return autoPtr<mapDistribute>();
+    }
+
+    distributeBoundBoxes(decomposition.procBounds());
+
+    DynamicList<point> points(Triangulation::number_of_vertices());
+
+    for
+    (
+        Finite_vertices_iterator vit = Triangulation::finite_vertices_begin();
+        vit != Triangulation::finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            points.append(topoint(vit->point()));
+        }
+    }
+
+    autoPtr<mapDistribute> mapDist = decomposition.distributePoints(points);
+
+    return mapDist;
+}
+
+
+template<class Triangulation>
+void Foam::DistributedDelaunayMesh<Triangulation>::sync(const boundBox& bb)
+{
+    if (!Pstream::parRun())
+    {
+        return;
+    }
+
+    if (allBackgroundMeshBounds_.empty())
+    {
+        distributeBoundBoxes(bb);
+    }
+
+    const label nApproxReferred =
+        Triangulation::number_of_vertices()
+       /Pstream::nProcs();
+
+    PtrList<labelPairHashSet> referralVertices(Pstream::nProcs());
+    forAll(referralVertices, procI)
+    {
+        if (!isLocal(procI))
+        {
+            referralVertices.set(procI, new labelPairHashSet(nApproxReferred));
+        }
+    }
+
+    labelPairHashSet receivedVertices(nApproxReferred);
+
+    sync
+    (
+        bb,
+        referralVertices,
+        receivedVertices,
+        true
+    );
+}
+
+
+template<class Triangulation>
+template<class PointIterator>
+typename Foam::DistributedDelaunayMesh<Triangulation>::labelPairHashSet
+Foam::DistributedDelaunayMesh<Triangulation>::rangeInsertReferredWithInfo
+(
+    PointIterator begin,
+    PointIterator end,
+    bool printErrors
+)
+{
+    const boundBox& bb = allBackgroundMeshBounds_()[Pstream::myProcNo()];
+
+    typedef DynamicList
+    <
+        std::pair<scalar, label>
+    > vectorPairPointIndex;
+
+    vectorPairPointIndex pointsBbDistSqr;
+
+    label count = 0;
+    for (PointIterator it = begin; it != end; ++it)
+    {
+        const scalar distFromBbSqr = bb.distanceFromBoxSqr
+        (
+            topoint(it->point())
+        );
+
+        pointsBbDistSqr.append
+        (
+            std::make_pair(distFromBbSqr, count++)
+        );
+    }
+
+    std::random_shuffle(pointsBbDistSqr.begin(), pointsBbDistSqr.end());
+
+    // Sort in ascending order by the distance of the point from the centre
+    // of the processor bounding box
+    sort(pointsBbDistSqr.begin(), pointsBbDistSqr.end());
+
+    typename Triangulation::Vertex_handle hint;
+
+    typename Triangulation::Locate_type lt;
+    int li, lj;
+
+    label nNotInserted = 0;
+
+    labelPairHashSet uninserted
+    (
+        Triangulation::number_of_vertices()
+       /Pstream::nProcs()
+    );
+
+    for
+    (
+        typename vectorPairPointIndex::const_iterator p =
+            pointsBbDistSqr.begin();
+        p != pointsBbDistSqr.end();
+        ++p
+    )
+    {
+        const size_t checkInsertion = Triangulation::number_of_vertices();
+
+        const Vb& vert = *(begin + p->second);
+        const Point& pointToInsert = vert.point();
+
+        // Locate the point
+        Cell_handle c = Triangulation::locate(pointToInsert, lt, li, lj, hint);
+
+        if (lt == Triangulation::VERTEX)
+        {
+            if (printErrors)
+            {
+                Vertex_handle nearV =
+                    Triangulation::nearest_vertex(pointToInsert);
+
+                Pout<< "Failed insertion, point already exists" << nl
+                    << "Failed insertion : " << vert.info()
+                    << "         nearest : " << nearV->info();
+            }
+
+            uninserted.insert(labelPair(vert.procIndex(), vert.index()));
+            nNotInserted++;
+
+            continue;
+        }
+
+        // Get the cells that conflict with p in a vector V,
+        // and a facet on the boundary of this hole in f.
+        std::vector<Cell_handle> V;
+        typename Triangulation::Facet f;
+
+        Triangulation::find_conflicts
+        (
+            pointToInsert,
+            c,
+            CGAL::Oneset_iterator<typename Triangulation::Facet>(f),
+            std::back_inserter(V)
+        );
+
+        bool insert = false;
+        for (size_t i = 0; i < V.size(); ++i)
+        {
+            if (V[i]->real() || V[i]->hasFarPoint())
+            {
+                insert = true;
+                break;
+            }
+        }
+
+        if (insert)
+        {
+            hint = Triangulation::insert_in_hole
+            (
+                pointToInsert,
+                V.begin(),
+                V.end(),
+                f.first,
+                f.second
+            );
+
+            if (checkInsertion != Triangulation::number_of_vertices() - 1)
+            {
+                if (printErrors)
+                {
+                    Vertex_handle nearV =
+                        Triangulation::nearest_vertex(pointToInsert);
+
+                    Pout<< "Failed insertion : " << vert.info()
+                        << "         nearest : " << nearV->info();
+                }
+            }
+            else
+            {
+                hint->index() = vert.index();
+                hint->type() = vert.type();
+                hint->procIndex() = vert.procIndex();
+                hint->targetCellSize() = vert.targetCellSize();
+                hint->alignment() = vert.alignment();
+            }
+        }
+        else
+        {
+            uninserted.insert(labelPair(vert.procIndex(), vert.index()));
+            nNotInserted++;
+        }
+    }
+
+    return uninserted;
+}
+
+
+// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..124f4b39dc1558721662de315c51d50e33584256
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/DelaunayMesh/DistributedDelaunayMesh.H
@@ -0,0 +1,207 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::DistributedDelaunayMesh
+
+Description
+
+SourceFiles
+    DistributedDelaunayMeshI.H
+    DistributedDelaunayMesh.C
+    DistributedDelaunayMeshIO.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef DistributedDelaunayMesh_H
+#define DistributedDelaunayMesh_H
+
+#include "DelaunayMesh.H"
+#include "backgroundMeshDecomposition.H"
+#include "autoPtr.H"
+#include "boundBox.H"
+#include "indexedVertex.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class mapDistribute;
+
+/*---------------------------------------------------------------------------*\
+                  Class DistributedDelaunayMesh Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Triangulation>
+class DistributedDelaunayMesh
+:
+    public DelaunayMesh<Triangulation>
+{
+public:
+
+        typedef typename Triangulation::Vertex_handle Vertex_handle;
+        typedef typename Triangulation::Cell_handle   Cell_handle;
+        typedef typename Triangulation::Point         Point;
+
+        typedef typename Triangulation::Finite_vertices_iterator
+            Finite_vertices_iterator;
+        typedef typename Triangulation::Finite_cells_iterator
+            Finite_cells_iterator;
+        typedef typename Triangulation::All_cells_iterator
+            All_cells_iterator;
+
+        typedef typename DelaunayMesh<Triangulation>::labelPairHashSet
+            labelPairHashSet;
+
+
+private:
+
+        autoPtr<List<boundBox> > allBackgroundMeshBounds_;
+
+
+    // Private Member Functions
+
+        //-
+        bool distributeBoundBoxes(const boundBox& bb);
+
+        //-
+        bool isLocal(const Vertex_handle& v) const;
+
+        bool isLocal(const label localProcIndex) const;
+
+        labelList overlapProcessors
+        (
+            const point& centre,
+            const scalar radiusSqr
+        ) const;
+
+        bool checkProcBoundaryCell
+        (
+            const Cell_handle& cit,
+            Map<labelList>& circumsphereOverlaps
+        ) const;
+
+        void findProcessorBoundaryCells
+        (
+            Map<labelList>& circumsphereOverlaps
+        ) const;
+
+        void markVerticesToRefer
+        (
+            const Map<labelList>& circumsphereOverlaps,
+            PtrList<labelPairHashSet>& referralVertices,
+            DynamicList<label>& targetProcessor,
+            DynamicList<Vb>& parallelInfluenceVertices
+        );
+
+        label referVertices
+        (
+            const DynamicList<label>& targetProcessor,
+            DynamicList<Vb>& parallelVertices,
+            PtrList<labelPairHashSet>& referralVertices,
+            labelPairHashSet& receivedVertices
+        );
+
+        //- Disallow default bitwise copy construct
+        DistributedDelaunayMesh(const DistributedDelaunayMesh<Triangulation>&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const DistributedDelaunayMesh<Triangulation>&);
+
+
+public:
+
+    // Constructors
+
+        //- Construct from components
+        DistributedDelaunayMesh();
+
+
+    //- Destructor
+    ~DistributedDelaunayMesh();
+
+
+    // Member Functions
+
+        //- Build a mapDistribute for the supplied destination processor data
+        static autoPtr<mapDistribute> buildMap(const List<label>& toProc);
+
+        //-
+        bool distribute(const boundBox& bb);
+
+        autoPtr<mapDistribute> distribute
+        (
+            const backgroundMeshDecomposition& decomposition
+        );
+
+        //- Refer vertices so that the processor interfaces are consistent
+        void sync(const boundBox& bb);
+
+        //- Refer vertices so that the processor interfaces are consistent
+        void sync
+        (
+            const boundBox& bb,
+            PtrList<labelPairHashSet>& referralVertices,
+            labelPairHashSet& receivedVertices,
+            bool iterateReferral = true
+        );
+
+        //- Inserts points into the triangulation if the point is within
+        //  the circumsphere of another cell
+        template<class PointIterator>
+        labelPairHashSet rangeInsertReferredWithInfo
+        (
+            PointIterator begin,
+            PointIterator end,
+            bool printErrors = true
+        );
+
+//        distributeField();
+
+
+    // Queries
+
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//#include "DistributedDelaunayMeshI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "DistributedDelaunayMesh.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/files b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/files
index 3974c7df757b19c9230a6a904fcc6760435e3ad5..c6e553f64c32b3e7a61d3b26908ecfa3a9e35172 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/files
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/files
@@ -1,5 +1,8 @@
 #include CGAL_FILES
 
+conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C
+conformalVoronoiMesh/indexedCell/indexedCellEnum.C
+
 conformalVoronoiMesh/conformalVoronoiMesh.C
 conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C
 conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C
@@ -13,7 +16,20 @@ conformationSurfaces/conformationSurfaces.C
 
 backgroundMeshDecomposition/backgroundMeshDecomposition.C
 
-cellSizeControlSurfaces/cellSizeControlSurfaces.C
+cellShapeControl/cellShapeControl/cellShapeControl.C
+
+cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.C
+
+cellSizeAndAlignmentControl = cellShapeControl/cellSizeAndAlignmentControl
+$(cellSizeAndAlignmentControl)/cellSizeAndAlignmentControls.C
+$(cellSizeAndAlignmentControl)/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.C
+$(cellSizeAndAlignmentControl)/fileControl/fileControl.C
+$(cellSizeAndAlignmentControl)/searchableSurfaceControl/searchableSurfaceControl.C
+/*cellShapeControl/pQuadCoorControl/pQuadCoorControl.C*/
+
+cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.C
+
+/*cellSizeControlSurfaces/cellSizeControlSurfaces.C*/
 
 cellSizeFunctions = cellSizeControlSurfaces/cellSizeFunction
 $(cellSizeFunctions)/cellSizeFunction/cellSizeFunction.C
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/options b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/options
index 2082f88ff045c1cff3ff1238ebcba1a4a0af978d..4a072aa59319d315848f0d8f75937e2650545842 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/options
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/Make/options
@@ -2,7 +2,7 @@ EXE_DEBUG = -DFULLDEBUG -g -O0
 EXE_FROUNDING_MATH = -frounding-math
 EXE_NDEBUG = -DNDEBUG
 
-CGAL_EXACT =
+CGAL_EXACT = /*-DCGAL_DONT_USE_LAZY_KERNEL*/
 CGAL_INEXACT = -DCGAL_INEXACT
 
 include $(GENERAL_RULES)/CGAL
@@ -20,6 +20,8 @@ EXE_INC = \
     -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/triSurface/lnInclude \
+    -I$(LIB_SRC)/sampling/lnInclude \
+    -IPrintTable \
     -I../vectorTools
 
 EXE_LIBS = \
@@ -27,4 +29,5 @@ EXE_LIBS = \
     -ledgeMesh \
     -lfileFormats \
     -ltriSurface \
-    -ldynamicMesh
+    -ldynamicMesh \
+    -lsampling
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.C
new file mode 100644
index 0000000000000000000000000000000000000000..ee46bff366915e8ca6ef163b62dcd6629b446b52
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.C
@@ -0,0 +1,241 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "PrintTable.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class KeyType, class DataType>
+Foam::PrintTable<KeyType, DataType>::PrintTable()
+:
+    table_(),
+    title_(string::null)
+{}
+
+
+template<class KeyType, class DataType>
+Foam::PrintTable<KeyType, DataType>::PrintTable(const string& title)
+:
+    table_(),
+    title_(title)
+{}
+
+
+template<class KeyType, class DataType>
+Foam::PrintTable<KeyType, DataType>::PrintTable
+(
+    const PrintTable<KeyType, DataType>& table
+)
+:
+    table_(table.table_),
+    title_(table.title_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+template<class KeyType, class DataType>
+Foam::PrintTable<KeyType, DataType>::~PrintTable()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+template<class KeyType, class DataType>
+void Foam::PrintTable<KeyType, DataType>::print
+(
+    Ostream& os,
+    const bool printSum,
+    const bool printAverage
+) const
+{
+    HashTable<HashTable<DataType, label>, KeyType> combinedTable;
+
+    List<HashTable<DataType, KeyType> > procData
+    (
+        Pstream::nProcs(),
+        HashTable<DataType, KeyType>()
+    );
+
+    procData[Pstream::myProcNo()] = table_;
+
+    Pstream::gatherList(procData);
+
+    if (Pstream::master())
+    {
+        label largestKeyLength = 6;
+        label largestDataLength = 0;
+
+        List<label> largestProcSize(Pstream::nProcs(), 0);
+
+        forAll(procData, procI)
+        {
+            const HashTable<DataType, KeyType>& procIData
+                = procData[procI];
+
+            for
+            (
+                typename HashTable<DataType, KeyType>
+                    ::const_iterator iter = procIData.begin();
+                iter != procIData.end();
+                ++iter
+            )
+            {
+                if (!combinedTable.found(iter.key()))
+                {
+                    combinedTable.insert
+                    (
+                        iter.key(),
+                        HashTable<DataType, label>()
+                    );
+                }
+
+                HashTable<DataType, label>& key
+                    = combinedTable[iter.key()];
+
+                key.insert(procI, iter());
+
+                for
+                (
+                    typename HashTable<DataType, label>
+                        ::const_iterator dataIter = key.begin();
+                    dataIter != key.end();
+                    ++dataIter
+                )
+                {
+                    std::ostringstream buf;
+                    buf << dataIter();
+
+                    largestDataLength = max
+                    (
+                        largestDataLength,
+                        label(buf.str().length())
+                    );
+                }
+
+                std::ostringstream buf;
+                buf << iter.key();
+
+                largestKeyLength = max
+                (
+                    largestKeyLength,
+                    label(buf.str().length())
+                );
+            }
+        }
+
+        os.width(largestKeyLength);
+        os  << nl << indent << tab << title_.c_str() << endl;
+
+        os.width(largestKeyLength);
+        os  << indent << "Proc #";
+        forAll(procData, procI)
+        {
+            os  << tab;
+            os.width(largestDataLength);
+            os  << procI;
+        }
+
+        if (printSum)
+        {
+            os  << tab;
+            os.width(largestDataLength);
+            os  << "Sum";
+        }
+
+        if (printAverage)
+        {
+            os  << tab;
+            os.width(largestDataLength);
+            os  << "Average";
+        }
+
+        os  << endl;
+
+        const List<KeyType>& sortedTable = combinedTable.sortedToc();
+
+        forAll(sortedTable, keyI)
+        {
+            const HashTable<DataType, label>& procDataList
+                = combinedTable[sortedTable[keyI]];
+
+            os.width(largestKeyLength);
+            os  << indent << sortedTable[keyI];
+
+            forAll(procDataList, elemI)
+            {
+                os  << tab;
+                os.width(largestDataLength);
+                os  << procDataList[elemI];
+            }
+
+            if (printSum)
+            {
+                DataType sum = 0;
+                forAll(procDataList, elemI)
+                {
+                    sum += procDataList[elemI];
+                }
+
+                os  << tab;
+                os.width(largestDataLength);
+                os  << sum;
+
+                if (printAverage)
+                {
+                    os  << tab;
+                    os.width(largestDataLength);
+                    os  << sum/Pstream::nProcs();
+                }
+            }
+
+            os  << endl;
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
+
+template<class KeyType, class DataType>
+void Foam::PrintTable<KeyType, DataType>::operator=
+(
+    const PrintTable<KeyType, DataType>& rhs
+)
+{
+    // Check for assignment to self
+    if (this == &rhs)
+    {
+        FatalErrorIn
+        (
+            "Foam::PrintTable<KeyType, DataType>::operator="
+            "(const Foam::PrintTable<KeyType, DataType>&)"
+        )   << "Attempted assignment to self"
+            << abort(FatalError);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.H
new file mode 100644
index 0000000000000000000000000000000000000000..7f9ed788713b3860c02721e89e8bf0d5cd4360a1
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTable.H
@@ -0,0 +1,137 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::PrintTable
+
+Description
+    Print a table in parallel, e.g.;
+
+    \verbatim
+                            Vertex Type Information
+                   Proc #        0       1       2       3
+                    Total   145680  145278  145751  145359
+               Unassigned        0       0       0       0
+     nExternalFeatureEdge      883     829     828     960
+    nExternalFeaturePoint        8      10      10      12
+         nExternalSurface     9533    9488    9502    9482
+                     nFar        0       0       0       0
+                nInternal   125494  125198  125642  125174
+     nInternalFeatureEdge      238     241     241     240
+    nInternalFeaturePoint        2       2       2       2
+    nInternalNearBoundary        0       0       0       0
+         nInternalSurface     9522    9510    9526    9489
+                nReferred     7545    7497    7500    7587
+    \endverbatim
+
+SourceFiles
+    PrintTableI.H
+    PrintTable.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PrintTable_H
+#define PrintTable_H
+
+#include "HashTable.H"
+#include "Ostream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class PrintTable Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class KeyType, class DataType>
+class PrintTable
+{
+    // Private data
+
+        //- Hash table holding the data
+        HashTable<DataType, KeyType> table_;
+
+        //- Title of the table
+        string title_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise assignment
+        void operator=(const PrintTable<KeyType, DataType>&);
+
+
+public:
+
+    // Constructors
+
+        //- Null constructor
+        PrintTable();
+
+        //- Construct with a title
+        explicit PrintTable(const string& title);
+
+        //- Copy constructor
+        PrintTable(const PrintTable<KeyType, DataType>& table);
+
+
+    //- Destructor
+    ~PrintTable();
+
+
+    // Member Functions
+
+        //- Add an entry (D) to the given key(K)
+        void add(const KeyType& K, const DataType& D);
+
+        //- Print the table
+        void print
+        (
+            Ostream& os,
+            const bool printSum = false,
+            const bool printAverage = false
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "PrintTableI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "PrintTable.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTableI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTableI.H
new file mode 100644
index 0000000000000000000000000000000000000000..6c093bc13a2d8ea6e05fa53cc452403950a65743
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/PrintTable/PrintTableI.H
@@ -0,0 +1,42 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class KeyType, class DataType>
+void Foam::PrintTable<KeyType, DataType>::add
+(
+    const KeyType& K,
+    const DataType& D
+)
+{
+    table_.set(K, D);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C
index cf7a1eb9021fd476ba2c4589b51ac07963cbc4e6..6e49d111a0b457f8be05e659a471e7400027722b 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C
@@ -25,6 +25,10 @@ License
 
 #include "backgroundMeshDecomposition.H"
 #include "meshSearch.H"
+#include "conformationSurfaces.H"
+#include "zeroGradientFvPatchFields.H"
+#include "Time.H"
+#include "Random.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -377,7 +381,7 @@ void Foam::backgroundMeshDecomposition::initialRefinement()
                         if (oldCellI == -1)
                         {
                             newVolumeStatus[newCellI] =
-                                searchableSurface::UNKNOWN;;
+                                searchableSurface::UNKNOWN;
                         }
                         else
                         {
@@ -413,8 +417,10 @@ void Foam::backgroundMeshDecomposition::initialRefinement()
 
             fvMeshDistribute distributor(mesh_, mergeDist_);
 
-            autoPtr<mapDistributePolyMesh> mapDist =
-                distributor.distribute(newDecomp);
+            autoPtr<mapDistributePolyMesh> mapDist = distributor.distribute
+            (
+                newDecomp
+            );
 
             meshCutter_.distribute(mapDist);
 
@@ -527,87 +533,87 @@ bool Foam::backgroundMeshDecomposition::refineCell
 
     if (volType == searchableSurface::MIXED)
     {
-        // Assess the cell size at the nearest point on the surface for the
-        // MIXED cells, if the cell is large with respect to the cell size,
-        // then refine it.
-
-        pointField samplePoints
-        (
-            volRes_*volRes_*volRes_,
-            vector::zero
-        );
-
-        // scalar sampleVol = cellBb.volume()/samplePoints.size();
-
-        vector delta = cellBb.span()/volRes_;
-
-        label pI = 0;
-
-        for (label i = 0; i < volRes_; i++)
-        {
-            for (label j = 0; j < volRes_; j++)
-            {
-                for (label k = 0; k < volRes_; k++)
-                {
-                    samplePoints[pI++] =
-                        cellBb.min()
-                      + vector
-                        (
-                            delta.x()*(i + 0.5),
-                            delta.y()*(j + 0.5),
-                            delta.z()*(k + 0.5)
-                        );
-                }
-            }
-        }
-
-        List<pointIndexHit> hitInfo;
-        labelList hitSurfaces;
-
-        geometry.findSurfaceNearest
-        (
-            samplePoints,
-            scalarField(samplePoints.size(), sqr(GREAT)),
-            hitInfo,
-            hitSurfaces
-        );
-
-        // weightEstimate = 0.0;
-
-        scalar minCellSize = GREAT;
-
-        forAll(samplePoints, i)
-        {
-            scalar s = cellSizeControl_.cellSize
-            (
-                hitInfo[i].hitPoint()
-            );
-
-            // Info<< "cellBb.midpoint() " << cellBb.midpoint() << nl
-            //     << samplePoints[i] << nl
-            //     << hitInfo[i] << nl
-            //     << "cellBb.span() " << cellBb.span() << nl
-            //     << "cellBb.mag() " << cellBb.mag() << nl
-            //     << s << endl;
-
-            if (s < minCellSize)
-            {
-                minCellSize = max(s, minCellSizeLimit_);
-            }
-
-            // Estimate the number of points in the cell by the surface size,
-            // this is likely to be too small, so reduce.
-            // weightEstimate += sampleVol/pow3(s);
-        }
-
-        if (sqr(spanScale_)*sqr(minCellSize) < magSqr(cellBb.span()))
-        {
-            return true;
-        }
+//        // Assess the cell size at the nearest point on the surface for the
+//        // MIXED cells, if the cell is large with respect to the cell size,
+//        // then refine it.
+//
+//        pointField samplePoints
+//        (
+//            volRes_*volRes_*volRes_,
+//            vector::zero
+//        );
+//
+//        // scalar sampleVol = cellBb.volume()/samplePoints.size();
+//
+//        vector delta = cellBb.span()/volRes_;
+//
+//        label pI = 0;
+//
+//        for (label i = 0; i < volRes_; i++)
+//        {
+//            for (label j = 0; j < volRes_; j++)
+//            {
+//                for (label k = 0; k < volRes_; k++)
+//                {
+//                    samplePoints[pI++] =
+//                        cellBb.min()
+//                      + vector
+//                        (
+//                            delta.x()*(i + 0.5),
+//                            delta.y()*(j + 0.5),
+//                            delta.z()*(k + 0.5)
+//                        );
+//                }
+//            }
+//        }
+//
+//        List<pointIndexHit> hitInfo;
+//        labelList hitSurfaces;
+//
+//        geometry.findSurfaceNearest
+//        (
+//            samplePoints,
+//            scalarField(samplePoints.size(), sqr(GREAT)),
+//            hitInfo,
+//            hitSurfaces
+//        );
+//
+//        // weightEstimate = 0.0;
+//
+//        scalar minCellSize = GREAT;
+//
+//        forAll(samplePoints, i)
+//        {
+//            scalar s = cellShapeControl_.cellSize
+//            (
+//                hitInfo[i].hitPoint()
+//            );
+//
+//            // Info<< "cellBb.midpoint() " << cellBb.midpoint() << nl
+//            //     << samplePoints[i] << nl
+//            //     << hitInfo[i] << nl
+//            //     << "cellBb.span() " << cellBb.span() << nl
+//            //     << "cellBb.mag() " << cellBb.mag() << nl
+//            //     << s << endl;
+//
+//            if (s < minCellSize)
+//            {
+//                minCellSize = max(s, minCellSizeLimit_);
+//            }
+//
+//            // Estimate the number of points in the cell by the surface size,
+//            // this is likely to be too small, so reduce.
+//            // weightEstimate += sampleVol/pow3(s);
+//        }
+//
+//        if (sqr(spanScale_)*sqr(minCellSize) < magSqr(cellBb.span()))
+//        {
+//            return true;
+//        }
     }
     else if (volType == searchableSurface::INSIDE)
     {
-        // scalar s = cvMesh_.cellSizeControl().cellSize(cellBb.midpoint());
+        // scalar s = cvMesh_.cellShapeControl_.cellSize(cellBb.midpoint());
 
         // Estimate the number of points in the cell by the size at the cell
         // midpoint
@@ -724,9 +730,7 @@ void Foam::backgroundMeshDecomposition::buildPatchAndTree()
 
     globalBackgroundBounds_ = treeBoundBox(bbMin, bbMax);
 
-    octreeNearestDistances_ = bFTreePtr_().calcNearestDistance();
-
-    if (cvMeshControls_.objOutput())
+    if (false)
     {
         OFstream fStr
         (
@@ -773,15 +777,15 @@ void Foam::backgroundMeshDecomposition::buildPatchAndTree()
 
 Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
 (
-    const dictionary& coeffsDict,
-    const conformalVoronoiMesh& cvMesh
+    const Time& runTime,
+    Random& rndGen,
+    const conformationSurfaces& geometryToConformTo,
+    const dictionary& coeffsDict
 )
 :
-    runTime_(cvMesh.time()),
-    geometryToConformTo_(cvMesh.geometryToConformTo()),
-    cellSizeControl_(cvMesh.cellSizeControl()),
-    rndGen_(cvMesh.rndGen()),
-    cvMeshControls_(cvMesh.cvMeshControls()),
+    runTime_(runTime),
+    geometryToConformTo_(geometryToConformTo),
+    rndGen_(rndGen),
     mesh_
     (
         IOobject
@@ -800,7 +804,6 @@ Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
     ),
     boundaryFacesPtr_(),
     bFTreePtr_(),
-    octreeNearestDistances_(),
     allBackgroundMeshBounds_(Pstream::nProcs()),
     globalBackgroundBounds_(),
     decomposeDict_
@@ -857,74 +860,6 @@ Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
 }
 
 
-Foam::backgroundMeshDecomposition::backgroundMeshDecomposition
-(
-    const scalar spanScale,
-    const scalar minCellSizeLimit,
-    const label minLevels,
-    const label volRes,
-    const scalar maxCellWeightCoeff,
-
-    const Time& runTime,
-    const conformationSurfaces& geometryToConformTo,
-    const cellSizeControlSurfaces& cellSizeControl,
-    Random& rndGen,
-    const cvControls& cvMeshControls
-)
-:
-    runTime_(runTime),
-    geometryToConformTo_(geometryToConformTo),
-    cellSizeControl_(cellSizeControl),
-    rndGen_(rndGen),
-    cvMeshControls_(cvMeshControls),
-    mesh_
-    (
-        IOobject
-        (
-            fvMesh::defaultRegion,
-            runTime_.timeName(),
-            runTime_,
-            IOobject::MUST_READ
-        )
-    ),
-    meshCutter_
-    (
-        mesh_,
-        labelList(mesh_.nCells(), 0),
-        labelList(mesh_.nPoints(), 0)
-    ),
-    boundaryFacesPtr_(),
-    bFTreePtr_(),
-    octreeNearestDistances_(),
-    allBackgroundMeshBounds_(Pstream::nProcs()),
-    globalBackgroundBounds_(),
-    decomposeDict_
-    (
-        IOobject
-        (
-            "decomposeParDict",
-            runTime_.system(),
-            runTime_,
-            IOobject::MUST_READ_IF_MODIFIED,
-            IOobject::NO_WRITE
-        )
-    ),
-    decomposerPtr_(decompositionMethod::New(decomposeDict_)),
-    mergeDist_(1e-6*mesh_.bounds().mag()),
-    spanScale_(spanScale),
-    minCellSizeLimit_(minCellSizeLimit),
-    minLevels_(minLevels),
-    volRes_(volRes),
-    maxCellWeightCoeff_(maxCellWeightCoeff)
-{
-    // Stand-alone operation
-
-    Info<< nl << "Building initial background mesh decomposition" << endl;
-
-    initialRefinement();
-}
-
-
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 Foam::backgroundMeshDecomposition::~backgroundMeshDecomposition()
@@ -936,10 +871,7 @@ Foam::backgroundMeshDecomposition::~backgroundMeshDecomposition()
 Foam::autoPtr<Foam::mapDistributePolyMesh>
 Foam::backgroundMeshDecomposition::distribute
 (
-    volScalarField& cellWeights,
-    List<DynamicList<point> >& cellVertices,
-    List<DynamicList<label> >& cellVertexIndices,
-    List<DynamicList<label> >& cellVertexTypes
+    volScalarField& cellWeights
 )
 {
     if (debug)
@@ -982,10 +914,8 @@ Foam::backgroundMeshDecomposition::distribute
         {
             Info<< "    cellWeightLimit " << cellWeightLimit << endl;
 
-            Pout<< "    sum(cellWeights) "
-                << sum(cellWeights.internalField())
-                << " max(cellWeights) "
-                << max(cellWeights.internalField())
+            Pout<< "    sum(cellWeights) " << sum(cellWeights.internalField())
+                << " max(cellWeights) " << max(cellWeights.internalField())
                 << endl;
         }
 
@@ -1049,94 +979,6 @@ Foam::backgroundMeshDecomposition::distribute
         // Update numbering of cells/vertices.
         meshCutter_.updateMesh(map);
 
-        {
-            // Map cellVertices, cellVertexIndices and cellVertexTypes
-
-            meshSearch cellSearch(mesh_, polyMesh::FACEPLANES);
-
-            const labelList& reverseCellMap = map().reverseCellMap();
-
-            List<DynamicList<point> > newCellVertices(mesh_.nCells());
-            List<DynamicList<label> > newCellVertexIndices(mesh_.nCells());
-            List<DynamicList<label> > newCellVertexTypes(mesh_.nCells());
-
-            forAll(cellVertices, oldCellI)
-            {
-                DynamicList<point>& oldCellVertices =
-                    cellVertices[oldCellI];
-
-                DynamicList<label>& oldCellVertexIndices =
-                    cellVertexIndices[oldCellI];
-
-                DynamicList<label>& oldCellVertexTypes =
-                    cellVertexTypes[oldCellI];
-
-                if (findIndex(newCellsToRefine, oldCellI) >= 0)
-                {
-                    // This old cell was refined so the cell for the vertices
-                    // in the new mesh needs to be searched for.
-
-                    forAll(oldCellVertices, oPI)
-                    {
-                        const point& v = oldCellVertices[oPI];
-
-                        label newCellI = cellSearch.findCell(v);
-
-                        if (newCellI == -1)
-                        {
-                            // Pout<< "findCell backgroundMeshDecomposition "
-                            //     << v << " "
-                            //     << oldCellI
-                            //     << newCellI
-                            //     << " find nearest cellI ";
-
-                            newCellI = cellSearch.findNearestCell(v);
-
-                            // Pout<< newCellI << endl;
-                        }
-
-                        newCellVertices[newCellI].append(v);
-
-                        newCellVertexIndices[newCellI].append
-                        (
-                            oldCellVertexIndices[oPI]
-                        );
-
-                        newCellVertexTypes[newCellI].append
-                        (
-                            oldCellVertexTypes[oPI]
-                        );
-                    }
-                }
-                else
-                {
-                    label newCellI = reverseCellMap[oldCellI];
-
-                    forAll(oldCellVertices, oPI)
-                    {
-                        newCellVertices[newCellI].append
-                        (
-                            oldCellVertices[oPI]
-                        );
-
-                        newCellVertexIndices[newCellI].append
-                        (
-                            oldCellVertexIndices[oPI]
-                        );
-
-                        newCellVertexTypes[newCellI].append
-                        (
-                            oldCellVertexTypes[oPI]
-                        );
-                    }
-                }
-            }
-
-            cellVertices.transfer(newCellVertices);
-            cellVertexIndices.transfer(newCellVertexIndices);
-            cellVertexTypes.transfer(newCellVertexTypes);
-        }
-
         Info<< "    Background mesh refined from "
             << returnReduce(map().nOldCells(), sumOp<label>())
             << " to " << mesh_.globalData().nTotalCells()
@@ -1193,10 +1035,6 @@ Foam::backgroundMeshDecomposition::distribute
         cellWeights.write();
     }
 
-    mapDist().distributeCellData(cellVertices);
-    mapDist().distributeCellData(cellVertexIndices);
-    mapDist().distributeCellData(cellVertexTypes);
-
     buildPatchAndTree();
 
     return mapDist;
@@ -1227,8 +1065,10 @@ bool Foam::backgroundMeshDecomposition::positionOnThisProcessor
 //    return bFTreePtr_().findAnyOverlap(pt, 0.0);
 
     return
+    (
         bFTreePtr_().getVolumeType(pt)
-     == indexedOctree<treeDataBPatch>::INSIDE;
+     == indexedOctree<treeDataBPatch>::INSIDE
+    );
 }
 
 
@@ -1247,6 +1087,7 @@ Foam::boolList Foam::backgroundMeshDecomposition::positionOnThisProcessor
     return posProc;
 }
 
+
 bool Foam::backgroundMeshDecomposition::overlapsThisProcessor
 (
     const treeBoundBox& box
@@ -1660,110 +1501,304 @@ Foam::backgroundMeshDecomposition::intersectsProcessors
 }
 
 
-Foam::labelListList Foam::backgroundMeshDecomposition::overlapsProcessors
+bool Foam::backgroundMeshDecomposition::overlapsOtherProcessors
 (
-    const List<point>& centres,
-    const List<scalar>& radiusSqrs,
-    bool includeOwnProcessor
+    const point& centre,
+    const scalar& radiusSqr
 ) const
 {
-    DynamicList<label> toCandidateProc;
-    DynamicList<point> testCentres;
-    DynamicList<scalar> testRadiusSqrs;
-    labelList sphereBlockStart(centres.size(), -1);
-    labelList sphereBlockSize(centres.size(), -1);
-
-    label nTotalCandidates = 0;
-
-    forAll(centres, sI)
+    forAll(allBackgroundMeshBounds_, procI)
     {
-        const point& c = centres[sI];
-        scalar rSqr = radiusSqrs[sI];
-
-        label nCandidates = 0;
-
-        forAll(allBackgroundMeshBounds_, procI)
+        if (bFTreePtr_().findNearest(centre, radiusSqr).hit())
         {
-            // It is assumed that the sphere in question overlaps the source
-            // processor, so don't test it, unless includeOwnProcessor is true
-            if
-            (
-                (includeOwnProcessor || procI != Pstream::myProcNo())
-             && allBackgroundMeshBounds_[procI].overlaps(c, rSqr)
-            )
-            {
-                toCandidateProc.append(procI);
-                testCentres.append(c);
-                testRadiusSqrs.append(rSqr);
-
-                nCandidates++;
-            }
+            return true;
         }
-
-        sphereBlockStart[sI] = nTotalCandidates;
-        sphereBlockSize[sI] = nCandidates;
-
-        nTotalCandidates += nCandidates;
     }
 
-    // Needed for reverseDistribute
-    label preDistributionToCandidateProcSize = toCandidateProc.size();
-
-    autoPtr<mapDistribute> map(buildMap(toCandidateProc));
-
-    map().distribute(testCentres);
-    map().distribute(testRadiusSqrs);
-
-    List<bool> sphereOverlapsCandidate(testCentres.size(), false);
-
-    // Test candidate spheres on candidate processors
-    forAll(testCentres, sI)
-    {
-        const point& c = testCentres[sI];
-        scalar rSqr = testRadiusSqrs[sI];
-
-        // If the sphere finds a nearest element of the patch, then it overlaps
-        sphereOverlapsCandidate[sI] = bFTreePtr_().findNearest(c, rSqr).hit();
-        //sphereOverlapsCandidate[sI] = bFTreePtr_().findAnyOverlap(c, rSqr);
-    }
-
-    map().reverseDistribute
-    (
-        preDistributionToCandidateProcSize,
-        sphereOverlapsCandidate
-    );
+    return false;
+}
 
-    labelListList sphereProcs(centres.size());
 
-    // Working storage for assessing processors
-    DynamicList<label> tmpProcs;
+Foam::labelList Foam::backgroundMeshDecomposition::overlapProcessors
+(
+    const point& centre,
+    const scalar radiusSqr
+) const
+{
+    DynamicList<label> toProc(Pstream::nProcs());
 
-    forAll(centres, sI)
+    forAll(allBackgroundMeshBounds_, procI)
     {
-        tmpProcs.clear();
-
-        // Extract the sub list of results for this point
-
-        SubList<bool> sphereProcResults
+        // Test against the bounding box of the processor
+        if
         (
-            sphereOverlapsCandidate,
-            sphereBlockSize[sI],
-            sphereBlockStart[sI]
-        );
-
-        forAll(sphereProcResults, sPRI)
+            procI != Pstream::myProcNo()
+         && allBackgroundMeshBounds_[procI].overlaps(centre, radiusSqr)
+        )
         {
-            if (sphereProcResults[sPRI])
+            // Expensive test
+//            if (bFTreePtr_().findNearest(centre, radiusSqr).hit())
             {
-                tmpProcs.append(toCandidateProc[sphereBlockStart[sI] + sPRI]);
+                toProc.append(procI);
             }
         }
-
-        sphereProcs[sI] = tmpProcs;
     }
 
-    return sphereProcs;
+    return toProc;
 }
 
 
+//Foam::labelListList Foam::backgroundMeshDecomposition::overlapsProcessors
+//(
+//    const List<point>& centres,
+//    const List<scalar>& radiusSqrs,
+//    const Delaunay& T,
+//    bool includeOwnProcessor
+//) const
+//{
+//    DynamicList<label> toCandidateProc;
+//    DynamicList<point> testCentres;
+//    DynamicList<scalar> testRadiusSqrs;
+//    labelList sphereBlockStart(centres.size(), -1);
+//    labelList sphereBlockSize(centres.size(), -1);
+//
+//    label nTotalCandidates = 0;
+//
+//    forAll(centres, sI)
+//    {
+//        const point& c = centres[sI];
+//        scalar rSqr = radiusSqrs[sI];
+//
+//        label nCandidates = 0;
+//
+//        forAll(allBackgroundMeshBounds_, procI)
+//        {
+//            // It is assumed that the sphere in question overlaps the source
+//            // processor, so don't test it, unless includeOwnProcessor is true
+//            if
+//            (
+//                (includeOwnProcessor || procI != Pstream::myProcNo())
+//             && allBackgroundMeshBounds_[procI].overlaps(c, rSqr)
+//            )
+//            {
+//                if (bFTreePtr_().findNearest(c, rSqr).hit())
+//                {
+//                    toCandidateProc.append(procI);
+//                    testCentres.append(c);
+//                    testRadiusSqrs.append(rSqr);
+//
+//                    nCandidates++;
+//                }
+//            }
+//        }
+//
+//        sphereBlockStart[sI] = nTotalCandidates;
+//        sphereBlockSize[sI] = nCandidates;
+//
+//        nTotalCandidates += nCandidates;
+//    }
+//
+//    // Needed for reverseDistribute
+////    label preDistributionToCandidateProcSize = toCandidateProc.size();
+////
+////    autoPtr<mapDistribute> map(buildMap(toCandidateProc));
+////
+////    map().distribute(testCentres);
+////    map().distribute(testRadiusSqrs);
+//
+//    // @todo This is faster, but results in more vertices being referred
+//    boolList sphereOverlapsCandidate(testCentres.size(), true);
+////    boolList sphereOverlapsCandidate(testCentres.size(), false);
+////
+////    // Test candidate spheres on candidate processors
+////    forAll(testCentres, sI)
+////    {
+////        const point& c = testCentres[sI];
+////        const scalar rSqr = testRadiusSqrs[sI];
+////
+////        const bool flagOverlap = bFTreePtr_().findNearest(c, rSqr).hit();
+////
+////        if (flagOverlap)
+////        {
+////            //if (vertexOctree.findAnyOverlap(c, rSqr))
+//////            if (vertexOctree.findNearest(c, rSqr*1.001).hit())
+//////            {
+//////                sphereOverlapsCandidate[sI] = true;
+//////            }
+////
+//////            Vertex_handle nearestVertex = T.nearest_vertex
+//////            (
+//////                toPoint<Point>(c)
+//////            );
+//////
+//////            const scalar distSqr = magSqr
+//////            (
+//////                topoint(nearestVertex->point()) - c
+//////            );
+//////
+//////            if (distSqr <= rSqr)
+//////            {
+//////                // If the sphere finds a nearest element of the patch, then it
+//////                // overlaps
+////                sphereOverlapsCandidate[sI] = true;
+//////            }
+////        }
+////    }
+//
+////    map().reverseDistribute
+////    (
+////        preDistributionToCandidateProcSize,
+////        sphereOverlapsCandidate
+////    );
+//
+//    labelListList sphereProcs(centres.size());
+//
+//    // Working storage for assessing processors
+//    DynamicList<label> tmpProcs;
+//
+//    forAll(centres, sI)
+//    {
+//        tmpProcs.clear();
+//
+//        // Extract the sub list of results for this point
+//
+//        SubList<bool> sphereProcResults
+//        (
+//            sphereOverlapsCandidate,
+//            sphereBlockSize[sI],
+//            sphereBlockStart[sI]
+//        );
+//
+//        forAll(sphereProcResults, sPRI)
+//        {
+//            if (sphereProcResults[sPRI])
+//            {
+//                tmpProcs.append(toCandidateProc[sphereBlockStart[sI] + sPRI]);
+//            }
+//        }
+//
+//        sphereProcs[sI] = tmpProcs;
+//    }
+//
+//    return sphereProcs;
+//}
+
+
+//Foam::labelListList Foam::backgroundMeshDecomposition::overlapProcessors
+//(
+//    const point& cc,
+//    const scalar rSqr
+//) const
+//{
+//    DynamicList<label> toCandidateProc;
+//    label sphereBlockStart(-1);
+//    label sphereBlockSize(-1);
+//
+//    label nCandidates = 0;
+//
+//    forAll(allBackgroundMeshBounds_, procI)
+//    {
+//        // It is assumed that the sphere in question overlaps the source
+//        // processor, so don't test it, unless includeOwnProcessor is true
+//        if
+//        (
+//            (includeOwnProcessor || procI != Pstream::myProcNo())
+//         && allBackgroundMeshBounds_[procI].overlaps(cc, rSqr)
+//        )
+//        {
+//            toCandidateProc.append(procI);
+//
+//            nCandidates++;
+//        }
+//    }
+//
+//    sphereBlockSize = nCandidates;
+//    nTotalCandidates += nCandidates;
+//
+//    // Needed for reverseDistribute
+//    label preDistributionToCandidateProcSize = toCandidateProc.size();
+//
+//    autoPtr<mapDistribute> map(buildMap(toCandidateProc));
+//
+//    map().distribute(testCentres);
+//    map().distribute(testRadiusSqrs);
+//
+//    // @todo This is faster, but results in more vertices being referred
+////    boolList sphereOverlapsCandidate(testCentres.size(), true);
+//    boolList sphereOverlapsCandidate(testCentres.size(), false);
+//
+//    // Test candidate spheres on candidate processors
+//    forAll(testCentres, sI)
+//    {
+//        const point& c = testCentres[sI];
+//        const scalar rSqr = testRadiusSqrs[sI];
+//
+//        const bool flagOverlap = bFTreePtr_().findNearest(c, rSqr).hit();
+//
+//        if (flagOverlap)
+//        {
+//            //if (vertexOctree.findAnyOverlap(c, rSqr))
+////            if (vertexOctree.findNearest(c, rSqr*1.001).hit())
+////            {
+////                sphereOverlapsCandidate[sI] = true;
+////            }
+//
+////            Vertex_handle nearestVertex = T.nearest_vertex
+////            (
+////                toPoint<Point>(c)
+////            );
+////
+////            const scalar distSqr = magSqr
+////            (
+////                topoint(nearestVertex->point()) - c
+////            );
+////
+////            if (distSqr <= rSqr)
+////            {
+////                // If the sphere finds a nearest element of the patch, then it
+////                // overlaps
+//                sphereOverlapsCandidate[sI] = true;
+////            }
+//        }
+//    }
+//
+//    map().reverseDistribute
+//    (
+//        preDistributionToCandidateProcSize,
+//        sphereOverlapsCandidate
+//    );
+//
+//    labelListList sphereProcs(centres.size());
+//
+//    // Working storage for assessing processors
+//    DynamicList<label> tmpProcs;
+//
+//    forAll(centres, sI)
+//    {
+//        tmpProcs.clear();
+//
+//        // Extract the sub list of results for this point
+//
+//        SubList<bool> sphereProcResults
+//        (
+//            sphereOverlapsCandidate,
+//            sphereBlockSize[sI],
+//            sphereBlockStart[sI]
+//        );
+//
+//        forAll(sphereProcResults, sPRI)
+//        {
+//            if (sphereProcResults[sPRI])
+//            {
+//                tmpProcs.append(toCandidateProc[sphereBlockStart[sI] + sPRI]);
+//            }
+//        }
+//
+//        sphereProcs[sI] = tmpProcs;
+//    }
+//
+//    return sphereProcs;
+//}
+
+
 // ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H
index bcdd1638345c49d41a3d0f122546517732d057c7..4fe772b932856de39b519d81c78270ab7e628ac8 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H
@@ -53,7 +53,6 @@ SourceFiles
 #ifndef backgroundMeshDecomposition_H
 #define backgroundMeshDecomposition_H
 
-#include "conformalVoronoiMesh.H"
 #include "fvMesh.H"
 #include "hexRef8.H"
 #include "cellSet.H"
@@ -81,6 +80,10 @@ namespace Foam
 typedef PrimitivePatch<face, List, const pointField, point> bPatch;
 typedef treeDataPrimitivePatch<bPatch> treeDataBPatch;
 
+class Time;
+class Random;
+class conformationSurfaces;
+
 /*---------------------------------------------------------------------------*\
                   Class backgroundMeshDecomposition Declaration
 \*---------------------------------------------------------------------------*/
@@ -98,15 +101,9 @@ class backgroundMeshDecomposition
         //- Reference to surface
         const conformationSurfaces& geometryToConformTo_;
 
-        //- The cell size control object
-        const cellSizeControlSurfaces& cellSizeControl_;
-
         //- Random number generator
         Random& rndGen_;
 
-        //- Controls
-        const cvControls& cvMeshControls_;
-
         //- Mesh stored on for this processor, specifiying the domain that it
         //  is responsible for.
         fvMesh mesh_;
@@ -121,8 +118,6 @@ class backgroundMeshDecomposition
         //- Search tree for the boundaryFaces_ patch
         autoPtr<indexedOctree<treeDataBPatch> > bFTreePtr_;
 
-        List<scalar> octreeNearestDistances_;
-
         //- The bounds of all background meshes on all processors
         treeBoundBoxList allBackgroundMeshBounds_;
 
@@ -204,24 +199,10 @@ public:
         //- Construct from components in cvMesh operation
         backgroundMeshDecomposition
         (
-            const dictionary& coeffsDict,
-            const conformalVoronoiMesh& cvMesh
-        );
-
-        //- Construct from components for standalone operation
-        backgroundMeshDecomposition
-        (
-            const scalar spanScale,
-            const scalar minCellSizeLimit,
-            const label minLevels,
-            const label volRes,
-            const scalar maxCellWeightCoeff,
-
             const Time& runTime,
-            const conformationSurfaces& geometryToConformTo,
-            const cellSizeControlSurfaces& cellSizeControl,
             Random& rndGen,
-            const cvControls& cvMeshControls
+            const conformationSurfaces& geometryToConformTo,
+            const dictionary& coeffsDict
         );
 
 
@@ -238,10 +219,7 @@ public:
         //  returning a map to use to redistribute vertices.
         autoPtr<mapDistributePolyMesh> distribute
         (
-            volScalarField& cellWeights,
-            List<DynamicList<point> >& cellVertices,
-            List<DynamicList<label> >& cellVertexIndices,
-            List<DynamicList<label> >& cellVertexTypes
+            volScalarField& cellWeights
         );
 
         //- Distribute supplied the points to the appropriate processor
@@ -300,18 +278,31 @@ public:
             bool includeOwnProcessor = false
         ) const;
 
-        //- Which processors overlap the given sphere, returns all processors
-        //  whose boundary patch is touched by the sphere or whom the sphere is
-        //  inside.  By default this does not return the processor that the
-        //  query is launched from, it is assumed that the point is on that
-        //  processor.
-        labelListList overlapsProcessors
+        bool overlapsOtherProcessors
         (
-            const List<point>& centres,
-            const List<scalar>& radiusSqrs,
-            bool includeOwnProcessor = false
+            const point& centre,
+            const scalar& radiusSqr
+        ) const;
+
+        labelList overlapProcessors
+        (
+            const point& centre,
+            const scalar radiusSqr
         ) const;
 
+//        //- Which processors overlap the given sphere, returns all processors
+//        //  whose boundary patch is touched by the sphere or whom the sphere is
+//        //  inside.  By default this does not return the processor that the
+//        //  query is launched from, it is assumed that the point is on that
+//        //  processor.
+//        labelListList overlapsProcessors
+//        (
+//            const List<point>& centres,
+//            const List<scalar>& radiusSqrs,
+//            const Delaunay& T,
+//            bool includeOwnProcessor
+//        ) const;
+
         // Access
 
             //- Return access to the underlying mesh
@@ -320,9 +311,6 @@ public:
             //- Return access to the underlying tree
             inline const indexedOctree<treeDataBPatch>& tree() const;
 
-            //- Return access to the nearest distance of the octree nodes
-            inline const List<scalar>& octreeNearestDistances() const;
-
             //- Return the boundBox of this processor
             inline const treeBoundBox& procBounds() const;
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H
index 44a007193d8e85fae30c2b8a024385a2c90fedab..1f8b7b0a327a1bd7d74fbf5c1ce49719cd4e9734 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H
@@ -30,18 +30,13 @@ const Foam::fvMesh& Foam::backgroundMeshDecomposition::mesh() const
     return mesh_;
 }
 
+
 const Foam::indexedOctree<Foam::treeDataBPatch>&
 Foam::backgroundMeshDecomposition::tree() const
 {
     return bFTreePtr_();
 }
 
-const Foam::List<Foam::scalar>&
-Foam::backgroundMeshDecomposition::octreeNearestDistances() const
-{
-    return octreeNearestDistances_;
-}
-
 
 const Foam::treeBoundBox&
 Foam::backgroundMeshDecomposition::procBounds() const
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.C
new file mode 100644
index 0000000000000000000000000000000000000000..dfba259e674b5dbd6b5cca8bb4e32ab0ff59a3b7
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.C
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "cellAspectRatioControl.H"
+#include "vectorTools.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellAspectRatioControl::cellAspectRatioControl
+(
+    const dictionary& motionDict
+)
+:
+    aspectRatioDict_(motionDict.subOrEmptyDict("cellAspectRatioControl")),
+    aspectRatio_(aspectRatioDict_.lookupOrDefault<scalar>("aspectRatio", 1.0)),
+    aspectRatioDirection_
+    (
+        aspectRatioDict_.lookupOrDefault<vector>
+        (
+            "aspectRatioDirection",
+            vector(0, 0, 0)
+        )
+    )
+{
+    Info<< nl << "    Cell Aspect Ratio Control" << nl
+        << "        Ratio     : " << aspectRatio_ << nl
+        << "        Direction : " << aspectRatioDirection_ << nl << endl;
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellAspectRatioControl::~cellAspectRatioControl()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::cellAspectRatioControl::updateCellSizeAndFaceArea
+(
+    vector& alignmentDir,
+    scalar& targetFaceArea,
+    scalar& targetCellSize
+) const
+{
+    const scalar cosAngle = mag
+    (
+        vectorTools::cosPhi(alignmentDir, aspectRatioDirection_)
+    );
+
+    // Change target face area based on aspect ratio
+    targetFaceArea
+        += targetFaceArea
+          *(aspectRatio_ - 1.0)
+          *(1.0 - cosAngle);
+
+    // Change target cell size based on aspect ratio
+    targetCellSize
+        += targetCellSize
+          *(aspectRatio_ - 1.0)
+          *cosAngle;
+
+    alignmentDir *= 0.5*targetCellSize;
+}
+
+
+void Foam::cellAspectRatioControl::updateDeltaVector
+(
+    const vector& alignmentDir,
+    const scalar targetCellSize,
+    const scalar rABMag,
+    vector& delta
+) const
+{
+    const scalar cosAngle = mag
+    (
+        vectorTools::cosPhi(alignmentDir, aspectRatioDirection_)
+    );
+
+    delta += 0.5
+            *delta
+            *cosAngle
+            *(targetCellSize/rABMag)
+            *(aspectRatio_ - 1.0);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.H
new file mode 100644
index 0000000000000000000000000000000000000000..ac47311940a7c3672b9c2e378946d1c5b8b658e1
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellAspectRatioControl/cellAspectRatioControl.H
@@ -0,0 +1,115 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::cellAspectRatioControl
+
+Description
+
+SourceFiles
+    cellAspectRatioControl.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellAspectRatioControl_H
+#define cellAspectRatioControl_H
+
+#include "dictionary.H"
+#include "vector.H"
+#include "scalar.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                     Class cellAspectRatioControl Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellAspectRatioControl
+{
+    // Private data
+
+        const dictionary aspectRatioDict_;
+
+        const scalar aspectRatio_;
+
+        const vector aspectRatioDirection_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cellAspectRatioControl(const cellAspectRatioControl&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellAspectRatioControl&);
+
+
+public:
+
+    // Constructors
+
+        //- Construct from dictionary
+        cellAspectRatioControl
+        (
+            const dictionary& motionDict
+        );
+
+
+    //- Destructor
+    virtual ~cellAspectRatioControl();
+
+
+    // Member Functions
+
+        // Query
+
+            void updateCellSizeAndFaceArea
+            (
+                vector& alignmentDir,
+                scalar& targetFaceArea,
+                scalar& targetCellSize
+            ) const;
+
+            void updateDeltaVector
+            (
+                const vector& alignmentDir,
+                const scalar targetCellSize,
+                const scalar rABMag,
+                vector& delta
+            ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.C
new file mode 100644
index 0000000000000000000000000000000000000000..102f637c0972f230175b3c9da4e65002b09a401e
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.C
@@ -0,0 +1,920 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "cellShapeControl.H"
+#include "pointField.H"
+#include "scalarField.H"
+#include "cellSizeAndAlignmentControl.H"
+#include "searchableSurfaceControl.H"
+#include "cellSizeFunction.H"
+#include "triad.H"
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+template <class Triangulation, class Type>
+Foam::tmp<Foam::Field<Type> > Foam::cellShapeControl::filterFarPoints
+(
+    const Triangulation& mesh,
+    const Field<Type>& field
+)
+{
+    tmp<Field<Type> > tNewField(new Field<Type>(field.size()));
+    Field<Type>& newField = tNewField();
+
+    label added = 0;
+    label count = 0;
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            newField[added++] = field[count];
+        }
+
+        count++;
+    }
+
+    newField.resize(added);
+
+    return tNewField;
+}
+
+
+template <class Triangulation>
+Foam::autoPtr<Foam::mapDistribute> Foam::cellShapeControl::buildReferredMap
+(
+    const Triangulation& mesh,
+    labelList& indices
+)
+{
+    globalIndex globalIndexing(mesh.vertexCount());
+
+    DynamicList<label> dynIndices(mesh.vertexCount()/10);
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->referred())
+        {
+            dynIndices.append
+            (
+                globalIndexing.toGlobal(vit->procIndex(), vit->index())
+            );
+        }
+    }
+
+    indices.transfer(dynIndices);
+
+    List<Map<label> > compactMap;
+    return autoPtr<mapDistribute>
+    (
+        new mapDistribute
+        (
+            globalIndexing,
+            indices,
+            compactMap
+        )
+    );
+}
+
+
+template <class Triangulation>
+Foam::autoPtr<Foam::mapDistribute> Foam::cellShapeControl::buildMap
+(
+    const Triangulation& mesh,
+    labelListList& pointPoints
+)
+{
+    pointPoints.setSize(mesh.vertexCount());
+
+    globalIndex globalIndexing(mesh.vertexCount());
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        std::list<typename Triangulation::Vertex_handle> adjVerts;
+        mesh.finite_adjacent_vertices(vit, std::back_inserter(adjVerts));
+
+        DynamicList<label> indices(adjVerts.size());
+
+        for
+        (
+            typename std::list<typename Triangulation::Vertex_handle>::
+                const_iterator adjVertI = adjVerts.begin();
+            adjVertI != adjVerts.end();
+            ++adjVertI
+        )
+        {
+            typename Triangulation::Vertex_handle vh = *adjVertI;
+
+            if (!vh->farPoint())
+            {
+                indices.append
+                (
+                    globalIndexing.toGlobal(vh->procIndex(), vh->index())
+                );
+            }
+        }
+
+        pointPoints[vit->index()].transfer(indices);
+    }
+
+    List<Map<label> > compactMap;
+    return autoPtr<mapDistribute>
+    (
+        new mapDistribute
+        (
+            globalIndexing,
+            pointPoints,
+            compactMap
+        )
+    );
+}
+
+
+template <class Triangulation>
+Foam::tmp<Foam::triadField> Foam::cellShapeControl::buildAlignmentField
+(
+    const Triangulation& mesh
+)
+{
+    tmp<triadField> tAlignments
+    (
+        new triadField(mesh.vertexCount(), triad::unset)
+    );
+    triadField& alignments = tAlignments();
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        alignments[vit->index()] = triad
+        (
+            vit->alignment().x(),
+            vit->alignment().y(),
+            vit->alignment().z()
+        );
+    }
+
+    return tAlignments;
+}
+
+
+template <class Triangulation>
+Foam::tmp<Foam::pointField> Foam::cellShapeControl::buildPointField
+(
+    const Triangulation& mesh
+)
+{
+    tmp<pointField> tPoints
+    (
+        new pointField(mesh.vertexCount(), point(GREAT, GREAT, GREAT))
+    );
+    pointField& points = tPoints();
+
+    for
+    (
+        typename Triangulation::Finite_vertices_iterator vit =
+            mesh.finite_vertices_begin();
+        vit != mesh.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->real())
+        {
+            continue;
+        }
+
+        points[vit->index()] = topoint(vit->point());
+    }
+
+    return tPoints;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellShapeControl::cellShapeControl
+(
+    const Time& runTime,
+    const dictionary& motionDict,
+    const searchableSurfaces& allGeometry,
+    const conformationSurfaces& geometryToConformTo
+)
+:
+    dictionary(motionDict),
+    runTime_(runTime),
+    allGeometry_(allGeometry),
+    geometryToConformTo_(geometryToConformTo),
+    defaultCellSize_(readScalar(lookup("defaultCellSize"))),
+    shapeControlMesh_(runTime),
+    aspectRatio_(motionDict),
+    sizeAndAlignment_
+    (
+        runTime,
+        motionDict.subDict("shapeControlFunctions"),
+        geometryToConformTo
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellShapeControl::~cellShapeControl()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+Foam::scalarField Foam::cellShapeControl::cellSize
+(
+    const pointField& pts
+) const
+{
+    scalarField cellSizes(pts.size());
+
+    forAll(pts, i)
+    {
+        cellSizes[i] = cellSize(pts[i]);
+    }
+
+    return cellSizes;
+}
+
+
+Foam::scalar Foam::cellShapeControl::cellSize(const point& pt) const
+{
+    scalarList bary;
+    cellShapeControlMesh::Cell_handle ch;
+
+    shapeControlMesh_.barycentricCoords(pt, bary, ch);
+
+    scalar size = 0;
+
+    label nFarPoints = 0;
+    for (label pI = 0; pI < 4; ++pI)
+    {
+        if (ch->vertex(pI)->farPoint())
+        {
+            nFarPoints++;
+        }
+    }
+
+    if (shapeControlMesh_.is_infinite(ch))
+    {
+//        if (nFarPoints != 0)
+//        {
+//            for (label pI = 0; pI < 4; ++pI)
+//            {
+//                if (!ch->vertex(pI)->farPoint())
+//                {
+//                    size = ch->vertex(pI)->targetCellSize();
+//                    return size;
+//                }
+//            }
+//        }
+
+        // Look up nearest point
+        cellShapeControlMesh::Vertex_handle nearV =
+            shapeControlMesh_.nearest_vertex
+            (
+                toPoint<cellShapeControlMesh::Point>(pt)
+            );
+
+        size = nearV->targetCellSize();
+    }
+    else
+    {
+        if (nFarPoints != 0)
+        {
+            for (label pI = 0; pI < 4; ++pI)
+            {
+                if (!ch->vertex(pI)->farPoint())
+                {
+                    size = ch->vertex(pI)->targetCellSize();
+                    return size;
+                }
+            }
+        }
+        else
+        {
+            forAll(bary, pI)
+            {
+                size += bary[pI]*ch->vertex(pI)->targetCellSize();
+            }
+        }
+    }
+
+    return size;
+}
+
+
+//- Return the cell alignment at the given location
+Foam::tensor Foam::cellShapeControl::cellAlignment(const point& pt) const
+{
+    scalarList bary;
+    cellShapeControlMesh::Cell_handle ch;
+
+    shapeControlMesh_.barycentricCoords(pt, bary, ch);
+
+    tensor alignment = tensor::zero;
+
+    label nFarPoints = 0;
+    for (label pI = 0; pI < 4; ++pI)
+    {
+        if (ch->vertex(pI)->farPoint())
+        {
+            nFarPoints++;
+        }
+    }
+
+    if (shapeControlMesh_.is_infinite(ch) || nFarPoints == 4)
+    {
+        Pout<< "At Infinite vertex" << endl;
+
+        if (nFarPoints != 0)
+        {
+            for (label pI = 0; pI < 4; ++pI)
+            {
+                if (!ch->vertex(pI)->farPoint())
+                {
+                    alignment = ch->vertex(pI)->alignment();
+                    return alignment;
+                }
+            }
+        }
+
+//        cellShapeControlMesh::Vertex_handle nearV =
+//            shapeControlMesh_.nearest_vertex
+//            (
+//                toPoint<cellShapeControlMesh::Point>(pt)
+//            );
+//
+//        alignment = nearV->alignment();
+    }
+    else
+    {
+//        forAll(bary, pI)
+//        {
+//            alignment += bary[pI]*ch->vertex(pI)->alignment();
+//        }
+
+        cellShapeControlMesh::Vertex_handle nearV =
+            shapeControlMesh_.nearest_vertex_in_cell
+            (
+                toPoint<cellShapeControlMesh::Point>(pt),
+                ch
+            );
+
+        alignment = nearV->alignment();
+    }
+
+    return alignment;
+}
+
+
+void Foam::cellShapeControl::cellSizeAndAlignment
+(
+    const point& pt,
+    scalar& size,
+    tensor& alignment
+) const
+{
+    scalarList bary;
+    cellShapeControlMesh::Cell_handle ch;
+
+    shapeControlMesh_.barycentricCoords(pt, bary, ch);
+
+    alignment = tensor::zero;
+    size = 0;
+
+    label nFarPoints = 0;
+    for (label pI = 0; pI < 4; ++pI)
+    {
+        if (ch->vertex(pI)->farPoint())
+        {
+            nFarPoints++;
+        }
+    }
+
+    if (shapeControlMesh_.is_infinite(ch))
+    {
+        if (nFarPoints != 0)
+        {
+            for (label pI = 0; pI < 4; ++pI)
+            {
+                if (!ch->vertex(pI)->farPoint())
+                {
+                    size = ch->vertex(pI)->targetCellSize();
+                    alignment = ch->vertex(pI)->alignment();
+                    return;
+                }
+            }
+        }
+
+//        cellShapeControlMesh::Vertex_handle nearV =
+//            shapeControlMesh_.nearest_vertex
+//            (
+//                toPoint<cellShapeControlMesh::Point>(pt)
+//            );
+//
+//        size = nearV->targetCellSize();
+//        alignment = nearV->alignment();
+    }
+    else
+    {
+        if (nFarPoints != 0)
+        {
+            for (label pI = 0; pI < 4; ++pI)
+            {
+                if (!ch->vertex(pI)->farPoint())
+                {
+                    size = ch->vertex(pI)->targetCellSize();
+                    alignment = ch->vertex(pI)->alignment();
+                    return;
+                }
+            }
+        }
+        else
+        {
+            triad tri;
+
+            forAll(bary, pI)
+            {
+                size += bary[pI]*ch->vertex(pI)->targetCellSize();
+
+                triad triTmp2
+                (
+                    ch->vertex(pI)->alignment().x(),
+                    ch->vertex(pI)->alignment().y(),
+                    ch->vertex(pI)->alignment().z()
+                );
+
+                tri += triTmp2*bary[pI];
+            }
+
+            tri.normalize();
+            tri.orthogonalize();
+            tri = tri.sortxyz();
+
+            alignment = tensor
+            (
+                tri.x(), tri.y(), tri.z()
+            );
+        }
+    }
+}
+
+
+void Foam::cellShapeControl::initialMeshPopulation
+(
+    const autoPtr<backgroundMeshDecomposition>& decomposition
+)
+{
+    // Need to pass in the background mesh decomposition so that can test if
+    // a point to insert is on the processor.
+    if (Pstream::parRun())
+    {
+        shapeControlMesh_.insertBoundingPoints(decomposition().procBounds());
+    }
+    else
+    {
+        shapeControlMesh_.insertBoundingPoints(allGeometry_.bounds());
+    }
+
+    const PtrList<cellSizeAndAlignmentControl>& controlFunctions =
+        sizeAndAlignment_.controlFunctions();
+
+    forAll(controlFunctions, fI)
+    {
+        const cellSizeAndAlignmentControl& controlFunction =
+            controlFunctions[fI];
+
+        Info<< "Inserting points from " << controlFunction.name()
+            << " (" << controlFunction.type() << ")" << endl;
+
+        pointField pts(1);
+        scalarField sizes(1);
+        Field<triad> alignments(1);
+
+        controlFunction.initialVertices(pts, sizes, alignments);
+
+        label nRejected = 0;
+
+        forAll(pts, pI)
+        {
+            if (Pstream::parRun())
+            {
+                if (!decomposition().positionOnThisProcessor(pts[pI]))
+                {
+                    nRejected++;
+                    continue;
+                }
+            }
+
+            shapeControlMesh_.insert
+            (
+                pts[pI],
+                sizes[pI],
+                alignments[pI]
+            );
+        }
+
+        Info<< "    Inserted " << (pts.size() - nRejected) << "/" << pts.size()
+            << endl;
+    }
+}
+
+
+Foam::label Foam::cellShapeControl::refineMesh
+(
+    const autoPtr<backgroundMeshDecomposition>& decomposition
+)
+{
+    const pointField cellCentres = shapeControlMesh_.cellCentres();
+
+    Info<< "    Created cell centres" << endl;
+
+    const PtrList<cellSizeAndAlignmentControl>& controlFunctions =
+        sizeAndAlignment_.controlFunctions();
+
+    DynamicList<Vb> verts(shapeControlMesh_.number_of_vertices());
+
+    forAll(cellCentres, cellI)
+    {
+        const Foam::point& pt = cellCentres[cellI];
+
+        if (!geometryToConformTo_.inside(pt))
+        {
+            continue;
+        }
+
+        scalarList bary;
+        cellShapeControlMesh::Cell_handle ch;
+
+        shapeControlMesh_.barycentricCoords(pt, bary, ch);
+
+        if (shapeControlMesh_.is_infinite(ch))
+        {
+            continue;
+        }
+
+        scalar interpolatedSize = 0;
+        forAll(bary, pI)
+        {
+            interpolatedSize += bary[pI]*ch->vertex(pI)->targetCellSize();
+        }
+
+        label lastPriority = labelMax;
+        scalar lastCellSize = GREAT;
+        forAll(controlFunctions, fI)
+        {
+            const cellSizeAndAlignmentControl& controlFunction =
+                controlFunctions[fI];
+
+            if (controlFunction.priority() > lastPriority)
+            {
+                continue;
+            }
+
+            if (isA<searchableSurfaceControl>(controlFunction))
+            {
+                const cellSizeFunction& sizeFunction =
+                    dynamicCast<const searchableSurfaceControl>
+                    (
+                        controlFunction
+                    ).sizeFunction();
+
+                scalar cellSize = 0;
+                if (sizeFunction.cellSize(pt, cellSize))
+                {
+                    if (controlFunction.priority() == lastPriority)
+                    {
+                        if (cellSize < lastCellSize)
+                        {
+                            lastCellSize = cellSize;
+                        }
+                    }
+                    else
+                    {
+                        lastCellSize = cellSize;
+                    }
+
+                    lastPriority = controlFunction.priority();
+                }
+            }
+        }
+
+        if
+        (
+            lastCellSize < GREAT
+         && mag(interpolatedSize - lastCellSize)/lastCellSize > 0.2
+        )
+        {
+            if (Pstream::parRun())
+            {
+                if (!decomposition().positionOnThisProcessor(pt))
+                {
+                    continue;
+                }
+            }
+
+            verts.append
+            (
+                Vb
+                (
+                    toPoint<cellShapeControlMesh::Point>(pt),
+                    Vb::vtInternal
+                )
+            );
+            verts.last().targetCellSize() = lastCellSize;
+            verts.last().alignment() = tensor::I;
+        }
+    }
+
+    shapeControlMesh_.insertPoints(verts);
+
+    return verts.size();
+}
+
+
+void Foam::cellShapeControl::smoothMesh()
+{
+    label maxSmoothingIterations = 200;
+    scalar minResidual = 0;
+
+    labelListList pointPoints;
+    autoPtr<mapDistribute> meshDistributor = buildMap
+    (
+        shapeControlMesh_,
+        pointPoints
+    );
+
+    triadField alignments = buildAlignmentField(shapeControlMesh_);
+    pointField points = buildPointField(shapeControlMesh_);
+    // Setup the sizes and alignments on each point
+    triadField fixedAlignments(shapeControlMesh_.vertexCount(), triad::unset);
+
+    for
+    (
+        CellSizeDelaunay::Finite_vertices_iterator vit =
+            shapeControlMesh_.finite_vertices_begin();
+        vit != shapeControlMesh_.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            const tensor& alignment = vit->alignment();
+
+            fixedAlignments[vit->index()] = triad
+            (
+                alignment.x(),
+                alignment.y(),
+                alignment.z()
+            );
+        }
+    }
+
+    Info<< nl << "Smoothing alignments" << endl;
+
+    for (label iter = 0; iter < maxSmoothingIterations; iter++)
+    {
+        Info<< "Iteration " << iter;
+
+        meshDistributor().distribute(points);
+        meshDistributor().distribute(alignments);
+
+        scalar residual = 0;
+
+        triadField triadAv(alignments.size(), triad::unset);
+
+        forAll(pointPoints, pI)
+        {
+            const labelList& pPoints = pointPoints[pI];
+
+            if (pPoints.empty())
+            {
+                continue;
+            }
+
+            triad& newTriad = triadAv[pI];
+
+            forAll(pPoints, adjPointI)
+            {
+                const label adjPointIndex = pPoints[adjPointI];
+
+                scalar dist = mag(points[pI] - points[adjPointIndex]);
+
+                dist = max(dist, SMALL);
+
+                triad tmpTriad = alignments[adjPointIndex];
+
+                for (direction dir = 0; dir < 3; dir++)
+                {
+                    if (tmpTriad.set(dir))
+                    {
+                        tmpTriad[dir] *= (1.0/dist);
+                    }
+                }
+
+                newTriad += tmpTriad;
+            }
+
+            newTriad.normalize();
+            newTriad.orthogonalize();
+            newTriad = newTriad.sortxyz();
+
+            // Enforce the boundary conditions
+            const triad& fixedAlignment = fixedAlignments[pI];
+
+            label nFixed = 0;
+
+            forAll(fixedAlignment, dirI)
+            {
+                if (fixedAlignment[dirI] != triad::unset[dirI])
+                {
+                    nFixed++;
+                }
+            }
+
+            if (nFixed == 1)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad.align(fixedAlignment[dirI]);
+                    }
+                }
+            }
+            else if (nFixed == 2)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad[dirI] = fixedAlignment[dirI];
+                    }
+                    else
+                    {
+                        newTriad[dirI] = triad::unset[dirI];
+                    }
+                }
+
+                newTriad.orthogonalize();
+            }
+            else if (nFixed == 3)
+            {
+                forAll(fixedAlignment, dirI)
+                {
+                    if (fixedAlignment.set(dirI))
+                    {
+                        newTriad[dirI] = fixedAlignment[dirI];
+                    }
+                }
+            }
+
+            const triad& oldTriad = alignments[pI];
+
+            if (newTriad.set(vector::X) && oldTriad.set(vector::X))
+            {
+                scalar dotProd = (oldTriad.x() & newTriad.x());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+            if (newTriad.set(vector::Y) && oldTriad.set(vector::Y))
+            {
+                scalar dotProd = (oldTriad.y() & newTriad.y());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+            if (newTriad.set(vector::Z) && oldTriad.set(vector::Z))
+            {
+                scalar dotProd = (oldTriad.z() & newTriad.z());
+
+                scalar diff = mag(dotProd) - 1.0;
+                residual += mag(diff);
+            }
+        }
+
+        forAll(alignments, pI)
+        {
+            alignments[pI] = triadAv[pI].sortxyz();
+        }
+
+        reduce(residual, sumOp<scalar>());
+
+        Info<< ", Residual = " << residual << endl;
+
+        if (residual <= minResidual)
+        {
+            break;
+        }
+    }
+
+    meshDistributor().distribute(alignments);
+
+    for
+    (
+        CellSizeDelaunay::Finite_vertices_iterator vit =
+            shapeControlMesh_.finite_vertices_begin();
+        vit != shapeControlMesh_.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            vit->alignment() = tensor
+            (
+                alignments[vit->index()].x(),
+                alignments[vit->index()].y(),
+                alignments[vit->index()].z()
+            );
+        }
+    }
+
+    labelList referredPoints;
+    autoPtr<mapDistribute> referredDistributor = buildReferredMap
+    (
+        shapeControlMesh_,
+        referredPoints
+    );
+
+    alignments.setSize(shapeControlMesh_.vertexCount());
+    referredDistributor().distribute(alignments);
+
+    label referredI = 0;
+    for
+    (
+        CellSizeDelaunay::Finite_vertices_iterator vit =
+            shapeControlMesh_.finite_vertices_begin();
+        vit != shapeControlMesh_.finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->referred())
+        {
+            const triad& t = alignments[referredPoints[referredI++]];
+
+            vit->alignment() = tensor(t.x(), t.y(), t.z());
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.H
new file mode 100644
index 0000000000000000000000000000000000000000..3bffe717f7002f3138e29b754b7ff01f899daf35
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControl.H
@@ -0,0 +1,212 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::cellShapeControl
+
+Description
+
+SourceFiles
+    cellShapeControlI.H
+    cellShapeControl.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellShapeControl_H
+#define cellShapeControl_H
+
+#include "dictionary.H"
+#include "autoPtr.H"
+#include "tensor.H"
+#include "point.H"
+#include "primitiveFieldsFwd.H"
+#include "pointFieldFwd.H"
+#include "triadField.H"
+#include "Time.H"
+#include "searchableSurfaces.H"
+#include "conformationSurfaces.H"
+#include "cellAspectRatioControl.H"
+#include "cellSizeAndAlignmentControls.H"
+#include "cellShapeControlMesh.H"
+#include "backgroundMeshDecomposition.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                     Class cellShapeControl Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellShapeControl
+:
+    public dictionary
+{
+    // Private data
+
+        const Time& runTime_;
+
+        const searchableSurfaces& allGeometry_;
+
+        const conformationSurfaces& geometryToConformTo_;
+
+        const scalar defaultCellSize_;
+
+        cellShapeControlMesh shapeControlMesh_;
+
+        cellAspectRatioControl aspectRatio_;
+
+        cellSizeAndAlignmentControls sizeAndAlignment_;
+
+
+    // Private Member Functions
+
+        template <class Triangulation, class Type>
+        tmp<Field<Type> > filterFarPoints
+        (
+            const Triangulation& mesh,
+            const Field<Type>& field
+        );
+
+        template <class Triangulation>
+        autoPtr<mapDistribute> buildMap
+        (
+            const Triangulation& mesh,
+            labelListList& pointPoints
+        );
+
+        template <class Triangulation>
+        autoPtr<mapDistribute> buildReferredMap
+        (
+            const Triangulation& mesh,
+            labelList& indices
+        );
+
+        template <class Triangulation>
+        tmp<triadField> buildAlignmentField(const Triangulation& mesh);
+
+        template <class Triangulation>
+        tmp<pointField> buildPointField(const Triangulation& mesh);
+
+        //- Disallow default bitwise copy construct
+        cellShapeControl(const cellShapeControl&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellShapeControl&);
+
+
+public:
+
+    //- Runtime type information
+    ClassName("cellShapeControl");
+
+
+    // Constructors
+
+        //- Construct from dictionary and references to conformalVoronoiMesh and
+        //  searchableSurfaces
+        cellShapeControl
+        (
+            const Time& runTime,
+            const dictionary& cellShapeControlDict,
+            const searchableSurfaces& allGeometry,
+            const conformationSurfaces& geometryToConformTo
+        );
+
+
+    //- Destructor
+    ~cellShapeControl();
+
+
+    // Member Functions
+
+        // Access
+
+            inline const scalar& defaultCellSize() const;
+
+            inline cellShapeControlMesh& shapeControlMesh();
+
+            inline const cellShapeControlMesh& shapeControlMesh() const;
+
+            inline const cellAspectRatioControl& aspectRatio() const;
+
+            inline const cellSizeAndAlignmentControls& sizeAndAlignment() const;
+
+
+        // Query
+
+            //- Return the cell size at the given location
+            scalar cellSize(const point& pt) const;
+
+            scalarField cellSize(const pointField& pts) const;
+
+            //- Return the cell alignment at the given location
+            tensor cellAlignment(const point& pt) const;
+
+            void cellSizeAndAlignment
+            (
+                const point& pt,
+                scalar& size,
+                tensor& alignment
+            ) const;
+
+
+        // Edit
+
+            void initialMeshPopulation
+            (
+                const autoPtr<backgroundMeshDecomposition>& decomposition
+            );
+
+            label refineMesh
+            (
+                const autoPtr<backgroundMeshDecomposition>& decomposition
+            );
+
+            void smoothMesh();
+
+            //- Add a control point with a specified size and alignment
+//            virtual void addControlPoint
+//            (
+//                const point& pt,
+//                const scalar& size,
+//                const tensor& alignment
+//            );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "cellShapeControlI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControlI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControlI.H
new file mode 100644
index 0000000000000000000000000000000000000000..f7fdebc93192998027adbdfc2ba6527221a0b248
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControl/cellShapeControlI.H
@@ -0,0 +1,55 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+inline Foam::cellShapeControlMesh&
+Foam::cellShapeControl::shapeControlMesh()
+{
+    return shapeControlMesh_;
+}
+
+
+inline const Foam::cellShapeControlMesh&
+Foam::cellShapeControl::shapeControlMesh() const
+{
+    return shapeControlMesh_;
+}
+
+
+inline const Foam::scalar& Foam::cellShapeControl::defaultCellSize() const
+{
+    return defaultCellSize_;
+}
+
+
+inline const Foam::cellAspectRatioControl&
+Foam::cellShapeControl::aspectRatio() const
+{
+    return aspectRatio_;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..bdcbf5a8857efa543ed0bbd0521e284a58bd1d31
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.C
@@ -0,0 +1,760 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "cellShapeControlMesh.H"
+#include "pointIOField.H"
+#include "scalarIOField.H"
+#include "tensorIOField.H"
+#include "tetrahedron.H"
+#include "plane.H"
+#include "transform.H"
+#include "meshTools.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(cellShapeControlMesh, 0);
+
+}
+
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+//Foam::tensor Foam::cellShapeControlMesh::requiredAlignment
+//(
+//    const Foam::point& pt,
+//    const searchableSurfaces& allGeometry,
+//    const conformationSurfaces& geometryToConformTo
+//) const
+//{
+//    pointIndexHit surfHit;
+//    label hitSurface;
+//
+//    geometryToConformTo.findSurfaceNearest
+//    (
+//        pt,
+//        sqr(GREAT),
+//        surfHit,
+//        hitSurface
+//    );
+//
+//    if (!surfHit.hit())
+//    {
+//        FatalErrorIn
+//        (
+//            "Foam::tensor Foam::conformalVoronoiMesh::requiredAlignment"
+//        )   << "findSurfaceNearest did not find a hit across the surfaces."
+//            << exit(FatalError) << endl;
+//    }
+//
+//    // Primary alignment
+//
+//    vectorField norm(1);
+//
+//    allGeometry[hitSurface].getNormal
+//    (
+//        List<pointIndexHit>(1, surfHit),
+//        norm
+//    );
+//
+//    const vector np = norm[0];
+//
+//    // Generate equally spaced 'spokes' in a circle normal to the
+//    // direction from the vertex to the closest point on the surface
+//    // and look for a secondary intersection.
+//
+//    const vector d = surfHit.hitPoint() - pt;
+//
+//    const tensor Rp = rotationTensor(vector(0,0,1), np);
+//
+//    const label s = 36;//cvMeshControls().alignmentSearchSpokes();
+//
+//    scalar closestSpokeHitDistance = GREAT;
+//
+//    pointIndexHit closestSpokeHit;
+//
+//    label closestSpokeSurface = -1;
+//
+//    const scalar spanMag = geometryToConformTo.globalBounds().mag();
+//
+//    for (label i = 0; i < s; i++)
+//    {
+//        vector spoke
+//        (
+//            Foam::cos(i*constant::mathematical::twoPi/s),
+//            Foam::sin(i*constant::mathematical::twoPi/s),
+//            0
+//        );
+//
+//        spoke *= spanMag;
+//
+//        spoke = Rp & spoke;
+//
+//        pointIndexHit spokeHit;
+//
+//        label spokeSurface = -1;
+//
+//        // internal spoke
+//
+//        geometryToConformTo.findSurfaceNearestIntersection
+//        (
+//            pt,
+//            pt + spoke,
+//            spokeHit,
+//            spokeSurface
+//        );
+//
+//        if (spokeHit.hit())
+//        {
+//            scalar spokeHitDistance = mag
+//            (
+//                spokeHit.hitPoint() - pt
+//            );
+//
+//            if (spokeHitDistance < closestSpokeHitDistance)
+//            {
+//                closestSpokeHit = spokeHit;
+//                closestSpokeSurface = spokeSurface;
+//                closestSpokeHitDistance = spokeHitDistance;
+//            }
+//        }
+//
+//        //external spoke
+//
+//        Foam::point mirrorPt = pt + 2*d;
+//
+//        geometryToConformTo.findSurfaceNearestIntersection
+//        (
+//            mirrorPt,
+//            mirrorPt + spoke,
+//            spokeHit,
+//            spokeSurface
+//        );
+//
+//        if (spokeHit.hit())
+//        {
+//            scalar spokeHitDistance = mag
+//            (
+//                spokeHit.hitPoint() - mirrorPt
+//            );
+//
+//            if (spokeHitDistance < closestSpokeHitDistance)
+//            {
+//                closestSpokeHit = spokeHit;
+//                closestSpokeSurface = spokeSurface;
+//                closestSpokeHitDistance = spokeHitDistance;
+//            }
+//        }
+//    }
+//
+//    if (closestSpokeSurface == -1)
+//    {
+////        WarningIn
+////        (
+////            "conformalVoronoiMesh::requiredAlignment"
+////            "("
+////                "const Foam::point& pt"
+////            ") const"
+////        )   << "No secondary surface hit found in spoke search "
+////            << "using " << s
+////            << " spokes, try increasing alignmentSearchSpokes."
+////            << endl;
+//
+//        return I;
+//    }
+//
+//    // Auxiliary alignment generated by spoke intersection normal.
+//
+//    allGeometry[closestSpokeSurface].getNormal
+//    (
+//        List<pointIndexHit>(1, closestSpokeHit),
+//        norm
+//    );
+//
+//    const vector& na = norm[0];
+//
+//    // Secondary alignment
+//    vector ns = np ^ na;
+//
+//    if (mag(ns) < SMALL)
+//    {
+//        FatalErrorIn("conformalVoronoiMesh::requiredAlignment")
+//            << "Parallel normals detected in spoke search." << nl
+//            << "point: " << pt << nl
+//            << "closest surface point: " << surfHit.hitPoint() << nl
+//            << "closest spoke hit: " << closestSpokeHit.hitPoint() << nl
+//            << "np: " << surfHit.hitPoint() + np << nl
+//            << "ns: " << closestSpokeHit.hitPoint() + na << nl
+//            << exit(FatalError);
+//    }
+//
+//    ns /= mag(ns);
+//
+//    tensor Rs = rotationTensor((Rp & vector(0,1,0)), ns);
+//
+//    return (Rs & Rp);
+//}
+
+
+Foam::label Foam::cellShapeControlMesh::removePoints()
+{
+    label nRemoved = 0;
+    for
+    (
+        CellSizeDelaunay::Finite_vertices_iterator vit =
+            finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        std::list<Vertex_handle> verts;
+        adjacent_vertices(vit, std::back_inserter(verts));
+
+        bool removePt = true;
+        for
+        (
+            std::list<Vertex_handle>::iterator aVit = verts.begin();
+            aVit != verts.end();
+            ++aVit
+        )
+        {
+            Vertex_handle avh = *aVit;
+
+            scalar diff =
+                mag(avh->targetCellSize() - vit->targetCellSize())
+               /max(vit->targetCellSize(), 1e-6);
+
+            if (diff > 0.05)
+            {
+                removePt = false;
+            }
+        }
+
+        if (removePt)
+        {
+            remove(vit);
+            nRemoved++;
+        }
+    }
+
+    return nRemoved;
+}
+
+
+Foam::tmp<Foam::pointField> Foam::cellShapeControlMesh::cellCentres() const
+{
+    tmp<pointField> tcellCentres(new pointField(number_of_finite_cells()));
+    pointField& cellCentres = tcellCentres();
+
+    label count = 0;
+    for
+    (
+        CellSizeDelaunay::Finite_cells_iterator c = finite_cells_begin();
+        c != finite_cells_end();
+        ++c
+    )
+    {
+        if (c->hasFarPoint())
+        {
+            continue;
+        }
+
+        scalarList bary;
+        cellShapeControlMesh::Cell_handle ch;
+
+        const Foam::point centre = topoint
+        (
+            CGAL::centroid<baseK>
+            (
+                c->vertex(0)->point(),
+                c->vertex(1)->point(),
+                c->vertex(2)->point(),
+                c->vertex(3)->point()
+            )
+        );
+
+        cellCentres[count++] = centre;
+    }
+
+    cellCentres.resize(count);
+
+    return tcellCentres;
+}
+
+
+void Foam::cellShapeControlMesh::writeTriangulation()
+{
+    OFstream str
+    (
+        "refinementTriangulation_"
+      + name(Pstream::myProcNo())
+      + ".obj"
+    );
+
+    label count = 0;
+
+    Info<< "Write refinementTriangulation" << endl;
+
+    for
+    (
+        CellSizeDelaunay::Finite_edges_iterator e = finite_edges_begin();
+        e != finite_edges_end();
+        ++e
+    )
+    {
+        Cell_handle c = e->first;
+        Vertex_handle vA = c->vertex(e->second);
+        Vertex_handle vB = c->vertex(e->third);
+
+        // Don't write far edges
+        if (vA->farPoint() || vB->farPoint())
+        {
+            continue;
+        }
+
+        // Don't write unowned edges
+        if (vA->referred() && vB->referred())
+        {
+            continue;
+        }
+
+        pointFromPoint p1 = topoint(vA->point());
+        pointFromPoint p2 = topoint(vB->point());
+
+        meshTools::writeOBJ(str, p1, p2, count);
+    }
+
+    if (is_valid())
+    {
+        Info<< "    Triangulation is valid" << endl;
+    }
+    else
+    {
+        FatalErrorIn
+        (
+            "Foam::triangulatedMesh::writeRefinementTriangulation()"
+        )   << "Triangulation is not valid"
+            << abort(FatalError);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellShapeControlMesh::cellShapeControlMesh(const Time& runTime)
+:
+    runTime_(runTime),
+    defaultCellSize_(0.0)
+{}
+
+
+//Foam::triangulatedMesh::triangulatedMesh
+//(
+//    const Time& runTime,
+//    const fileName& pointsFile,
+//    const fileName& sizesFile,
+//    const fileName& alignmentsFile,
+//    const scalar& defaultCellSize
+//)
+//:
+//    defaultCellSize_(defaultCellSize)
+//{
+//    Info<< "    Reading points from file     : " << pointsFile << endl;
+//
+//    pointIOField points
+//    (
+//        IOobject
+//        (
+//            pointsFile,
+//            runTime.constant(),
+//            runTime,
+//            IOobject::MUST_READ,
+//            IOobject::NO_WRITE
+//        )
+//    );
+//
+//    Info<< "    Reading sizes from file      : " << sizesFile << endl;
+//
+//    scalarIOField sizes
+//    (
+//        IOobject
+//        (
+//            sizesFile,
+//            runTime.constant(),
+//            runTime,
+//            IOobject::MUST_READ,
+//            IOobject::NO_WRITE
+//        )
+//    );
+//
+//    Info<< "    Reading alignments from file : " << alignmentsFile << endl;
+//
+//    tensorIOField alignments
+//    (
+//        IOobject
+//        (
+//            alignmentsFile,
+//            runTime.constant(),
+//            runTime,
+//            IOobject::MUST_READ,
+//            IOobject::NO_WRITE
+//        )
+//    );
+//
+//    Info<< "    Number of points : " << points.size() << endl;
+//    Info<< "    Minimum size     : " << min(sizes) << endl;
+//    Info<< "    Average size     : " << average(sizes) << endl;
+//    Info<< "    Maximum size     : " << max(sizes) << endl;
+//
+//    forAll(points, pI)
+//    {
+//        size_t nVert = number_of_vertices();
+//
+//        Vertex_handle v = insert
+//        (
+//            Point(points[pI].x(), points[pI].y(), points[pI].z())
+//        );
+//
+//        if (number_of_vertices() == nVert)
+//        {
+//            Info<< "    Failed to insert point : " << points[pI] << endl;
+//        }
+//
+//        v->targetCellSize() = sizes[pI];
+//
+//        const tensor& alignment = alignments[pI];
+//
+//
+//
+//        v->alignment() = alignment;
+//    }
+//
+////    scalar factor = 1.0;
+////    label maxIteration = 1;
+////
+////    for (label iteration = 0; iteration < maxIteration; ++iteration)
+////    {
+////        Info<< "Iteration : " << iteration << endl;
+////
+////        label nRefined = refineTriangulation(factor);
+////
+////        Info<< "    Number of cells refined in refinement iteration : "
+////            << nRefined << nl << endl;
+////
+////        if (nRefined <= 0 && iteration != 0)
+////        {
+////            break;
+////        }
+////
+////        factor *= 1.5;
+////    }
+//
+//    //writeRefinementTriangulation();
+//}
+
+
+//Foam::triangulatedMesh::triangulatedMesh
+//(
+//    const Time& runTime,
+//    const DynamicList<Foam::point>& points,
+//    const DynamicList<scalar>& sizes,
+//    const DynamicList<tensor>& alignments,
+//    const scalar& defaultCellSize
+//)
+//:
+//    defaultCellSize_(defaultCellSize)
+//{
+//    forAll(points, pI)
+//    {
+//        size_t nVert = number_of_vertices();
+//
+//        Vertex_handle v = insert
+//        (
+//            Point(points[pI].x(), points[pI].y(), points[pI].z())
+//        );
+//
+//        if (number_of_vertices() == nVert)
+//        {
+//            Info<< "Failed to insert point : " << points[pI] << endl;
+//        }
+//
+//        v->targetCellSize() = sizes[pI];
+//
+//        v->alignment() = alignments[pI];
+//    }
+//
+//    //writeRefinementTriangulation();
+//
+//    Info<< nl << "Refinement triangulation information: " << endl;
+//    Info<< "    Number of vertices: " << label(number_of_vertices()) << endl;
+//    Info<< "    Number of cells   : "
+//        << label(number_of_finite_cells()) << endl;
+//    Info<< "    Number of faces   : "
+//        << label(number_of_finite_facets()) << endl;
+//    Info<< "    Number of edges   : "
+//        << label(number_of_finite_edges()) << endl;
+//    Info<< "    Dimensionality    : " << label(dimension()) << nl << endl;
+//}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellShapeControlMesh::~cellShapeControlMesh()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::cellShapeControlMesh::barycentricCoords
+(
+    const Foam::point& pt,
+    scalarList& bary,
+    Cell_handle& ch
+) const
+{
+    // Use the previous cell handle as a hint on where to start searching
+    ch = locate
+    (
+        Point(pt.x(), pt.y(), pt.z())
+    );
+
+    if (!is_infinite(ch))
+    {
+        oldCellHandle_ = ch;
+
+        tetPointRef tet
+        (
+            topoint(ch->vertex(0)->point()),
+            topoint(ch->vertex(1)->point()),
+            topoint(ch->vertex(2)->point()),
+            topoint(ch->vertex(3)->point())
+        );
+
+        tet.barycentric(pt, bary);
+    }
+}
+
+
+Foam::boundBox Foam::cellShapeControlMesh::bounds() const
+{
+    DynamicList<Foam::point> pts(number_of_vertices());
+
+    for
+    (
+        Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            pts.append(topoint(vit->point()));
+        }
+    }
+
+    boundBox bb(pts);
+
+    return bb;
+}
+
+
+void Foam::cellShapeControlMesh::distribute
+(
+    const backgroundMeshDecomposition& decomposition
+)
+{
+    if (!Pstream::parRun())
+    {
+        return;
+    }
+
+    autoPtr<mapDistribute> mapDist =
+        DistributedDelaunayMesh<CellSizeDelaunay>::distribute(decomposition);
+
+    DynamicList<Foam::point> points(number_of_vertices());
+    DynamicList<scalar> sizes(number_of_vertices());
+    DynamicList<tensor> alignments(number_of_vertices());
+
+    for
+    (
+        Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            points.append(topoint(vit->point()));
+            sizes.append(vit->targetCellSize());
+            alignments.append(vit->alignment());
+        }
+    }
+
+    mapDist().distribute(points);
+    mapDist().distribute(sizes);
+    mapDist().distribute(alignments);
+
+    // Reset the entire tessellation
+    DelaunayMesh<CellSizeDelaunay>::reset();
+
+    Info<< nl << "    Inserting distributed tessellation" << endl;
+
+    insertBoundingPoints(decomposition.procBounds());
+
+    // Internal points have to be inserted first
+
+    DynamicList<Vb> verticesToInsert(points.size());
+
+    forAll(points, pI)
+    {
+        verticesToInsert.append
+        (
+            Vb
+            (
+                toPoint<Point>(points[pI]),
+                -1,
+                Vb::vtInternal,
+                Pstream::myProcNo()
+            )
+        );
+
+        verticesToInsert.last().targetCellSize() = sizes[pI];
+        verticesToInsert.last().alignment() = alignments[pI];
+    }
+
+    this->rangeInsertWithInfo
+    (
+        verticesToInsert.begin(),
+        verticesToInsert.end(),
+        true
+    );
+
+    sync(decomposition.procBounds());
+
+    Info<< "    Total number of vertices after redistribution "
+        << returnReduce(label(number_of_vertices()), sumOp<label>()) << endl;
+}
+
+
+Foam::tensorField Foam::cellShapeControlMesh::dumpAlignments() const
+{
+    tensorField alignmentsTmp(number_of_vertices(), tensor::zero);
+
+    label count = 0;
+    for
+    (
+        Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        alignmentsTmp[count++] = vit->alignment();
+    }
+
+    return alignmentsTmp;
+}
+
+
+void Foam::cellShapeControlMesh::insertBoundingPoints(const boundBox& bb)
+{
+    boundBox bbInflate = bb;
+    bbInflate.inflate(10);
+
+    pointField pts = bbInflate.points();
+
+    forAll(pts, pI)
+    {
+        insertFar(pts[pI]);
+    }
+}
+
+
+void Foam::cellShapeControlMesh::write() const
+{
+    Info<< "Writing cell size and alignment mesh" << endl;
+
+    const fileName name("cellSizeAndAlignmentMesh");
+
+    // Reindex the cells
+    label cellCount = 0;
+    for
+    (
+        Finite_cells_iterator cit = finite_cells_begin();
+        cit != finite_cells_end();
+        ++cit
+    )
+    {
+        if (!cit->hasFarPoint() && !is_infinite(cit))
+        {
+            cit->cellIndex() = cellCount++;
+        }
+    }
+
+    labelList vertexMap;
+    labelList cellMap;
+
+    autoPtr<fvMesh> meshPtr = DelaunayMesh<CellSizeDelaunay>::createMesh
+    (
+        name,
+        runTime_,
+        vertexMap,
+        cellMap
+    );
+    const fvMesh& mesh = meshPtr();
+
+    pointScalarField sizes
+    (
+        IOobject
+        (
+            "sizes",
+            mesh.time().timeName(),
+            mesh,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        pointMesh::New(mesh),
+        scalar(0)
+    );
+
+    for
+    (
+        Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (!vit->farPoint())
+        {
+            sizes[vertexMap[vit->index()]] = vit->targetCellSize();
+        }
+    }
+
+    mesh.write();
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..e6cb37a2c3b097b82af919982f1a512331a6bf03
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMesh.H
@@ -0,0 +1,168 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::cellShapeControlMesh
+
+Description
+
+SourceFiles
+    cellShapeControlMeshI.H
+    cellShapeControlMesh.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellShapeControlMesh_H
+#define cellShapeControlMesh_H
+
+#include "Time.H"
+#include "scalar.H"
+#include "point.H"
+#include "tensor.H"
+#include "triad.H"
+#include "fileName.H"
+#include "searchableSurfaces.H"
+#include "conformationSurfaces.H"
+#include "DistributedDelaunayMesh.H"
+#include "CGALTriangulation3Ddefs.H"
+#include "backgroundMeshDecomposition.H"
+#include "boundBox.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class cellShapeControlMesh Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellShapeControlMesh
+:
+    public DistributedDelaunayMesh<CellSizeDelaunay>
+{
+public:
+
+        typedef CellSizeDelaunay::Cell_handle      Cell_handle;
+        typedef CellSizeDelaunay::Vertex_handle    Vertex_handle;
+        typedef CellSizeDelaunay::Point            Point;
+
+
+private:
+
+        // Private data
+
+        const Time& runTime_;
+
+        mutable Cell_handle oldCellHandle_;
+
+        const scalar defaultCellSize_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cellShapeControlMesh(const cellShapeControlMesh&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellShapeControlMesh&);
+
+
+public:
+
+    //- Runtime type information
+    ClassName("cellShapeControlMesh");
+
+
+    // Constructors
+
+        explicit cellShapeControlMesh(const Time& runTime);
+
+
+    //- Destructor
+    ~cellShapeControlMesh();
+
+
+    // Member Functions
+
+        // Query
+
+            //- Calculate and return the barycentric coordinates for
+            //  interpolating quantities on the background mesh
+            void barycentricCoords
+            (
+                const Foam::point& pt,
+                scalarList& bary,
+                Cell_handle& ch
+            ) const;
+
+            boundBox bounds() const;
+
+
+        // Edit
+
+            label removePoints();
+
+            //- Get the centres of all the tets
+            tmp<pointField> cellCentres() const;
+
+            inline Vertex_handle insert
+            (
+                const Foam::point& pt,
+                const scalar& size,
+                const triad& alignment,
+                const Foam::indexedVertexEnum::vertexType type = Vb::vtInternal
+            );
+
+            inline Vertex_handle insertFar
+            (
+                const Foam::point& pt
+            );
+
+            void distribute
+            (
+                const backgroundMeshDecomposition& decomposition
+            );
+
+            tensorField dumpAlignments() const;
+
+            void insertBoundingPoints(const boundBox& bb);
+
+            void writeTriangulation();
+
+            void write() const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "cellShapeControlMeshI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMeshI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMeshI.H
new file mode 100644
index 0000000000000000000000000000000000000000..305256d4ccaf924d7c5dc19c867b6812ffa724f0
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellShapeControlMesh/cellShapeControlMeshI.H
@@ -0,0 +1,68 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::cellShapeControlMesh::Vertex_handle Foam::cellShapeControlMesh::insert
+(
+    const Foam::point& pt,
+    const scalar& size,
+    const triad& alignment,
+    const Foam::indexedVertexEnum::vertexType type
+)
+{
+    Vertex_handle v = CellSizeDelaunay::insert
+    (
+        Point(pt.x(), pt.y(), pt.z())
+    );
+    v->type() = type;
+    v->index() = getNewVertexIndex();
+    v->procIndex() = Pstream::myProcNo();
+    v->targetCellSize() = size;
+    v->alignment() = tensor(alignment.x(), alignment.y(), alignment.z());
+
+    return v;
+}
+
+
+Foam::cellShapeControlMesh::Vertex_handle Foam::cellShapeControlMesh::insertFar
+(
+    const Foam::point& pt
+)
+{
+    Vertex_handle v = CellSizeDelaunay::insert
+    (
+        Point(pt.x(), pt.y(), pt.z())
+    );
+    v->type() = Vb::vtFar;
+//    v->type() = Vb::vtExternalFeaturePoint;
+    v->index() = getNewVertexIndex();
+    v->procIndex() = Pstream::myProcNo();
+
+    return v;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.C
new file mode 100644
index 0000000000000000000000000000000000000000..3dce1d518e5d90acd1adf7a7363bf80d8d92f43e
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.C
@@ -0,0 +1,121 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "cellSizeAndAlignmentControl.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(cellSizeAndAlignmentControl, 0);
+defineRunTimeSelectionTable(cellSizeAndAlignmentControl, dictionary);
+
+}
+
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellSizeAndAlignmentControl::cellSizeAndAlignmentControl
+(
+    const Time& runTime,
+    const word& name,
+    const dictionary& controlFunctionDict,
+    const conformationSurfaces& allGeometry
+)
+:
+    runTime_(runTime),
+    name_(name),
+    priority_(readLabel(controlFunctionDict.lookup("priority")))
+{}
+
+
+// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
+
+Foam::autoPtr<Foam::cellSizeAndAlignmentControl>
+Foam::cellSizeAndAlignmentControl::New
+(
+    const Time& runTime,
+    const word& name,
+    const dictionary& controlFunctionDict,
+    const conformationSurfaces& allGeometry
+)
+{
+    word cellSizeAndAlignmentControlTypeName
+    (
+        controlFunctionDict.lookup("type")
+    );
+
+    Info<< nl << "Selecting cellSizeAndAlignmentControl "
+        << cellSizeAndAlignmentControlTypeName << endl;
+
+    dictionaryConstructorTable::iterator cstrIter =
+        dictionaryConstructorTablePtr_->find
+        (
+            cellSizeAndAlignmentControlTypeName
+        );
+
+    if (cstrIter == dictionaryConstructorTablePtr_->end())
+    {
+        FatalErrorIn
+        (
+            "cellSizeAndAlignmentControl::New()"
+        )   << "Unknown cellSizeAndAlignmentControl type "
+            << cellSizeAndAlignmentControlTypeName
+            << endl << endl
+            << "Valid cellSizeAndAlignmentControl types are :" << endl
+            << dictionaryConstructorTablePtr_->toc()
+            << exit(FatalError);
+    }
+
+    return autoPtr<cellSizeAndAlignmentControl>
+    (
+        cstrIter()
+        (
+            runTime,
+            name,
+            controlFunctionDict,
+            allGeometry
+        )
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellSizeAndAlignmentControl::~cellSizeAndAlignmentControl()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.H
new file mode 100644
index 0000000000000000000000000000000000000000..d8589ba6ef483fc467e491a0a7ac21e95b26e314
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControl.H
@@ -0,0 +1,166 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::cellSizeAndAlignmentControl
+
+Description
+
+SourceFiles
+    cellSizeAndAlignmentControlI.H
+    cellSizeAndAlignmentControl.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellSizeAndAlignmentControl_H
+#define cellSizeAndAlignmentControl_H
+
+#include "dictionary.H"
+#include "conformationSurfaces.H"
+#include "Time.H"
+#include "quaternion.H"
+#include "triad.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                Class cellSizeAndAlignmentControl Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellSizeAndAlignmentControl
+{
+protected:
+
+        const Time& runTime_;
+
+
+private:
+
+    // Private data
+
+        const word name_;
+
+        //- Priority of this cellSizeFunction
+        label priority_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cellSizeAndAlignmentControl(const cellSizeAndAlignmentControl&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellSizeAndAlignmentControl&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("cellSizeAndAlignmentControl");
+
+
+    // Declare run-time constructor selection table
+
+        declareRunTimeSelectionTable
+        (
+            autoPtr,
+            cellSizeAndAlignmentControl,
+            dictionary,
+            (
+                const Time& runTime,
+                const word& name,
+                const dictionary& controlFunctionDict,
+                const conformationSurfaces& allGeometry
+            ),
+            (runTime, name, controlFunctionDict, allGeometry)
+        );
+
+
+    // Constructors
+
+        //- Construct from dictionary and references to conformalVoronoiMesh and
+        //  searchableSurfaces
+        cellSizeAndAlignmentControl
+        (
+            const Time& runTime,
+            const word& name,
+            const dictionary& controlFunctionDict,
+            const conformationSurfaces& allGeometry
+        );
+
+
+    // Selectors
+
+        //- Return a reference to the selected cellShapeControl
+        static autoPtr<cellSizeAndAlignmentControl> New
+        (
+            const Time& runTime,
+            const word& name,
+            const dictionary& controlFunctionDict,
+            const conformationSurfaces& allGeometry
+        );
+
+
+    //- Destructor
+    virtual ~cellSizeAndAlignmentControl();
+
+
+    // Member Functions
+
+        // Access
+
+            const word& name() const
+            {
+                return name_;
+            }
+
+            inline label priority() const
+            {
+                return priority_;
+            }
+
+
+        // Query
+
+            virtual void initialVertices
+            (
+                pointField& pts,
+                scalarField& sizes,
+                Field<triad>& alignments
+            ) const = 0;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.C
new file mode 100644
index 0000000000000000000000000000000000000000..44c8852abfcb7430dc834d8de27b5f60372e114b
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.C
@@ -0,0 +1,78 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "cellSizeAndAlignmentControls.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellSizeAndAlignmentControls::cellSizeAndAlignmentControls
+(
+    const Time& runTime,
+    const dictionary& shapeControlDict,
+    const conformationSurfaces& allGeometry
+)
+:
+    shapeControlDict_(shapeControlDict),
+    allGeometry_(allGeometry),
+    controlFunctions_(shapeControlDict_.size())
+{
+    label functionI = 0;
+
+    forAllConstIter(dictionary, shapeControlDict_, iter)
+    {
+        word shapeControlEntryName = iter().keyword();
+
+        const dictionary& controlFunctionDict
+        (
+            shapeControlDict_.subDict(shapeControlEntryName)
+        );
+
+        controlFunctions_.set
+        (
+            functionI,
+            cellSizeAndAlignmentControl::New
+            (
+                runTime,
+                shapeControlEntryName,
+                controlFunctionDict,
+                allGeometry
+            )
+        );
+
+        functionI++;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellSizeAndAlignmentControls::~cellSizeAndAlignmentControls()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.H
new file mode 100644
index 0000000000000000000000000000000000000000..dac3ffc13cea99b7649526bd489e33febac9551b
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/cellSizeAndAlignmentControls.H
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::cellSizeAndAlignmentControls
+
+Description
+
+SourceFiles
+    cellSizeAndAlignmentControls.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellSizeAndAlignmentControls_H
+#define cellSizeAndAlignmentControls_H
+
+#include "dictionary.H"
+#include "cellShapeControlMesh.H"
+#include "cellSizeAndAlignmentControl.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                     Class cellSizeAndAlignmentControls Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellSizeAndAlignmentControls
+{
+    // Private data
+
+        const dictionary& shapeControlDict_;
+
+        const conformationSurfaces& allGeometry_;
+
+        PtrList<cellSizeAndAlignmentControl> controlFunctions_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cellSizeAndAlignmentControls(const cellSizeAndAlignmentControls&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellSizeAndAlignmentControls&);
+
+
+public:
+
+    // Constructors
+
+        //- Construct from dictionary
+        cellSizeAndAlignmentControls
+        (
+            const Time& runTime,
+            const dictionary& shapeControlDict,
+            const conformationSurfaces& allGeometry
+        );
+
+
+    //- Destructor
+    virtual ~cellSizeAndAlignmentControls();
+
+
+    // Member Functions
+
+        // Access
+
+            const PtrList<cellSizeAndAlignmentControl>& controlFunctions() const
+            {
+                return controlFunctions_;
+            }
+
+
+        // Query
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.C
new file mode 100644
index 0000000000000000000000000000000000000000..4d83468fc4cef053a0031756ebd40de36588bb81
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.C
@@ -0,0 +1,236 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "fileControl.H"
+#include "addToRunTimeSelectionTable.H"
+#include "tetrahedron.H"
+#include "scalarList.H"
+#include "vectorTools.H"
+#include "pointIOField.H"
+#include "scalarIOField.H"
+#include "triadIOField.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(fileControl, 0);
+addToRunTimeSelectionTable
+(
+    cellSizeAndAlignmentControl,
+    fileControl,
+    dictionary
+);
+
+}
+
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileControl::fileControl
+(
+    const Time& runTime,
+    const word& name,
+    const dictionary& controlFunctionDict,
+    const conformationSurfaces& allGeometry
+)
+:
+    cellSizeAndAlignmentControl(runTime, name, controlFunctionDict, allGeometry),
+    pointsFile_(controlFunctionDict.lookup("pointsFile")),
+    sizesFile_(controlFunctionDict.lookup("sizesFile")),
+    alignmentsFile_(controlFunctionDict.lookup("alignmentsFile"))
+{
+    Info<< indent << "Loading from file... " << nl
+        << indent << "    points     : " << pointsFile_ << nl
+        << indent << "    sizes      : " << sizesFile_ << nl
+        << indent << "    alignments : " << alignmentsFile_
+        << endl;
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileControl::~fileControl()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+//
+//Foam::scalar Foam::fileControl::cellSize(const point& pt) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_.barycentricCoords(pt, bary, ch);
+//
+//    scalar size = 0;
+//    forAll(bary, pI)
+//    {
+//        size += bary[pI]*ch->vertex(pI)->size();
+//    }
+//
+//    return size;
+//}
+//
+//
+////- Return the cell alignment at the given location
+//Foam::tensor Foam::fileControl::cellAlignment(const point& pt) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_.barycentricCoords(pt, bary, ch);
+//
+//    label nearest = 0;
+//
+//    tensor alignment = Foam::tensor::zero;
+//    forAll(bary, pI)
+//    {
+//        //alignment += bary[pI]*ch->vertex(pI)->alignment();
+//
+//        // Find nearest point
+//        if (bary[pI] > nearest)
+//        {
+//            alignment = ch->vertex(pI)->alignment();
+//            nearest = bary[pI];
+//        }
+//    }
+//
+//    return alignment;
+//}
+//
+//
+////- Return the cell alignment at the given location
+//void Foam::fileControl::cellSizeAndAlignment
+//(
+//    const point& pt,
+//    scalar& size,
+//    tensor& alignment
+//) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_.barycentricCoords(pt, bary, ch);
+//
+//    size = 0;
+//    forAll(bary, pI)
+//    {
+//        size += bary[pI]*ch->vertex(pI)->size();
+//    }
+//
+////    alignment = Foam::tensor::zero;
+////    forAll(bary, pI)
+////    {
+////        alignment += bary[pI]*ch->vertex(pI)->alignment();
+////    }
+//
+//    alignment = cellAlignment(pt);
+//}
+
+
+void Foam::fileControl::initialVertices
+(
+    pointField& pts,
+    scalarField& sizes,
+    Field<triad>& alignments
+) const
+{
+    Info<< "    Reading points from file     : " << pointsFile_ << endl;
+
+    pointIOField pointsTmp
+    (
+        IOobject
+        (
+            pointsFile_,
+            runTime_.constant(),
+            runTime_,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            false
+        )
+    );
+
+    pts.transfer(pointsTmp);
+
+    Info<< "    Reading sizes from file      : " << sizesFile_ << endl;
+
+    scalarIOField sizesTmp
+    (
+        IOobject
+        (
+            sizesFile_,
+            runTime_.constant(),
+            runTime_,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            false
+        )
+    );
+
+    sizes.transfer(sizesTmp);
+
+    Info<< "    Reading alignments from file : " << alignmentsFile_ << endl;
+
+    triadIOField alignmentsTmp
+    (
+        IOobject
+        (
+            alignmentsFile_,
+            runTime_.constant(),
+            runTime_,
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            false
+        )
+    );
+
+    alignments.transfer(alignmentsTmp);
+
+    if ((pts.size() != sizes.size()) || (pts.size() != alignments.size()))
+    {
+        FatalErrorIn
+        (
+            "Foam::fileControl::initialVertices"
+            "("
+            "   pointField&,"
+            "   scalarField&,"
+            "   Field<triad>&"
+            ")"
+        )   << "Size of list of points, sizes and alignments do not match:"
+            << nl
+            << "Points size     = " << pts.size() << nl
+            << "Sizes size      = " << sizes.size() << nl
+            << "Alignments size = " << alignments.size()
+            << abort(FatalError);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.H
new file mode 100644
index 0000000000000000000000000000000000000000..9c84b516d1afc3ec22fec6f16c9c7a52cfd55f13
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/fileControl/fileControl.H
@@ -0,0 +1,134 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::fileControl
+
+Description
+
+SourceFiles
+    fileControl.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef fileControl_H
+#define fileControl_H
+
+#include "cellSizeAndAlignmentControl.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                      Class fileControl Declaration
+\*---------------------------------------------------------------------------*/
+
+class fileControl
+:
+    public cellSizeAndAlignmentControl
+{
+    // Private data
+
+        const fileName pointsFile_;
+
+        const fileName sizesFile_;
+
+        const fileName alignmentsFile_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        fileControl(const fileControl&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const fileControl&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("fileControl");
+
+
+    // Constructors
+
+        //- Construct from dictionary and references to conformalVoronoiMesh and
+        //  searchableSurfaces
+        fileControl
+        (
+            const Time& runTime,
+            const word& name,
+            const dictionary& controlFunctionDict,
+            const conformationSurfaces& allGeometry
+        );
+
+    //- Destructor
+    ~fileControl();
+
+
+    // Member Functions
+
+        // Access
+
+
+        // Query
+
+//            //- Return the cell size at the given location
+//            virtual scalar cellSize(const point& pt) const;
+//
+//            //- Return the cell alignment at the given location
+//            virtual tensor cellAlignment(const point& pt) const;
+//
+//            virtual void cellSizeAndAlignment
+//            (
+//                const point& pt,
+//                scalar& size,
+//                tensor& alignment
+//            ) const;
+
+
+        // Edit
+
+        virtual void initialVertices
+        (
+            pointField& pts,
+            scalarField& sizes,
+            Field<triad>& alignments
+        ) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.C
new file mode 100644
index 0000000000000000000000000000000000000000..b5e3be42f88c72cb43d384d833fc2f2540905406
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.C
@@ -0,0 +1,640 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "searchableSurfaceControl.H"
+#include "addToRunTimeSelectionTable.H"
+#include "cellSizeFunction.H"
+#include "triSurfaceMesh.H"
+#include "searchableBox.H"
+#include "tetrahedron.H"
+#include "vectorTools.H"
+#include "quaternion.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+defineTypeNameAndDebug(searchableSurfaceControl, 0);
+addToRunTimeSelectionTable
+(
+    cellSizeAndAlignmentControl,
+    searchableSurfaceControl,
+    dictionary
+);
+
+}
+
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+//Foam::tensor Foam::surfaceControl::requiredAlignment
+//(
+//    const Foam::point& pt,
+//    const vectorField& ptNormals
+//) const
+//{
+////    pointIndexHit surfHit;
+////    label hitSurface;
+////
+////    geometryToConformTo_.findSurfaceNearest
+////    (
+////        pt,
+////        sqr(GREAT),
+////        surfHit,
+////        hitSurface
+////    );
+////
+////    if (!surfHit.hit())
+////    {
+////        FatalErrorIn
+////        (
+////            "Foam::tensor Foam::conformalVoronoiMesh::requiredAlignment"
+////        )
+////            << "findSurfaceNearest did not find a hit across the surfaces."
+////            << exit(FatalError) << endl;
+////    }
+////
+//////     Primary alignment
+////
+////    vectorField norm(1);
+////
+////    allGeometry_[hitSurface].getNormal
+////    (
+////        List<pointIndexHit>(1, surfHit),
+////        norm
+////    );
+////
+////    const vector np = norm[0];
+////
+////    const tensor Rp = rotationTensor(vector(0,0,1), np);
+////
+////    return (Rp);
+//
+////    Info<< "Point : " << pt << endl;
+////    forAll(ptNormals, pnI)
+////    {
+////        Info<< "    normal " << pnI << " : " << ptNormals[pnI] << endl;
+////    }
+//
+//    vector np = ptNormals[0];
+//
+//    const tensor Rp = rotationTensor(vector(0,0,1), np);
+//
+//    vector na = vector::zero;
+//
+//    scalar smallestAngle = GREAT;
+//
+//    for (label pnI = 1; pnI < ptNormals.size(); ++pnI)
+//    {
+//        const vector& nextNormal = ptNormals[pnI];
+//
+//        const scalar cosPhi = vectorTools::cosPhi(np, nextNormal);
+//
+//        if (mag(cosPhi) < smallestAngle)
+//        {
+//            na = nextNormal;
+//            smallestAngle = cosPhi;
+//        }
+//    }
+//
+//    // Secondary alignment
+//    vector ns = np ^ na;
+//
+//    if (mag(ns) < SMALL)
+//    {
+//        WarningIn("conformalVoronoiMesh::requiredAlignment")
+//            << "Parallel normals detected in spoke search." << nl
+//            << "point: " << pt << nl
+//            << "np   : " << np << nl
+//            << "na   : " << na << nl
+//            << "ns   : " << ns << nl
+//            << endl;
+//
+//        ns = np;
+//    }
+//
+//    ns /= mag(ns);
+//
+//    tensor Rs = rotationTensor((Rp & vector(0,1,0)), ns);
+//
+////    Info<< "Point " << pt << nl
+////        << "      np : " << np << nl
+////        << "      ns : " << ns << nl
+////        << "      Rp : " << Rp << nl
+////        << "      Rs : " << Rs << nl
+////        << "    Rs&Rp: " << (Rs & Rp) << endl;
+//
+//    return (Rs & Rp);
+//}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::searchableSurfaceControl::searchableSurfaceControl
+(
+    const Time& runTime,
+    const word& name,
+    const dictionary& controlFunctionDict,
+    const conformationSurfaces& allGeometry
+)
+:
+    cellSizeAndAlignmentControl(runTime, name, controlFunctionDict, allGeometry),
+    searchableSurface_(allGeometry.geometry()[name]),
+    allGeometry_(allGeometry),
+    cellSizeFunction_
+    (
+        cellSizeFunction::New(controlFunctionDict, searchableSurface_)
+    )
+//    geometryToConformTo_(geometryToConformTo),
+//    surfaces_(),
+//    cellSizeFunctions_(),
+//    triangulatedMesh_()
+{
+//    const dictionary& surfacesDict = coeffDict();
+//
+//    Info<< nl << "Reading cellSizeControlGeometry" << endl;
+//
+//    surfaces_.setSize(surfacesDict.size());
+//
+//    cellSizeFunctions_.setSize(surfacesDict.size());
+//
+//    label surfI = 0;
+//
+//    DynamicList<point> pointsToInsert;
+//    DynamicList<scalar> sizesToInsert;
+//    DynamicList<tensor> alignmentsToInsert;
+//
+//    forAllConstIter(dictionary, surfacesDict, iter)
+//    {
+//        const dictionary& surfaceSubDict
+//        (
+//            surfacesDict.subDict(iter().keyword())
+//        );
+//
+//        // If the "surface" keyword is not found in the dictionary, assume that
+//        // the name of the dictionary is the surface. Distinction required to
+//        // allow the same surface to be used multiple times to supply multiple
+//        // cellSizeFunctions
+//
+//        word surfaceName = surfaceSubDict.lookupOrDefault<word>
+//        (
+//            "surface",
+//            iter().keyword()
+//        );
+//
+//        surfaces_[surfI] = allGeometry_.findSurfaceID(surfaceName);
+//
+//        if (surfaces_[surfI] < 0)
+//        {
+//            FatalErrorIn
+//            (
+//                "Foam::surfaceControl::surfaceControl"
+//            )   << "No surface " << surfaceName << " found. "
+//                << "Valid geometry is " << nl << allGeometry_.names()
+//                << exit(FatalError);
+//        }
+//
+//        const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
+//
+//        Info<< nl << "    " << iter().keyword() << nl
+//            << "    surface: " << surfaceName << nl
+//            << "    size   : " << surface.size() << endl;
+//
+//        cellSizeFunctions_.set
+//        (
+//            surfI,
+//            cellSizeFunction::New
+//            (
+//                surfaceSubDict,
+//                surface
+//            )
+//        );
+//
+//        surfI++;
+//
+//        if (isA<triSurfaceMesh>(surface))
+//        {
+//            const triSurfaceMesh& tsm
+//                = refCast<const triSurfaceMesh>(surface);
+//
+//            const pointField& points = tsm.points();
+//            const vectorField& faceNormals = tsm.faceNormals();
+//            const labelListList& pointFaces = tsm.pointFaces();
+//
+//            Info<< "    Number of points: " << tsm.nPoints() << endl;
+//
+//            forAll(points, pI)
+//            {
+//                const Foam::point& pt = points[pI];
+//                const labelList& ptFaces = pointFaces[pI];
+//
+//                vectorField pointNormals(ptFaces.size());
+//
+//                forAll(pointNormals, pnI)
+//                {
+//                    pointNormals[pnI] = faceNormals[ptFaces[pnI]];
+//                }
+//
+//                pointsToInsert.append(pt);
+//
+//                // Get the value of the point from surfaceCellSizeFunction. If
+//                // adding points internally then will need to interpolate.
+//                scalar newSize = 0;
+//
+//                cellSizeFunctions_[surfI - 1].cellSize(pt, newSize);
+//                sizesToInsert.append(newSize);
+//
+//                tensor newAlignment = requiredAlignment(pt, pointNormals);
+//
+//                alignmentsToInsert.append(newAlignment);
+//            }
+//        }
+//    }
+//
+//    // Add the global bound box to ensure that all internal point queries
+//    // will return sizes and alignments
+////    boundBox bb = allGeometry_.bounds();
+////
+////    pointField bbPoints = bb.points();
+////
+////    forAll(bbPoints, pI)
+////    {
+////        pointsToInsert.append(bbPoints[pI]);
+////        sizesToInsert.append(defaultCellSize());
+////        alignmentsToInsert.append(tensor(1,0,0,0,1,0,0,0,1));
+////    }
+//
+//    triangulatedMesh_.set
+//    (
+//        new triangulatedMesh
+//        (
+//            runTime,
+//            pointsToInsert,
+//            sizesToInsert,
+//            alignmentsToInsert,
+//            defaultCellSize()
+//        )
+//    );
+//
+//    scalar factor = 1.0;
+//    label maxIteration = cellShapeControlDict.lookupOrDefault<label>
+//    (
+//        "maxRefinementIterations", 1
+//    );
+//
+//
+//    for (label iteration = 0; iteration < maxIteration; ++iteration)
+//    {
+//        Info<< "Iteration : " << iteration << endl;
+//
+//        label nRefined = triangulatedMesh_().refineTriangulation
+//        (
+//            factor,
+//            allGeometry_,
+//            geometryToConformTo_
+//        );
+//
+//        Info<< "    Number of cells refined in refinement iteration : "
+//            << nRefined << nl << endl;
+//
+//        if (nRefined <= 0 && iteration != 0)
+//        {
+//            break;
+//        }
+//
+//        factor *= 1.5;
+//    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::searchableSurfaceControl::~searchableSurfaceControl()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+//Foam::scalar Foam::surfaceControl::cellSize(const point& pt) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_().barycentricCoords(pt, bary, ch);
+//
+//    scalar size = 0;
+//    forAll(bary, pI)
+//    {
+//        size += bary[pI]*ch->vertex(pI)->size();
+//    }
+//
+//    return size;
+//}
+//
+//
+////- Return the cell alignment at the given location
+//Foam::tensor Foam::surfaceControl::cellAlignment(const point& pt) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_().barycentricCoords(pt, bary, ch);
+//
+////    vectorField cartesianDirections(3);
+////
+////    cartesianDirections[0] = vector(0,0,1);
+////    cartesianDirections[1] = vector(0,1,0);
+////    cartesianDirections[2] = vector(1,0,0);
+////
+////    // Rearrange each alignment tensor so that the x/y/z components are
+////    // in order of whichever makes the smallest angle with the global coordinate
+////    // system
+////    FixedList<tensor, 4> alignments;
+////
+////    forAll(alignments, aI)
+////    {
+////        tensor a = ch->vertex(aI)->alignment();
+////
+////        tensor tmpA = a;
+////
+//////        Info<< nl << indent<< a << endl;
+////
+////        scalar minAngle = 0;
+////
+////        scalar axx = vectorTools::cosPhi(a.x(), cartesianDirections[0]);
+////        scalar axy = vectorTools::cosPhi(a.y(), cartesianDirections[0]);
+////        scalar axz = vectorTools::cosPhi(a.z(), cartesianDirections[0]);
+////
+////        scalar ayx = vectorTools::cosPhi(a.x(), cartesianDirections[1]);
+////        scalar ayy = vectorTools::cosPhi(a.y(), cartesianDirections[1]);
+////        scalar ayz = vectorTools::cosPhi(a.z(), cartesianDirections[1]);
+////
+////        scalar azx = vectorTools::cosPhi(a.x(), cartesianDirections[2]);
+////        scalar azy = vectorTools::cosPhi(a.y(), cartesianDirections[2]);
+////        scalar azz = vectorTools::cosPhi(a.z(), cartesianDirections[2]);
+////
+//////        Info<< indent << axx << " " << axy << " " << axz << nl
+//////            << indent << ayx << " " << ayy << " " << ayz << nl
+//////            << indent << azx << " " << azy << " " << azz << endl;
+////
+////        if (mag(axx) >= minAngle)
+////        {
+////            tmpA.xx() = mag(a.xx()); tmpA.xy() = mag(a.xy()); tmpA.xz() = mag(a.xz());
+////            minAngle = mag(axx);
+////        }
+////        if (mag(axy) >= minAngle)
+////        {
+////            tmpA.xx() = mag(a.yx()); tmpA.xy() = mag(a.yy()); tmpA.xz() = mag(a.yz());
+////            minAngle = mag(axy);
+////        }
+////        if (mag(axz) >= minAngle)
+////        {
+////            tmpA.xx() = mag(a.zx()); tmpA.xy() = mag(a.zy()); tmpA.xz() = mag(a.zz());
+////        }
+////
+////        minAngle = 0;
+////
+////        if (mag(ayx) >= minAngle)
+////        {
+////            tmpA.yx() = mag(a.xx()); tmpA.yy() = mag(a.xy()); tmpA.yz() = mag(a.xz());
+////            minAngle = mag(ayx);
+////        }
+////        if (mag(ayy) >= minAngle)
+////        {
+////            tmpA.yx() = mag(a.yx()); tmpA.yy() = mag(a.yy()); tmpA.yz() = mag(a.yz());
+////            minAngle = mag(ayy);
+////        }
+////        if (mag(ayz) >= minAngle)
+////        {
+////            tmpA.yx() = mag(a.zx()); tmpA.yy() = mag(a.zy()); tmpA.yz() = mag(a.zz());
+////        }
+////
+////        minAngle = 0;
+////
+////        if (mag(azx) >= minAngle)
+////        {
+////            tmpA.zx() = mag(a.xx()); tmpA.zy() = mag(a.xy()); tmpA.zz() = mag(a.xz());
+////            minAngle = mag(azx);
+////        }
+////        if (mag(azy) >= minAngle)
+////        {
+////            tmpA.zx() = mag(a.yx()); tmpA.zy() = mag(a.yy()); tmpA.zz() = mag(a.yz());
+////            minAngle = mag(azy);
+////        }
+////        if (mag(azz) >= minAngle)
+////        {
+////            tmpA.zx() = mag(a.zx()); tmpA.zy() = mag(a.zy()); tmpA.zz() = mag(a.zz());
+////        }
+////
+////        alignments[aI] = tmpA;
+////    }
+//
+//    scalar nearest = 0;
+//
+////    Info<< nl << "Point " << pt << endl;
+////
+////    FixedList<quaternion, 4> qAlignments;
+////    forAll(qAlignments, aI)
+////    {
+//////        Info<< "    Direction " << aI << endl;
+//////        Info<< "        Rot tensor" << alignments[aI] << endl;
+////        qAlignments[aI] = quaternion(alignments[aI]);
+////        qAlignments[aI].normalize();
+//////        Info<< "        Quaternion: " << qAlignments[aI] << endl;
+//////        Info<< "        Rot tensor from quat: " << qAlignments[aI].R() << endl;
+////    }
+//
+//    tensor alignment = Foam::tensor::zero;
+//    forAll(bary, pI)
+//    {
+////        alignment += bary[pI]*ch->vertex(pI)->alignment();
+//
+////        alignment += bary[pI]*alignments[pI];
+//
+//        // Try slerp with quaternions
+//
+//        // Find nearest point
+//        if (bary[pI] > nearest)
+//        {
+//            alignment = ch->vertex(pI)->alignment();
+//            nearest = bary[pI];
+//        }
+//    }
+//
+////    quaternion alignment;
+//
+////    alignment = qAlignments[0]*bary[0]
+////              + qAlignments[1]*bary[1]
+////              + qAlignments[2]*bary[2]
+////              + qAlignments[3]*bary[3];
+//
+////    alignment = slerp(qAlignments[0], qAlignments[1], bary[0]+bary[1]+bary[2]);
+////    alignment = slerp(alignment, qAlignments[2], bary[0]+bary[1]+bary[2]);
+////    alignment = slerp(alignment, qAlignments[3], bary[0]+bary[1]+bary[2]);
+////    alignment = slerp(alignment, qAlignments[0], bary[0]/(bary[0]+bary[1]+bary[2]));
+//
+////    Info<< "    Interp alignment : " << alignment << endl;
+////    Info<< "    Interp rot tensor: " << alignment.R() << endl;
+//
+//    return alignment;
+//}
+//
+//
+//void Foam::surfaceControl::cellSizeAndAlignment
+//(
+//    const point& pt,
+//    scalar& size,
+//    tensor& alignment
+//) const
+//{
+//    scalarList bary;
+//    Cell_handle ch;
+//
+//    triangulatedMesh_().barycentricCoords(pt, bary, ch);
+//
+//    size = 0;
+//    forAll(bary, pI)
+//    {
+//        size += bary[pI]*ch->vertex(pI)->size();
+//    }
+//
+////    alignment = Foam::tensor::zero;
+////    forAll(bary, pI)
+////    {
+////        alignment += bary[pI]*ch->vertex(pI)->alignment();
+////    }
+//
+//    alignment = cellAlignment(pt);
+//}
+
+
+void Foam::searchableSurfaceControl::initialVertices
+(
+    pointField& pts,
+    scalarField& sizes,
+    Field<triad>& alignments
+) const
+{
+    pts = searchableSurface_.points();
+
+    const scalar nearFeatDistSqrCoeff = 1e-8;
+
+    sizes.setSize(pts.size());
+    alignments.setSize(pts.size());
+
+    forAll(pts, pI)
+    {
+        // Is the point in the extendedFeatureEdgeMesh? If so get the
+        // point normal, otherwise get the surface normal from
+        // searchableSurface
+
+        pointIndexHit info;
+        label infoFeature;
+        allGeometry_.findFeaturePointNearest
+        (
+            pts[pI],
+            nearFeatDistSqrCoeff,
+            info,
+            infoFeature
+        );
+
+        autoPtr<triad> pointAlignment;
+
+        if (info.hit())
+        {
+            const extendedFeatureEdgeMesh& features =
+                allGeometry_.features()[infoFeature];
+
+            vectorField norms = features.featurePointNormals(info.index());
+
+            // Create a triad from these norms.
+            pointAlignment.set(new triad());
+            forAll(norms, nI)
+            {
+                pointAlignment() += norms[nI];
+            }
+
+            pointAlignment().normalize();
+            pointAlignment().orthogonalize();
+        }
+        else
+        {
+            allGeometry_.findEdgeNearest
+            (
+                pts[pI],
+                nearFeatDistSqrCoeff,
+                info,
+                infoFeature
+            );
+
+            if (info.hit())
+            {
+                const extendedFeatureEdgeMesh& features =
+                    allGeometry_.features()[infoFeature];
+
+                vectorField norms = features.edgeNormals(info.index());
+
+                // Create a triad from these norms.
+                pointAlignment.set(new triad());
+                forAll(norms, nI)
+                {
+                    pointAlignment() += norms[nI];
+                }
+
+                pointAlignment().normalize();
+                pointAlignment().orthogonalize();
+            }
+            else
+            {
+                pointField ptField(1, pts[pI]);
+                scalarField distField(1, nearFeatDistSqrCoeff);
+                List<pointIndexHit> infoList(1, pointIndexHit());
+
+                searchableSurface_.findNearest(ptField, distField, infoList);
+
+                vectorField normals(1);
+                searchableSurface_.getNormal(infoList, normals);
+
+                pointAlignment.set(new triad(normals[0]));
+            }
+        }
+
+        if (!cellSizeFunction_().cellSize(pts[pI], sizes[pI]))
+        {
+            FatalErrorIn
+            (
+                "Foam::searchableSurfaceControl::initialVertices"
+                "(pointField&, scalarField&, tensorField&)"
+            )   << "Could not calculate cell size"
+                << abort(FatalError);
+        }
+
+        alignments[pI] = pointAlignment();
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.H
new file mode 100644
index 0000000000000000000000000000000000000000..87f807d1347a61a1dc3b6629128126a3b2c23fa8
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellShapeControl/cellSizeAndAlignmentControl/searchableSurfaceControl/searchableSurfaceControl.H
@@ -0,0 +1,166 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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::searchableSurfaceControl
+
+Description
+
+SourceFiles
+    searchableSurfaceControl.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef searchableSurfaceControl_H
+#define searchableSurfaceControl_H
+
+#include "cellShapeControl.H"
+#include "cellSizeFunction.H"
+#include "triad.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+
+/*---------------------------------------------------------------------------*\
+                      Class surfaceControl Declaration
+\*---------------------------------------------------------------------------*/
+
+class searchableSurfaceControl
+:
+    public cellSizeAndAlignmentControl
+{
+    // Private data
+
+//        //- Reference to the searchableSurfaces object holding all geometry data
+          const searchableSurface& searchableSurface_;
+
+          const conformationSurfaces& allGeometry_;
+
+          autoPtr<cellSizeFunction> cellSizeFunction_;
+
+
+//        const conformationSurfaces& geometryToConformTo_;
+//
+//        //- Indices of surfaces in allGeometry that are to be conformed to
+//        labelList surfaces_;
+//
+//        //- A list of all of the cellSizeFunction objects
+//        PtrList<cellSizeFunction> cellSizeFunctions_;
+//
+//        autoPtr<triangulatedMesh> triangulatedMesh_;
+//
+//
+//    // Private Member Functions
+//
+//        //-
+//        tensor requiredAlignment
+//        (
+//            const point& pt,
+//            const vectorField& ptNormals
+//        ) const;
+
+        //- Disallow default bitwise copy construct
+        searchableSurfaceControl(const searchableSurfaceControl&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const searchableSurfaceControl&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("searchableSurfaceControl");
+
+
+    // Constructors
+
+        //- Construct from dictionary and references to conformalVoronoiMesh and
+        //  searchableSurfaces
+        searchableSurfaceControl
+        (
+            const Time& runTime,
+            const word& name,
+            const dictionary& controlFunctionDict,
+            const conformationSurfaces& allGeometry
+        );
+
+    //- Destructor
+    ~searchableSurfaceControl();
+
+
+    // Member Functions
+
+        // Access
+
+//            //- Return reference to the searchableSurfaces object containing all
+//            //  of the geometry
+//            inline const searchableSurfaces& geometry() const;
+//
+//            //- Return the surface indices
+//            inline const labelList& surfaces() const;
+//
+//
+//        // Query
+//
+//            //- Return the cell size at the given location
+//            virtual scalar cellSize(const point& pt) const;
+//
+//            //- Return the cell alignment at the given location
+//            virtual tensor cellAlignment(const point& pt) const;
+//
+//            virtual void cellSizeAndAlignment
+//            (
+//                const point& pt,
+//                scalar& size,
+//                tensor& alignment
+//            ) const;
+
+        virtual void initialVertices
+        (
+            pointField& pts,
+            scalarField& sizes,
+            Field<triad>& alignments
+        ) const;
+
+        const cellSizeFunction& sizeFunction() const
+        {
+            return cellSizeFunction_();
+        }
+
+        // Edit
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
index 0b6acc5ca0853e86fb48f399b10d670cb0b24aea..1cc41dc29cc90c1193f4e02a1a7f78435c3431f7 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.C
@@ -26,6 +26,9 @@ License
 #include "cellSizeControlSurfaces.H"
 #include "conformalVoronoiMesh.H"
 #include "cellSizeFunction.H"
+#include "triSurfaceMesh.H"
+#include "tetrahedron.H"
+#include "OFstream.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -149,15 +152,358 @@ bool Foam::cellSizeControlSurfaces::evalCellSizeFunctions
 }
 
 
+bool Foam::cellSizeControlSurfaces::checkCoplanarTet
+(
+    Cell_handle c,
+    const scalar tol
+) const
+{
+    plane triPlane
+    (
+        topoint(c->vertex(0)->point()),
+        topoint(c->vertex(1)->point()),
+        topoint(c->vertex(2)->point())
+    );
+
+    // Check if the four points are roughly coplanar. If they are then we
+    // cannot calculate the circumcentre. Better test might be the volume
+    // of the tet.
+    if (triPlane.distance(topoint(c->vertex(3)->point())) < tol)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+
+bool Foam::cellSizeControlSurfaces::checkClosePoints
+(
+    Cell_handle c,
+    const scalar tol
+) const
+{
+    for (label v = 0; v < 4; ++v)
+    {
+        for (label vA = v + 1; vA < 4; ++vA)
+        {
+            if
+            (
+                mag
+                (
+                    topoint(c->vertex(v)->point())
+                  - topoint(c->vertex(vA)->point())
+                )
+              < tol
+            )
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
+Foam::label Foam::cellSizeControlSurfaces::refineTriangulation
+(
+    const scalar factor
+)
+{
+    // Check the tets and insert new points if necessary
+    List<Foam::point> corners(4);
+    List<scalar> values(4);
+
+    DynamicList<Foam::point> pointsToInsert(T_.number_of_vertices());
+    DynamicList<scalar> valuesToInsert(T_.number_of_vertices());
+
+    for
+    (
+        Delaunay::Finite_cells_iterator c = T_.finite_cells_begin();
+        c != T_.finite_cells_end();
+        ++c
+    )
+    {
+        //const point& newPoint = tet.centre();
+        //Cell_handle ch = c;
+
+//        Info<< count++ << endl;
+//        Info<< "    " << topoint(c->vertex(0)->point()) << nl
+//            << "    " << topoint(c->vertex(1)->point()) << nl
+//            << "    " << topoint(c->vertex(2)->point()) << nl
+//            << "    " << topoint(c->vertex(3)->point()) << endl;
+
+        scalar minDist = 1e-6*defaultCellSize_;
+
+        if (checkClosePoints(c, minDist) || checkCoplanarTet(c, minDist))
+        {
+            continue;
+        }
+
+        const Point circumcenter = CGAL::circumcenter
+        (
+            c->vertex(0)->point(),
+            c->vertex(1)->point(),
+            c->vertex(2)->point(),
+            c->vertex(3)->point()
+        );
+
+        pointFromPoint newPoint = topoint(circumcenter);
+
+        if (geometryToConformTo_.outside(newPoint))
+        {
+            continue;
+        }
+
+        Cell_handle ch = T_.locate
+        (
+            Point(newPoint.x(), newPoint.y(), newPoint.z())
+        );
+
+        forAll(corners, pI)
+        {
+            corners[pI] = topoint(ch->vertex(pI)->point());
+            values[pI] = ch->vertex(pI)->value();
+        }
+
+        tetPointRef tet(corners[0], corners[1], corners[2], corners[3]);
+
+        scalarList bary;
+        tet.barycentric(newPoint, bary);
+
+        scalar interpolatedSize = 0;
+        forAll(bary, pI)
+        {
+            interpolatedSize += bary[pI]*ch->vertex(pI)->value();
+        }
+
+        // Find largest gradient
+        label maxGradCorner = -1;
+        scalar maxGradient = 0.0;
+        forAll(corners, pI)
+        {
+            const scalar distance = mag(newPoint - corners[pI]);
+            const scalar diffSize = interpolatedSize - values[pI];
+
+            const scalar gradient = diffSize/distance;
+
+            if (gradient > maxGradient)
+            {
+                maxGradient = gradient;
+                maxGradCorner = pI;
+            }
+        }
+
+//        if (wallSize < 0.5*defaultCellSize_)
+//        {
+//        Info<< "Centre             : " << centre
+//            << " (Default Size: " << defaultCellSize_ << ")" << nl
+//            << "Interpolated Size  : " << interpolatedSize << nl
+//            << "Distance from wall : " << distanceSize << nl
+//            << "Wall size          : " << wallSize << nl
+//            << "distanceGradient   : " << distanceGradient << nl
+//            << "interpGradient     : " << interpolatedGradient << nl << endl;
+//        }
+
+        scalar minCellSize = 1e-6;
+        scalar initialMaxGradient = 0;//0.2*factor;
+        scalar initialMinGradient = 0;//0.01*(1.0/factor);
+        scalar idealGradient = 0.2;
+
+
+
+        // Reduce strong gradients
+        if (maxGradient > initialMaxGradient)
+        {
+            const scalar distance2 = mag(newPoint - corners[maxGradCorner]);
+
+            scalar newSize
+                = values[maxGradCorner] + idealGradient*distance2;
+
+            pointsToInsert.append(newPoint);
+            valuesToInsert.append
+            (
+                max(min(newSize, defaultCellSize_), minCellSize)
+            );
+        }
+        else if (maxGradient < -initialMaxGradient)
+        {
+            const scalar distance2 = mag(newPoint - corners[maxGradCorner]);
+
+            scalar newSize
+                = values[maxGradCorner] - idealGradient*distance2;
+
+            pointsToInsert.append(newPoint);
+            valuesToInsert.append
+            (
+                max(min(newSize, defaultCellSize_), minCellSize)
+            );
+        }
+
+        // Increase small gradients
+        if
+        (
+            maxGradient < initialMinGradient
+         && maxGradient > 0
+         && interpolatedSize < 0.5*defaultCellSize_
+        )
+        {
+            const scalar distance2 = mag(newPoint - corners[maxGradCorner]);
+
+            scalar newSize
+                = values[maxGradCorner] + idealGradient*distance2;
+
+            pointsToInsert.append(newPoint);
+            valuesToInsert.append
+            (
+                max(min(newSize, defaultCellSize_), minCellSize)
+            );
+        }
+        else if
+        (
+            maxGradient > -initialMinGradient
+         && maxGradient < 0
+         && interpolatedSize > 0.5*defaultCellSize_
+        )
+        {
+            const scalar distance2 = mag(newPoint - corners[maxGradCorner]);
+
+            scalar newSize
+                = values[maxGradCorner] - idealGradient*distance2;
+
+            pointsToInsert.append(newPoint);
+            valuesToInsert.append
+            (
+                max(min(newSize, defaultCellSize_), minCellSize)
+            );
+        }
+    }
+
+    if (!pointsToInsert.empty())
+    {
+        Info<< "    Minimum Cell Size : " << min(valuesToInsert) << nl
+            << "    Average Cell Size : " << average(valuesToInsert) << nl
+            << "    Maximum Cell Size : " << max(valuesToInsert) << endl;
+
+        forAll(pointsToInsert, pI)
+        {
+            Foam::point p = pointsToInsert[pI];
+
+            Vertex_handle v = T_.insert(Point(p.x(), p.y(), p.z()));
+
+            v->value(valuesToInsert[pI]);
+        }
+    }
+
+    return pointsToInsert.size();
+}
+
+
+void Foam::cellSizeControlSurfaces::writeRefinementTriangulation()
+{
+    OFstream str("refinementTriangulation.obj");
+
+    label count = 0;
+
+    Info<< "Write refinementTriangulation" << endl;
+
+    for
+    (
+        Delaunay::Finite_edges_iterator e = T_.finite_edges_begin();
+        e != T_.finite_edges_end();
+        ++e
+    )
+    {
+        Cell_handle c = e->first;
+        Vertex_handle vA = c->vertex(e->second);
+        Vertex_handle vB = c->vertex(e->third);
+
+        pointFromPoint p1 = topoint(vA->point());
+        pointFromPoint p2 = topoint(vB->point());
+
+        meshTools::writeOBJ(str, p1, p2, count);
+    }
+
+
+    OFstream strPoints("refinementObject.obj");
+
+    Info<< "Write refinementObject" << endl;
+
+    for
+    (
+        Delaunay::Finite_vertices_iterator v = T_.finite_vertices_begin();
+        v != T_.finite_vertices_end();
+        ++v
+    )
+    {
+        pointFromPoint p = topoint(v->point());
+
+        meshTools::writeOBJ
+        (
+            strPoints,
+            p,
+            point(p.x() + v->value(), p.y(), p.z())
+        );
+    }
+
+//    OFstream strDual("refinementDualPoints.obj");
+//
+//    Info<< "Write refinementDualPoints" << endl;
+//
+//    for
+//    (
+//        Delaunay::Finite_cells_iterator c = T_.finite_cells_begin();
+//        c != T_.finite_cells_end();
+//        ++c
+//    )
+//    {
+//        Point circumcenter = CGAL::circumcenter
+//        (
+//            c->vertex(0)->point(),
+//            c->vertex(1)->point(),
+//            c->vertex(2)->point(),
+//            c->vertex(3)->point()
+//        );
+//
+//        pointFromPoint p = topoint(circumcenter);
+//
+//        if (geometryToConformTo_.inside(p))
+//        {
+//            meshTools::writeOBJ
+//            (
+//                strDual,
+//                p
+//            );
+//        }
+//    }
+
+    if (T_.is_valid())
+    {
+        Info<< "    Triangulation is valid" << endl;
+    }
+    else
+    {
+        FatalErrorIn
+        (
+            "Foam::cellSizeControlSurfaces::writeRefinementTriangulation()"
+        )   << "Triangulation is not valid"
+            << abort(FatalError);
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::cellSizeControlSurfaces::cellSizeControlSurfaces
 (
     const searchableSurfaces& allGeometry,
+    const conformationSurfaces& geometryToConformTo,
     const dictionary& motionControlDict
 )
 :
     allGeometry_(allGeometry),
+    geometryToConformTo_(geometryToConformTo),
     surfaces_(),
     cellSizeFunctions_(),
     defaultCellSize_(readScalar(motionControlDict.lookup("defaultCellSize"))),
@@ -214,7 +560,8 @@ Foam::cellSizeControlSurfaces::cellSizeControlSurfaces
         const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
 
         Info<< nl << "    " << iter().keyword() << nl
-            << "    surface: " << surfaceName << endl;
+            << "    surface: " << surfaceName << nl
+            << "    size   : " << surface.size() << endl;
 
         cellSizeFunctions_.set
         (
@@ -229,11 +576,78 @@ Foam::cellSizeControlSurfaces::cellSizeControlSurfaces
         priorities[surfI] = cellSizeFunctions_[surfI].priority();
 
         surfI++;
+
+        if (isA<triSurfaceMesh>(surface))
+        {
+            const triSurfaceMesh& tsm
+                = refCast<const triSurfaceMesh>(surface);
+
+            const pointField& points = tsm.points();
+
+            Info<< "    number of points: " << tsm.nPoints() << endl;
+
+            std::vector<std::pair<Point, scalar> > pointsToInsert;
+
+            forAll(points, pI)
+            {
+                size_t nVert = T_.number_of_vertices();
+
+                Vertex_handle v = T_.insert
+                (
+                    Point(points[pI].x(), points[pI].y(), points[pI].z())
+                );
+
+                if (T_.number_of_vertices() == nVert)
+                {
+                    Info<< "Failed to insert point : " << points[pI] << endl;
+                }
+
+                // Get the value of the point from surfaceCellSizeFunction. If
+                // adding points internally then will need to interpolate.
+                scalar newSize = 0;
+                cellSizeFunctions_[surfI-1].cellSize(points[pI], newSize);
+                v->value(newSize);
+            }
+        }
     }
 
+    scalar factor = 1.0;
+    label maxIteration = 1;
+
+    for (label iteration = 0; iteration < maxIteration; ++iteration)
+    {
+        Info<< "Iteration : " << iteration << endl;
+
+        label nRefined = refineTriangulation(factor);
+
+        Info<< "    Number of cells refined in refinement iteration : "
+            << nRefined << nl << endl;
+
+        if (nRefined <= 0 && iteration != 0)
+        {
+            break;
+        }
+
+        factor *= 1.5;
+    }
+
+    writeRefinementTriangulation();
+
+    Info<< nl << "Refinement triangulation information: " << endl;
+    Info<< "    Number of vertices: " << label(T_.number_of_vertices()) << endl;
+    Info<< "    Number of cells   : "
+        << label(T_.number_of_finite_cells()) << endl;
+    Info<< "    Number of faces   : "
+        << label(T_.number_of_finite_facets()) << endl;
+    Info<< "    Number of edges   : "
+        << label(T_.number_of_finite_edges()) << endl;
+    Info<< "    Dimensionality    : " << label(T_.dimension()) << nl << endl;
+
+
     // Sort cellSizeFunctions_ and surfaces_ by priority.  Cut off any surfaces
     // where priority < defaultPriority_
 
+
     labelList sortedIndices;
 
     sortedOrder(priorities, sortedIndices);
@@ -282,8 +696,40 @@ Foam::scalar Foam::cellSizeControlSurfaces::cellSize
 {
     scalar size = defaultCellSize_;
 
-//  bool anyFunctionFound = evalCellSizeFunctions(pt, size);
-    evalCellSizeFunctions(pt, size);
+    bool refinementTriangulationSwitch = true;
+
+    if (!refinementTriangulationSwitch)
+    {
+        evalCellSizeFunctions(pt, size);
+    }
+    else
+    {
+        Cell_handle ch = T_.locate
+        (
+            Point(pt.x(), pt.y(), pt.z()),
+            oldCellHandle_
+        );
+
+        oldCellHandle_ = ch;
+
+        pointFromPoint pA = topoint(ch->vertex(0)->point());
+        pointFromPoint pB = topoint(ch->vertex(1)->point());
+        pointFromPoint pC = topoint(ch->vertex(2)->point());
+        pointFromPoint pD = topoint(ch->vertex(3)->point());
+
+        tetPointRef tet(pA, pB, pC, pD);
+
+        scalarList bary;
+        tet.barycentric(pt, bary);
+
+        scalar value = 0;
+        forAll(bary, pI)
+        {
+            value += bary[pI]*ch->vertex(pI)->value();
+        }
+
+        size = value;
+    }
 
 //if (!anyFunctionFound)
 //{
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
index 9f522f0dfcf2d2121f15a5b02127bd6f0e72549b..de3e9d75c1147da334f6a9db9b624d63fb78d1bc 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/cellSizeControlSurfaces.H
@@ -37,9 +37,92 @@ SourceFiles
 
 #include "searchableSurfaces.H"
 #include "searchableSurfacesQueries.H"
+#include "conformationSurfaces.H"
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_3.h>
+#include <CGAL/Triangulation_vertex_base_with_info_3.h>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+template < class GT, class Vb = CGAL::Triangulation_vertex_base_3<GT> >
+class vertexWithInfo
+:
+    public Vb
+{
+public:
+
+    Foam::scalar value_;
+
+    Foam::tensor alignment_;
+
+    typedef typename Vb::Vertex_handle  Vertex_handle;
+    typedef typename Vb::Cell_handle    Cell_handle;
+    typedef typename Vb::Point          Point;
+
+    template < class TDS2 >
+    struct Rebind_TDS
+    {
+        typedef typename Vb::template Rebind_TDS<TDS2>::Other   Vb2;
+        typedef vertexWithInfo<GT, Vb2>                         Other;
+    };
+
+    vertexWithInfo()
+    :
+        Vb(),
+        value_(0.0),
+        alignment_(Foam::tensor::zero)
+    {}
+
+    explicit vertexWithInfo(const Point& p)
+    :
+        Vb(p),
+        value_(0.0),
+        alignment_(Foam::tensor::zero)
+    {}
+
+    vertexWithInfo(const Point& p, const Foam::scalar& value)
+    :
+        Vb(p),
+        value_(value),
+        alignment_(Foam::tensor::zero)
+    {}
+
+    vertexWithInfo
+    (
+        const Point& p,
+        const Foam::scalar& value,
+        const Foam::tensor& alignment
+    )
+    :
+        Vb(p),
+        value_(value),
+        alignment_(alignment)
+    {}
+
+
+    const Foam::scalar& value() const
+    {
+        return value_;
+    }
+
+    void value(const Foam::scalar& value)
+    {
+        value_ = value;
+    }
+
+    const Foam::tensor& alignment() const
+    {
+        return alignment_;
+    }
+
+    void alignment(const Foam::tensor& alignment)
+    {
+        alignment_ = alignment;
+    }
+};
+
+
 namespace Foam
 {
 
@@ -55,11 +138,29 @@ class cellSizeFunction;
 
 class cellSizeControlSurfaces
 {
+    typedef CGAL::Exact_predicates_inexact_constructions_kernel             K;
+    typedef CGAL::Triangulation_data_structure_3<vertexWithInfo<K> >        Tds;
+
+    typedef CGAL::Delaunay_triangulation_3<K, Tds, CGAL::Fast_location>
+        Delaunay;
+
+    typedef Delaunay::Cell_handle    Cell_handle;
+    typedef Delaunay::Vertex_handle  Vertex_handle;
+    typedef Delaunay::Locate_type    Locate_type;
+    typedef Delaunay::Point          Point;
+
+    Delaunay T_;
+
+    mutable Cell_handle oldCellHandle_;
+
+
     // Private data
 
         //- Reference to the searchableSurfaces object holding all geometry data
         const searchableSurfaces& allGeometry_;
 
+        const conformationSurfaces& geometryToConformTo_;
+
         //- Indices of surfaces in allGeometry that are to be conformed to
         labelList surfaces_;
 
@@ -84,6 +185,14 @@ class cellSizeControlSurfaces
             scalar& minSize
         ) const;
 
+        bool checkCoplanarTet(Cell_handle c, const scalar tol) const;
+
+        bool checkClosePoints(Cell_handle c, const scalar tol) const;
+
+        label refineTriangulation(const scalar factor);
+
+        void writeRefinementTriangulation();
+
         //- Disallow default bitwise copy construct
         cellSizeControlSurfaces(const cellSizeControlSurfaces&);
 
@@ -104,6 +213,7 @@ public:
         cellSizeControlSurfaces
         (
             const searchableSurfaces& allGeometry,
+            const conformationSurfaces& geometryToConformTo,
             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 127613362347607caaed2a085ec3c9c305918d3f..995d10fdc378838042123ad75d5a603831abc46d 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
@@ -56,8 +56,7 @@ Foam::cellSizeFunction::cellSizeFunction
         )
     ),
     coeffsDict_(subDict(type + "Coeffs")),
-    sideMode_(),
-    priority_(readLabel(cellSizeFunctionDict.lookup("priority")))
+    sideMode_()
 {
     word mode = cellSizeFunctionDict.lookup("mode");
 
@@ -77,7 +76,7 @@ Foam::cellSizeFunction::cellSizeFunction
         }
         else
         {
-            FatalErrorIn("cellSizeFunction::cellSizeFunction")
+            FatalErrorIn("searchableSurfaceControl::searchableSurfaceControl")
                 << "Unknown mode, expected: inside, outside or bothSides" << nl
                 << exit(FatalError);
         }
@@ -86,7 +85,7 @@ Foam::cellSizeFunction::cellSizeFunction
     {
         if (mode != "bothSides")
         {
-            WarningIn("cellSizeFunction::cellSizeFunction")
+            WarningIn("searchableSurfaceControl::searchableSurfaceControl")
                 << "surface does not support volumeType, defaulting mode to "
                 << "bothSides."
                 << endl;
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 1e6fd4442eb96d415aa7b3555b978cf2a04ba09e..58ee5d5e0fd18a7cf7d406378437562bb495fc10 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
@@ -59,9 +59,6 @@ class cellSizeFunction
 
 public:
 
-    //- Runtime type information
-    TypeName("cellSizeFunction");
-
     //- Surface side mode
     enum sideMode
     {
@@ -70,6 +67,9 @@ public:
         rmBothsides       // Control on both sides of a surface
     };
 
+    //- Runtime type information
+    TypeName("cellSizeFunction");
+
 
 protected:
 
@@ -97,9 +97,6 @@ protected:
         //- Mode of size specification, i.e. inside, outside or bothSides
         sideMode sideMode_;
 
-        //- Priority of this cellSizeFunction
-        label priority_;
-
 
 private:
 
@@ -162,11 +159,6 @@ public:
             return coeffsDict_;
         }
 
-        inline label priority() const
-        {
-            return priority_;
-        }
-
         //- Modify scalar argument to the cell size specified by function.
         //  Return a boolean specifying if the function was used, i.e. false if
         //  the point was not in range of the surface for a spatially varying
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.C
index d30cc2a5ffebe0efc12b7b8e36c7c6f68dcf1847..e8f09cf5f111d088cfb60838c3e53d7432147ca7 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.C
@@ -26,6 +26,7 @@ License
 #include "automatic.H"
 #include "addToRunTimeSelectionTable.H"
 #include "triSurfaceMesh.H"
+#include "vtkSurfaceWriter.H"
 #include "Time.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -36,6 +37,59 @@ namespace Foam
     addToRunTimeSelectionTable(cellSizeCalculationType, automatic, dictionary);
 }
 
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::automatic::smoothField(triSurfaceScalarField& surf)
+{
+    label nSmoothingIterations = 10;
+
+    for (label iter = 0; iter < nSmoothingIterations; ++iter)
+    {
+        const pointField& faceCentres = surface_.faceCentres();
+
+        forAll(surf, sI)
+        {
+            const labelList& faceFaces = surface_.faceFaces()[sI];
+
+            const point& fC = faceCentres[sI];
+            const scalar value = surf[sI];
+
+            scalar newValue = 0;
+            scalar totalDist = 0;
+
+            label nFaces = 0;
+
+            forAll(faceFaces, fI)
+            {
+                const label faceLabel = faceFaces[fI];
+                const point& faceCentre = faceCentres[faceLabel];
+
+                const scalar faceValue = surf[faceLabel];
+                const scalar distance = mag(faceCentre - fC);
+
+                newValue += faceValue/distance;
+
+                totalDist += 1.0/distance;
+
+                if (value < faceValue)
+                {
+                    nFaces++;
+                }
+            }
+
+            // Do not smooth out the peak values
+            if (nFaces == faceFaces.size())
+            {
+                //continue;
+            }
+
+            surf[sI] = newValue/totalDist;
+        }
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::automatic::automatic
@@ -90,7 +144,8 @@ Foam::triSurfaceScalarField Foam::automatic::load()
 
     if (readCurvature_)
     {
-        Info<< indent << "Reading curvature: " << curvatureFile_ << endl;
+        Info<< indent << "Reading curvature         : "
+            << curvatureFile_ << endl;
 
         triSurfacePointScalarField curvature
         (
@@ -174,7 +229,7 @@ Foam::triSurfaceScalarField Foam::automatic::load()
 
     if (readFeatureProximity_)
     {
-        Info<< indent << "Reading feature proximity: "
+        Info<< indent << "Reading feature proximity : "
             << featureProximityFile_ << endl;
 
         triSurfaceScalarField featureProximity
@@ -204,8 +259,34 @@ Foam::triSurfaceScalarField Foam::automatic::load()
         }
     }
 
+    smoothField(surfaceCellSize);
+
     surfaceCellSize.write();
 
+    debug = 1;
+
+    if (debug)
+    {
+        faceList faces(surface_.size());
+
+        forAll(surface_, fI)
+        {
+            faces[fI] = surface_.triSurface::operator[](fI).triFaceFace();
+        }
+
+        vtkSurfaceWriter().write
+        (
+            surface_.searchableSurface::time().constant()/"triSurface",
+            surfaceName_,
+            surface_.points(),
+            faces,
+            "cellSize",
+            surfaceCellSize,
+            false,
+            true
+        );
+    }
+
     return surfaceCellSize;
 }
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.H
index 04d8ed7ddb28c14730ac9c2bea77b0f0612c8fe9..4288176e8f3ddccd42dcf074cb5bd2f21d260756 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cellSizeControlSurfaces/surfaceCellSizeFunction/cellSizeCalculationType/automatic/automatic.H
@@ -85,6 +85,11 @@ private:
         const scalar maximumCellSize_;
 
 
+    // Private Member Functions
+
+        void smoothField(triSurfaceScalarField& surf);
+
+
 public:
 
     //- Runtime type information
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3DKernel.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3DKernel.H
new file mode 100644
index 0000000000000000000000000000000000000000..e80b3fb8f4b428ee42d4f739c582e4d429aafe35
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3DKernel.H
@@ -0,0 +1,62 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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
+    CGALTriangulation3DKernel
+
+Description
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CGALTriangulation3DKernel_H
+#define CGALTriangulation3DKernel_H
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "CGAL/Delaunay_triangulation_3.h"
+
+#ifdef CGAL_INEXACT
+
+    // Fast kernel using a double as the storage type but the triangulation may
+    // fail. Adding robust circumcentre traits
+    #include "CGAL/Exact_predicates_inexact_constructions_kernel.h"
+    typedef CGAL::Exact_predicates_inexact_constructions_kernel baseK;
+//    #include <CGAL/Robust_circumcenter_traits_3.h>
+    #include <CGAL/Robust_circumcenter_filtered_traits_3.h>
+//    typedef CGAL::Robust_circumcenter_traits_3<baseK>           K;
+    typedef CGAL::Robust_circumcenter_filtered_traits_3<baseK>  K;
+
+#else
+
+    // Very robust but expensive kernel
+    #include "CGAL/Exact_predicates_exact_constructions_kernel.h"
+    typedef CGAL::Exact_predicates_exact_constructions_kernel baseK;
+    typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3Ddefs.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3Ddefs.H
index 72d44618a21c589ead0275b7e47864c4ebea548f..4e7dd48c38c76ffe152bf7d194881540ca0c2381 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3Ddefs.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/CGALTriangulation3Ddefs.H
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Typedefs
     CGALTriangulation3Ddefs
 
@@ -43,76 +38,20 @@ Description
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-#include "CGAL/Delaunay_triangulation_3.h"
+#include "CGALTriangulation3DKernel.H"
 
 #include "indexedVertex.H"
 #include "indexedCell.H"
 
-#ifdef CGAL_INEXACT
-    // Fast kernel using a double as the storage type but the triangulation may
-    // fail.  Adding robust circumcentre traits
-    #include "CGAL/Exact_predicates_inexact_constructions_kernel.h"
-    #include <CGAL/Robust_circumcenter_traits_3.h>
-    typedef CGAL::Exact_predicates_inexact_constructions_kernel inexactK;
-    typedef CGAL::Robust_circumcenter_traits_3<inexactK>  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::indexedCell<K>       Cb;
 
-typedef CGAL::indexedVertex<K>          Vb;
-typedef CGAL::indexedCell<K>            Cb;
-
-typedef CGAL::Triangulation_data_structure_3<Vb, Cb>     Tds;
-typedef CGAL::Delaunay_triangulation_3<K, Tds, CGAL::Fast_location> Delaunay;
-
-typedef Delaunay::Vertex_handle    Vertex_handle;
-typedef Delaunay::Cell_handle      Cell_handle;
-typedef Delaunay::Point            Point;
-
-
-//- Spatial sort traits to use with a pair of point pointers and an integer.
-//  Taken from a post on the CGAL lists: 2010-01/msg00004.html by
-//  Sebastien Loriot (Geometry Factory).
-template<class Triangulation>
-struct Traits_for_spatial_sort
-:
-    public Triangulation::Geom_traits
-{
-    typedef typename Triangulation::Geom_traits Gt;
-
-    typedef std::pair<const typename Triangulation::Point*, int> Point_3;
-
-    struct Less_x_3
-    {
-        bool operator()(const Point_3& p, const Point_3& q) const
-        {
-            return typename Gt::Less_x_3()(*(p.first), *(q.first));
-        }
-    };
-
-    struct Less_y_3
-    {
-        bool operator()(const Point_3& p, const Point_3& q) const
-        {
-            return typename Gt::Less_y_3()(*(p.first), *(q.first));
-        }
-    };
-
-    struct Less_z_3
-    {
-        bool operator()(const Point_3& p, const Point_3& q) const
-        {
-            return typename Gt::Less_z_3()(*(p.first), *(q.first));
-        }
-    };
-
-    Less_x_3  less_x_3_object () const {return Less_x_3();}
-    Less_y_3  less_y_3_object () const {return Less_y_3();}
-    Less_z_3  less_z_3_object () const {return Less_z_3();}
-};
+typedef CGAL::Compact_location     CompactLocator;
+typedef CGAL::Fast_location        FastLocator;
 
+typedef CGAL::Triangulation_data_structure_3<Vb, Cb>           Tds;
+typedef CGAL::Delaunay_triangulation_3<K, Tds, CompactLocator> Delaunay;
+typedef CGAL::Delaunay_triangulation_3<K, Tds, FastLocator>    CellSizeDelaunay;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
index de23690ea43b26ca788d49724cb42e2d17a6e192..8f229fdbc14c6d65f94c303780b5a0d175b604ac 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C
@@ -27,8 +27,11 @@ License
 #include "initialPointsMethod.H"
 #include "relaxationModel.H"
 #include "faceAreaWeightModel.H"
-#include "backgroundMeshDecomposition.H"
 #include "meshSearch.H"
+#include "vectorTools.H"
+#include "IOmanip.H"
+#include "indexedCellChecks.H"
+
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -72,7 +75,7 @@ Foam::scalar Foam::conformalVoronoiMesh::requiredSize
             << exit(FatalError) << endl;
     }
 
-    cellSizeHits.append(cellSizeControl().cellSize(pt));
+    cellSizeHits.append(cellShapeControls().cellSize(pt));
 
     // Primary alignment
 
@@ -135,7 +138,7 @@ Foam::scalar Foam::conformalVoronoiMesh::requiredSize
 
             cellSizeHits.append
             (
-                cellSizeControl().cellSize(hitPt)
+                cellShapeControls().cellSize(hitPt)
             );
 
             totalDist += spokeHitDistance;
@@ -161,7 +164,7 @@ Foam::scalar Foam::conformalVoronoiMesh::requiredSize
 
             cellSizeHits.append
             (
-                cellSizeControl().cellSize(hitPt)
+                cellShapeControls().cellSize(hitPt)
             );
 
             totalDist += spokeHitDistance;
@@ -176,7 +179,7 @@ Foam::scalar Foam::conformalVoronoiMesh::requiredSize
     }
 
     return cellSize/cellSizeHits.size();
-    //return cellSizeControl().cellSize(pt);
+    //return cellShapeControls().cellSize(pt);
 }
 
 
@@ -355,14 +358,12 @@ Foam::tensor Foam::conformalVoronoiMesh::requiredAlignment
 }
 
 
-void Foam::conformalVoronoiMesh::insertPoints
+void Foam::conformalVoronoiMesh::insertInternalPoints
 (
     List<Point>& points,
     bool distribute
 )
 {
-    label preInsertionSize(number_of_vertices());
-
     label nPoints = points.size();
 
     if (Pstream::parRun())
@@ -374,37 +375,12 @@ void Foam::conformalVoronoiMesh::insertPoints
 
     if (Pstream::parRun() && distribute)
     {
-        label preDistributionSize(points.size());
-
-        DynamicList<Foam::point> transferPoints;
-
-        DynamicList<Point> pointsOnProcessor;
-
-        for
-        (
-            List<Point>::iterator pit = points.begin();
-            pit != points.end();
-            ++pit
-        )
-        {
-            Foam::point p(topoint(*pit));
-
-            if (!positionOnThisProc(p))
-            {
-                transferPoints.append(p);
-            }
-            else
-            {
-                pointsOnProcessor.append(*pit);
-            }
-        }
+        List<Foam::point> transferPoints(points.size());
 
-        points.setSize(pointsOnProcessor.size());
-        forAll(pointsOnProcessor, pI)
+        forAll(points, pI)
         {
-            points[pI] = pointsOnProcessor[pI];
+            transferPoints[pI] = topoint(points[pI]);
         }
-        pointsOnProcessor.clear();
 
         // Send the points that are not on this processor to the appropriate
         // place
@@ -413,41 +389,7 @@ void Foam::conformalVoronoiMesh::insertPoints
             decomposition_().distributePoints(transferPoints)
         );
 
-        const label oldSize = points.size();
-
-        points.setSize(oldSize + transferPoints.size());
-
-        forAll(transferPoints, tPI)
-        {
-            points[tPI + oldSize] = toPoint(transferPoints[tPI]);
-        }
-
-        label sizeChange = preDistributionSize - points.size();
-
-        // if (mag(sizeChange) > 0)
-        // {
-        //     Pout<< "    distribution points size change " << sizeChange
-        //         << endl;
-        // }
-
-        label totalMagSizeChange = returnReduce
-        (
-            mag(sizeChange), sumOp<label>()
-        );
-
-        if (totalMagSizeChange > 0)
-        {
-            Info<< "    distribution points size change total "
-                << totalMagSizeChange/2
-                << endl;
-        }
-
-        nPoints = points.size();
-
-        reduce(nPoints, sumOp<label>());
-
-        Info<< "    " << nPoints
-            << " points to insert after distribution..." << endl;
+        map().distribute(points);
     }
 
     label nVert = number_of_vertices();
@@ -455,25 +397,18 @@ void Foam::conformalVoronoiMesh::insertPoints
     // using the range insert (faster than inserting points one by one)
     insert(points.begin(), points.end());
 
-//     Info<< "USING INDIVIDUAL INSERTION TO DETECT FAILURE" << endl;
-//     for
-//     (
-//         List<Point>::iterator pit=points.begin();
-//         pit != points.end();
-//         ++pit
-//     )
-//     {
-//         insertPoint(topoint(*pit), Vb::vtInternal);
-//     }
-
-    label nInserted(number_of_vertices() - preInsertionSize);
+    label nInserted(number_of_vertices() - nVert);
 
     if (Pstream::parRun())
     {
         reduce(nInserted, sumOp<label>());
     }
 
-    Info<< "    " << nInserted << " points inserted" << endl;
+    Info<< "    " << nInserted << " points inserted"
+        << ", failed to insert " << nPoints - nInserted
+        << " ("
+        << 100.0*(nPoints - nInserted)/nInserted
+        << " %)"<< endl;
 
     for
     (
@@ -484,7 +419,8 @@ void Foam::conformalVoronoiMesh::insertPoints
     {
         if (vit->uninitialised())
         {
-            vit->index() = nVert++;
+            vit->index() = getNewVertexIndex();
+            vit->type() = Vb::vtInternal;
         }
     }
 }
@@ -492,30 +428,22 @@ void Foam::conformalVoronoiMesh::insertPoints
 
 void Foam::conformalVoronoiMesh::insertPoints
 (
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types,
+    List<Vb>& vertices,
     bool distribute
 )
 {
-    // The pts, indices and types lists must be intact and up-to-date at the
-    // end of this function as they may also be used by other functions
-    // subsequently.
-
     if (Pstream::parRun() && distribute)
     {
-        // The link between vertices that form the boundary via pairs cannot be
-        // strict because both points may end up on different processors.  The
-        // only important thing is that each vertex knows its own role.
-        // Therefore, index and type are set to 0 or 1, then on the destination
-        // processor add back the new index to both.
+        const label preDistributionSize = vertices.size();
+
+        List<Foam::point> pts(preDistributionSize);
 
-        // Each of points generated in this process are pair points, so there
-        // is no risk of underflowing "type".
+        forAll(vertices, vI)
+        {
+            const Foam::point& pt = topoint(vertices[vI].point());
 
-        // Pout<< "Points before "
-        //     << pts.size() << " " << indices.size() << " " << types.size()
-        //     << endl;
+            pts[vI] = pt;
+        }
 
         // Distribute points to their appropriate processor
         autoPtr<mapDistribute> map
@@ -523,97 +451,71 @@ void Foam::conformalVoronoiMesh::insertPoints
             decomposition_().distributePoints(pts)
         );
 
-        map().distribute(indices);
-        map().distribute(types);
+        map().distribute(vertices);
 
-        // Pout<< "Points after "
-        //     << pts.size() << " " << indices.size() << " " << types.size()
-        //     << endl;
-
-        // Info<< returnReduce(pts.size(), sumOp<label>())
-        //     << " points in total" << endl;
+        forAll(vertices, vI)
+        {
+            vertices[vI].procIndex() = Pstream::myProcNo();
+        }
     }
-//
-//    forAll(pts, pI)
-//    {
-//        // creation of points and indices is done assuming that it will be
-//        // relative to the instantaneous number_of_vertices() at insertion.
-//
-//        label type = types[pI];
-//
-//        if (type > Vb::vtFar)
-//        {
-//            // This is a member of a point pair, don't use the type directly
-//            // (note that this routine never gets called for referredPoints
-//            //  so type will never be -procI)
-//            type += number_of_vertices();
-//        }
-//
-//        insertPoint
-//        (
-//            pts[pI],
-//            indices[pI] + number_of_vertices(),
-//            type
-//        );
-//    }
 
     rangeInsertWithInfo
     (
-        pts.begin(),
-        pts.end(),
-        *this,
-        indices,
-        types
+        vertices.begin(),
+        vertices.end(),
+        true
     );
 }
 
 
 void Foam::conformalVoronoiMesh::insertSurfacePointPairs
 (
-    const List<pointIndexHit>& surfaceHits,
-    const List<label>& hitSurfaces,
+    const pointIndexHitAndFeatureList& surfaceHits,
     const fileName fName
 )
 {
-    if (surfaceHits.size() != hitSurfaces.size())
-    {
-        FatalErrorIn("Foam::conformalVoronoiMesh::insertPointPairs")
-            << "surfaceHits and hitSurfaces are not the same size. Sizes "
-            << surfaceHits.size() << ' '
-            << hitSurfaces.size()
-            << exit(FatalError);
-    }
-
-    DynamicList<Foam::point> pts;
-    DynamicList<label> indices;
-    DynamicList<label> types;
+    DynamicList<Vb> pts(2.0*surfaceHits.size());
 
     forAll(surfaceHits, i)
     {
         vectorField norm(1);
 
-        allGeometry_[hitSurfaces[i]].getNormal
+        const pointIndexHit surfaceHit = surfaceHits[i].first();
+        const label featureIndex = surfaceHits[i].second();
+
+        allGeometry_[featureIndex].getNormal
         (
-            List<pointIndexHit>(1, surfaceHits[i]),
+            List<pointIndexHit>(1, surfaceHit),
             norm
         );
 
         const vector& normal = norm[0];
 
-        const Foam::point& surfacePt(surfaceHits[i].hitPoint());
+        const Foam::point& surfacePt(surfaceHit.hitPoint());
 
-        createPointPair
-        (
-            pointPairDistance(surfacePt),
-            surfacePt,
-            normal,
-            pts,
-            indices,
-            types
-        );
+        if (geometryToConformTo_.isBaffle(featureIndex))
+        {
+            createBafflePointPair
+            (
+                pointPairDistance(surfacePt),
+                surfacePt,
+                normal,
+                pts
+            );
+        }
+        else
+        {
+            createPointPair
+            (
+                pointPairDistance(surfacePt),
+                surfacePt,
+                normal,
+                pts
+            );
+        }
     }
 
-    insertPoints(pts, indices, types, true);
+    insertPoints(pts, true);
 
     if (cvMeshControls().objOutput() && fName != fileName::null)
     {
@@ -624,35 +526,25 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
 
 void Foam::conformalVoronoiMesh::insertEdgePointGroups
 (
-    const List<pointIndexHit>& edgeHits,
-    const labelList& featuresHit,
+    const pointIndexHitAndFeatureList& edgeHits,
     const fileName fName
 )
 {
-    if (edgeHits.size() != featuresHit.size())
-    {
-        FatalErrorIn("Foam::conformalVoronoiMesh::insertEdgePointGroups")
-            << "edgeHits and featuresHit are not the same size. Sizes "
-            << edgeHits.size() << ' '
-            << featuresHit.size()
-            << exit(FatalError);
-    }
-
-    DynamicList<Foam::point> pts;
-    DynamicList<label> indices;
-    DynamicList<label> types;
+    DynamicList<Vb> pts(3.0*edgeHits.size());
 
     forAll(edgeHits, i)
     {
         const extendedFeatureEdgeMesh& feMesh
         (
-            geometryToConformTo_.features()[featuresHit[i]]
+            geometryToConformTo_.features()[edgeHits[i].second()]
         );
 
-        createEdgePointGroup(feMesh, edgeHits[i], pts, indices, types);
+        createEdgePointGroup(feMesh, edgeHits[i].first(), pts);
     }
 
-    insertPoints(pts, indices, types, true);
+    pts.shrink();
+
+    insertPoints(pts, true);
 
     if (cvMeshControls().objOutput() && fName != fileName::null)
     {
@@ -680,20 +572,6 @@ bool Foam::conformalVoronoiMesh::nearFeaturePt(const Foam::point& pt) const
 }
 
 
-void Foam::conformalVoronoiMesh::reset(const bool distribute)
-{
-    this->clear();
-
-    reinsertBoundingPoints();
-
-    // Reinsert feature points, distributing them as necessary.
-    reinsertFeaturePoints(distribute);
-    //insertFeaturePoints();
-
-    startOfInternalPoints_ = number_of_vertices();
-}
-
-
 void Foam::conformalVoronoiMesh::insertInitialPoints()
 {
     Info<< nl << "Inserting initial points" << endl;
@@ -706,13 +584,43 @@ void Foam::conformalVoronoiMesh::insertInitialPoints()
 
     // Assume that the initial points method made the correct decision for
     // which processor each point should be on, so give distribute = false
-    insertPoints(initPts, false);
+    insertInternalPoints(initPts);
+}
 
-    if (cvMeshControls().objOutput())
+
+Foam::scalar Foam::conformalVoronoiMesh::calculateLoadUnbalance() const
+{
+    label nRealVertices = 0;
+
+    for
+    (
+        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
     {
-        writePoints("initialPoints.obj", true);
+        // Only store real vertices that are not feature vertices
+        if (vit->real() && !vit->featurePoint())
+        {
+            nRealVertices++;
+        }
     }
 
+    scalar globalNRealVertices = returnReduce
+    (
+        nRealVertices,
+        sumOp<label>()
+    );
+
+    scalar unbalance = returnReduce
+    (
+        mag(1.0 - nRealVertices/(globalNRealVertices/Pstream::nProcs())),
+        maxOp<scalar>()
+    );
+
+    Info<< "    Processor unbalance " << unbalance << endl;
+
+    return unbalance;
 }
 
 
@@ -729,52 +637,29 @@ bool Foam::conformalVoronoiMesh::distributeBackground()
 
     label iteration = 0;
 
+    scalar previousLoadUnbalance = 0;
+
     while (true)
     {
-        label nRealVertices = 0;
+        scalar maxLoadUnbalance = calculateLoadUnbalance();
 
-        for
+        if
         (
-            Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-            vit != finite_vertices_end();
-            vit++
+            maxLoadUnbalance <= cvMeshControls().maxLoadUnbalance()
+         || maxLoadUnbalance <= previousLoadUnbalance
         )
-        {
-            // Only store real vertices that are not feature vertices
-            if (vit->real() && vit->index() >= startOfInternalPoints_)
-            {
-                nRealVertices++;
-            }
-        }
-
-        scalar globalNRealVertices = returnReduce
-        (
-            nRealVertices,
-            sumOp<label>()
-        );
-
-        scalar unbalance = returnReduce
-        (
-            mag(1.0 - nRealVertices/(globalNRealVertices/Pstream::nProcs())),
-            maxOp<scalar>()
-        );
-
-        Info<< "    Processor unbalance " << unbalance << endl;
-
-        if (unbalance <= cvMeshControls().maxLoadUnbalance())
         {
             // If this is the first iteration, return false, if it was a
             // subsequent one, return true;
             return iteration != 0;
         }
 
+        previousLoadUnbalance = maxLoadUnbalance;
+
         Info<< "    Total number of vertices before redistribution "
             << returnReduce(label(number_of_vertices()), sumOp<label>())
             << endl;
 
-        // Pout<< "    Real vertices before distribution "
-        //     << nRealVertices << endl;
-
         const fvMesh& bMesh = decomposition_().mesh();
 
         volScalarField cellWeights
@@ -794,42 +679,36 @@ bool Foam::conformalVoronoiMesh::distributeBackground()
 
         meshSearch cellSearch(bMesh, polyMesh::FACEPLANES);
 
-        List<DynamicList<Foam::point> > cellVertices(bMesh.nCells());
-        List<DynamicList<label> > cellVertexIndices(bMesh.nCells());
-        List<DynamicList<label> > cellVertexTypes(bMesh.nCells());
+        labelList cellVertices(bMesh.nCells(), 0);
 
         for
         (
             Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
             vit != finite_vertices_end();
-            vit++
+            ++vit
         )
         {
             // Only store real vertices that are not feature vertices
-            if (vit->real() && vit->index() >= startOfInternalPoints_)
+            if (vit->real() && !vit->featurePoint())
             {
-                Foam::point v = topoint(vit->point());
+                pointFromPoint v = topoint(vit->point());
 
                 label cellI = cellSearch.findCell(v);
 
                 if (cellI == -1)
                 {
-                    // Pout<< "findCell conformalVoronoiMesh::distribute "
-                    //     << "findCell "
-                    //     << vit->type() << " "
-                    //     << vit->index() << " "
-                    //     << v << " "
-                    //     << cellI
-                    //     << " find nearest cellI ";
+//                     Pout<< "findCell conformalVoronoiMesh::distribute "
+//                         << "findCell "
+//                         << vit->type() << " "
+//                         << vit->index() << " "
+//                         << v << " "
+//                         << cellI
+//                         << " find nearest cellI ";
 
                     cellI = cellSearch.findNearestCell(v);
-
-                    Pout<< cellI << endl;
                 }
 
-                cellVertices[cellI].append(topoint(vit->point()));
-                cellVertexIndices[cellI].append(vit->index());
-                cellVertexTypes[cellI].append(vit->type());
+                cellVertices[cellI]++;
             }
         }
 
@@ -840,76 +719,150 @@ bool Foam::conformalVoronoiMesh::distributeBackground()
             // the sum of the normalised weight field.
             cellWeights.internalField()[cI] = max
             (
-                cellVertices[cI].size(),
+                cellVertices[cI],
                 1e-2
             );
         }
 
         autoPtr<mapDistributePolyMesh> mapDist = decomposition_().distribute
         (
-            cellWeights,
-            cellVertices,
-            cellVertexIndices,
-            cellVertexTypes
+            cellWeights
         );
 
-        // Reset the entire tessellation
-        reset(true);
+        cellShapeControl_.shapeControlMesh().distribute(decomposition_);
 
-        timeCheck("Distribution performed");
+        distribute();
 
-        Info<< nl << "    Inserting distributed tessellation" << endl;
+        timeCheck("After distribute");
 
-        DynamicList<Foam::point> pointsToInsert;
-        DynamicList<label> indices;
-        DynamicList<label> types;
+        iteration++;
+    }
 
-        forAll(cellVertices, cI)
-        {
-            forAll(cellVertices[cI], cVPI)
-            {
-                pointsToInsert.append(cellVertices[cI][cVPI]);
+    return true;
+}
 
-                // All insertions relative to index of zero
-                indices.append(0);
 
-                label type = cellVertexTypes[cI][cVPI];
+void Foam::conformalVoronoiMesh::distribute()
+{
+    if (!Pstream::parRun())
+    {
+        return ;
+    }
 
-                if (type > Vb::vtFar)
-                {
-                    // This is a member of a point pair, don't use the type
-                    // directly, make type relative to the index in preparation
-                    // for insertion.
+    autoPtr<mapDistribute> mapDist =
+        DistributedDelaunayMesh<Delaunay>::distribute(decomposition_());
 
-                    type -= cellVertexIndices[cI][cVPI];
-                }
+    DynamicList<Foam::point> points(number_of_vertices());
+    DynamicList<Foam::indexedVertexEnum::vertexType> types
+    (
+        number_of_vertices()
+    );
+    DynamicList<scalar> sizes(number_of_vertices());
+    DynamicList<tensor> alignments(number_of_vertices());
 
-                types.append(type);
-            }
+    for
+    (
+        Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->real())
+        {
+            points.append(topoint(vit->point()));
+            types.append(vit->type());
+            sizes.append(vit->targetCellSize());
+            alignments.append(vit->alignment());
         }
+    }
 
-        // Assume that the distribution made the correct decision for which
-        // processor each point should be on, so give distribute = false
-        insertPoints(pointsToInsert, indices, types, false);
+    mapDist().distribute(points);
+    mapDist().distribute(types);
+    mapDist().distribute(sizes);
+    mapDist().distribute(alignments);
 
-        Info<< "    Total number of vertices after redistribution "
-            << returnReduce(label(number_of_vertices()), sumOp<label>())
-            << endl;
+    // Reset the entire tessellation
+    DelaunayMesh<Delaunay>::reset();
 
-        // Pout<< "    Real vertices after distribution "
-        //     << label(number_of_vertices() - 8) << endl;
+    Info<< nl << "    Inserting distributed tessellation" << endl;
 
-        if (cvMeshControls().objOutput())
+    // Internal points have to be inserted first
+
+    DynamicList<Vb> verticesToInsert(points.size());
+
+    forAll(points, pI)
+    {
+        verticesToInsert.append
+        (
+            Vb
+            (
+                toPoint<Point>(points[pI]),
+                -1,
+                types[pI],
+                Pstream::myProcNo()
+            )
+        );
+
+        verticesToInsert.last().targetCellSize() = sizes[pI];
+        verticesToInsert.last().alignment() = alignments[pI];
+    }
+
+    this->rangeInsertWithInfo
+    (
+        verticesToInsert.begin(),
+        verticesToInsert.end(),
+        true
+    );
+
+    Info<< "    Total number of vertices after redistribution "
+        << returnReduce
+           (
+               label(number_of_vertices()), sumOp<label>()
+           )
+        << endl;
+}
+
+
+void Foam::conformalVoronoiMesh::buildCellSizeAndAlignmentMesh()
+{
+    cellShapeControl_.initialMeshPopulation(decomposition_);
+
+    cellShapeControlMesh& cellSizeMesh = cellShapeControl_.shapeControlMesh();
+
+    if (Pstream::parRun())
+    {
+        cellSizeMesh.distribute(decomposition_);
+    }
+
+    label nMaxIter = 2;
+
+    for (label i = 0; i < nMaxIter; ++i)
+    {
+        label nAdded = cellShapeControl_.refineMesh(decomposition_);
+        reduce(nAdded, sumOp<label>());
+
+//        label nRemoved = cellShapeControl_.shapeControlMesh().removePoints();
+
+        if (Pstream::parRun())
         {
-            writePoints("distributedPoints.obj", true);
+            cellSizeMesh.distribute(decomposition_);
         }
 
-        timeCheck("After distribute");
+        if (nAdded == 0)
+        {
+            break;
+        }
 
-        iteration++;
+        Info<< "    Iteration " << i << ": Added = " << nAdded << " points"
+            << endl;
     }
 
-    return true;
+    cellShapeControl_.smoothMesh();
+
+    Info<< "Background cell size and alignment mesh:" << endl;
+    cellSizeMesh.printInfo(Info);
+
+//    cellSizeMesh.write();
 }
 
 
@@ -941,41 +894,48 @@ void Foam::conformalVoronoiMesh::storeSizesAndAlignments
     const List<Point>& storePts
 )
 {
-    timeCheck("Start of storeSizesAndAlignments");
-
-    Info << nl << "Store size and alignment" << endl;
-
-    sizeAndAlignmentLocations_.setSize(storePts.size());
-
-    storedSizes_.setSize(sizeAndAlignmentLocations_.size());
-
-    storedAlignments_.setSize(sizeAndAlignmentLocations_.size());
-
-    label i = 0;
-
-    checkCellSizing();
-
-    for
-    (
-        List<Point>::const_iterator pit = storePts.begin();
-        pit != storePts.end();
-        ++pit
-    )
-    {
-        sizeAndAlignmentLocations_[i] = topoint(*pit);
-
-        storedSizes_[i] = requiredSize(sizeAndAlignmentLocations_[i]);
-
-        storedAlignments_[i] = requiredAlignment(sizeAndAlignmentLocations_[i]);
-
-        i++;
-    }
-
-    timeCheck("Sizes and alignments calculated, build tree");
-
-    buildSizeAndAlignmentTree();
-
-    timeCheck("Size and alignment tree built");
+//    timeCheck("Start of storeSizesAndAlignments");
+//
+//    Info << nl << "Store size and alignment" << endl;
+//
+//    sizeAndAlignmentLocations_.setSize(storePts.size());
+//
+//    storedSizes_.setSize(sizeAndAlignmentLocations_.size());
+//
+//    storedAlignments_.setSize(sizeAndAlignmentLocations_.size());
+//
+//    label i = 0;
+//
+//    //checkCellSizing();
+//
+//    for
+//    (
+//        List<Point>::const_iterator pit = storePts.begin();
+//        pit != storePts.end();
+//        ++pit
+//    )
+//    {
+//        pointFromPoint pt = topoint(*pit);
+//
+////        storedAlignments_[i] = requiredAlignment(pt);
+////
+////        storedSizes_[i] = cellShapeControls().cellSize(pt);
+//
+//        cellShapeControls().cellSizeAndAlignment
+//        (
+//            pt,
+//            storedSizes_[i],
+//            storedAlignments_[i]
+//        );
+//
+//        i++;
+//    }
+//
+//    timeCheck("Sizes and alignments calculated, build tree");
+//
+//    buildSizeAndAlignmentTree();
+//
+//    timeCheck("Size and alignment tree built");
 }
 
 
@@ -1016,9 +976,51 @@ Foam::conformalVoronoiMesh::sizeAndAlignmentTree() const
 
 void Foam::conformalVoronoiMesh::setVertexSizeAndAlignment()
 {
-    Info<< nl << "Looking up target cell alignment and size" << endl;
+//    Info<< nl << "Looking up target cell alignment and size" << endl;
+//
+//    const indexedOctree<treeDataPoint>& tree = sizeAndAlignmentTree();
+//
+//    for
+//    (
+//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+//        vit != finite_vertices_end();
+//        vit++
+//    )
+//    {
+//        if
+//        (
+//            vit->internalOrBoundaryPoint()
+//         || vit->referredInternalOrBoundaryPoint()
+//        )
+//        {
+//            pointFromPoint pt = topoint(vit->point());
+//
+//            pointIndexHit info = tree.findNearest(pt, sqr(GREAT));
+//
+//            if (info.hit())
+//            {
+//                vit->alignment() = storedAlignments_[info.index()];
+//
+//                vit->targetCellSize() = storedSizes_[info.index()];
+//            }
+//            else
+//            {
+//                WarningIn
+//                (
+//                    "void "
+//                    "Foam::conformalVoronoiMesh::setVertexSizeAndAlignment()"
+//                )
+//                    << "Point " << pt << " did not find a nearest point "
+//                    << " for alignment and size lookup." << endl;
+//
+//                vit->alignment() = cellShapeControls().cellAlignment(pt);
+//
+//                vit->targetCellSize() = cellShapeControls().cellSize(pt);
+//            }
+//        }
+//    }
 
-    const indexedOctree<treeDataPoint>& tree = sizeAndAlignmentTree();
+    Info<< nl << "Calculating target cell alignment and size" << endl;
 
     for
     (
@@ -1027,57 +1029,23 @@ void Foam::conformalVoronoiMesh::setVertexSizeAndAlignment()
         vit++
     )
     {
-        if
-        (
-            vit->internalOrBoundaryPoint()
-         || vit->referredInternalOrBoundaryPoint()
-        )
+        if (vit->internalOrBoundaryPoint())
         {
-            Foam::point pt(topoint(vit->point()));
+            pointFromPoint pt = topoint(vit->point());
 
-            pointIndexHit info = tree.findNearest(pt, sqr(GREAT));
-
-            if (info.hit())
-            {
-                vit->alignment() = storedAlignments_[info.index()];
-
-                vit->targetCellSize() = storedSizes_[info.index()];
-            }
-            else
-            {
-                WarningIn
-                (
-                    "void "
-                    "Foam::conformalVoronoiMesh::setVertexSizeAndAlignment()"
-                )
-                    << "Point " << pt << " did not find a nearest point "
-                    << " for alignment and size lookup." << endl;
+            cellShapeControls().cellSizeAndAlignment
+            (
+                pt,
+                vit->targetCellSize(),
+                vit->alignment()
+            );
 
-                vit->alignment() = requiredAlignment(pt);
+//            vit->alignment() = tensor(1,0,0,0,1,0,0,0,1);
+            //vit->alignment() = requiredAlignment(pt);
 
-                vit->targetCellSize() = cellSizeControl().cellSize(pt);
-            }
+            //vit->targetCellSize() = cellShapeControls().cellSize(pt);
         }
     }
-
-    // Info<< nl << "Calculating target cell alignment and size" << endl;
-
-    // for
-    // (
-    //     Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-    //     vit != finite_vertices_end();
-    //     vit++
-    // )
-    // {
-    //     if (vit->internalOrBoundaryPoint())
-    //     {
-    //         point pt(topoint(vit->point()));
-
-    //         vit->alignment() = requiredAlignment(pt);
-
-    //         vit->targetCellSize() = targetCellSize(pt);
-    //     }
-    // }
 }
 
 
@@ -1100,7 +1068,7 @@ Foam::face Foam::conformalVoronoiMesh::buildDualFace
 
     do
     {
-        if (cc1->farCell() || cc2->farCell())
+        if (cc1->hasFarPoint() || cc2->hasFarPoint())
         {
             Cell_handle c = eit->first;
             Vertex_handle vA = c->vertex(eit->second);
@@ -1138,6 +1106,8 @@ Foam::face Foam::conformalVoronoiMesh::buildDualFace
 
     } while (cc1 != ccStart);
 
+    verticesOnFace.shrink();
+
     if (verticesOnFace.size() >= 3 && nUniqueVertices < 3)
     {
         // There are not enough unique vertices on this face to
@@ -1172,7 +1142,7 @@ Foam::label Foam::conformalVoronoiMesh::maxFilterCount
 
     do
     {
-        if (cc->farCell())
+        if (cc->hasFarPoint())
         {
             Cell_handle c = eit->first;
             Vertex_handle vA = c->vertex(eit->second);
@@ -1215,14 +1185,14 @@ bool Foam::conformalVoronoiMesh::ownerAndNeighbour
 
     label dualCellIndexA = vA->index();
 
-    if (!vA->internalOrBoundaryPoint())
+    if (!vA->internalOrBoundaryPoint() || vA->referred())
     {
         dualCellIndexA = -1;
     }
 
     label dualCellIndexB = vB->index();
 
-    if (!vB->internalOrBoundaryPoint())
+    if (!vB->internalOrBoundaryPoint() || vB->referred())
     {
         dualCellIndexB = -1;
     }
@@ -1289,7 +1259,7 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
     const dictionary& cvMeshDict
 )
 :
-    Delaunay(),
+    DistributedDelaunayMesh<Delaunay>(),
     runTime_(runTime),
     rndGen_(64293*Pstream::myProcNo()),
     cvMeshControls_(cvMeshDict),
@@ -1313,12 +1283,13 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
         allGeometry_,
         cvMeshDict.subDict("surfaceConformation")
     ),
-    cellSizeControl_
+    cellShapeControl_
     (
+        runTime_,
+        cvMeshDict.subDict("motionControl"),
         allGeometry_,
-        cvMeshDict.subDict("motionControl")
+        geometryToConformTo_
     ),
-    startOfInternalPoints_(0),
     limitBounds_(),
     featureVertices_(),
     featurePointLocations_(),
@@ -1354,67 +1325,112 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
     ),
     decomposition_()
 {
+    if (cvMeshControls().objOutput())
+    {
+        geometryToConformTo_.writeFeatureObj("cvMesh");
+    }
+
     if (Pstream::parRun())
     {
         decomposition_.reset
         (
             new backgroundMeshDecomposition
             (
-                cvMeshDict.subDict("backgroundMeshDecomposition"),
-                *this
+                runTime_,
+                rndGen_,
+                geometryToConformTo_,
+                cvMeshDict.subDict("backgroundMeshDecomposition")
             )
         );
     }
 
-    if (cvMeshControls().objOutput())
-    {
-        geometryToConformTo_.writeFeatureObj("cvMesh");
-    }
+    buildCellSizeAndAlignmentMesh();
 
-    insertBoundingPoints();
+    insertInitialPoints();
 
     insertFeaturePoints();
 
-    startOfInternalPoints_ = number_of_vertices();
+    setVertexSizeAndAlignment();
+
+    // Test for full containment
+    {
+        cellShapeControlMesh& cellSizeMesh =
+            cellShapeControl_.shapeControlMesh();
+
+        DynamicList<Foam::point> pts(number_of_vertices());
+
+        for
+        (
+            Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+            vit != finite_vertices_end();
+            ++vit
+        )
+        {
+            if (vit->internalOrBoundaryPoint())
+            {
+                pts.append(topoint(vit->point()));
+            }
+        }
+
+        boundBox bb(pts);
+
+        boundBox cellSizeMeshBb = cellSizeMesh.bounds();
+
+        bool fullyContained = true;
+
+        if (!cellSizeMeshBb.contains(bb))
+        {
+            Pout<< "Triangulation not fully contained in cell size mesh."
+                << endl;
+
+            Pout<< "Cell Size Mesh Bounds = " << cellSizeMesh.bounds() << endl;
+            Pout<< "cvMesh Bounds         = " << bb << endl;
+
+            fullyContained = false;
+        }
+
+        reduce(fullyContained, andOp<unsigned int>());
+
+        Info<< "Triangulation is "
+            << (fullyContained ? "fully" : "not fully")
+            << " contained in the cell size mesh"
+            << endl;
+    }
 
-    insertInitialPoints();
 
     // Improve the guess that the backgroundMeshDecomposition makes with the
     // initial positions.  Use before building the surface conformation to
     // better balance the surface conformation load.
     distributeBackground();
 
-//    conformToSurface();
-
-    buildSurfaceConformation(rmCoarse);
+    buildSurfaceConformation();
 
     // The introduction of the surface conformation may have distorted the
     // balance of vertices, distribute if necessary.
-    if (distributeBackground())
-    {
-        // distributeBackground has destroyed all referred vertices, so the
-        // parallel interface needs to be rebuilt.
-        buildParallelInterface("rebuild");
-    }
+    distributeBackground();
 
     // Do not store the surface conformation until after it has been
     // (potentially) redistributed.
     storeSurfaceConformation();
 
     // Use storeSizesAndAlignments with no feed points because all background
-    // points may have been distributed.  It is a requirement that none of the
-    // preceding functions requires look up of sizes or alignments from the
-    // Delaunay vertices, i.e. setVertexSizeAndAlignment cannot be called
-    // before this point.
+    // points may have been distributed.
     storeSizesAndAlignments();
 
     // Report any Delaunay vertices that do not think that they are in the
     // domain the processor they are on.
     // reportProcessorOccupancy();
 
+    printVertexInfo();
+
     if (cvMeshControls().objOutput())
     {
-        writePoints("allInitialPoints.obj", false);
+        writePoints
+        (
+            "internalPoints_" + runTime_.timeName() + ".obj",
+            Foam::indexedVertexEnum::vtUnassigned,
+            Foam::indexedVertexEnum::vtExternalFeaturePoint
+        );
     }
 }
 
@@ -1435,9 +1451,9 @@ void Foam::conformalVoronoiMesh::move()
 
     Info<< nl << "Relaxation = " << relaxation << endl;
 
-    pointField dualVertices(number_of_cells());
+    pointField dualVertices(number_of_finite_cells());
 
-    label dualVertI = 0;
+    this->resetCellCount();
 
     // Find the dual point of each tetrahedron and assign it an index.
     for
@@ -1447,19 +1463,22 @@ void Foam::conformalVoronoiMesh::move()
         ++cit
     )
     {
-        cit->cellIndex() = Cb::ctFar;
+        cit->cellIndex() = Cb::ctUnassigned;
 
         if (cit->anyInternalOrBoundaryDualVertex())
         {
-            cit->cellIndex() = dualVertI;
+            cit->cellIndex() = getNewCellIndex();
 
-            dualVertices[dualVertI] = cit->dual();
+            dualVertices[cit->cellIndex()] = cit->dual();
+        }
 
-            dualVertI++;
+        if (cit->hasFarPoint())
+        {
+            cit->cellIndex() = Cb::ctFar;
         }
     }
 
-    dualVertices.setSize(dualVertI);
+    dualVertices.setSize(cellCount());
 
     setVertexSizeAndAlignment();
 
@@ -1469,9 +1488,9 @@ void Foam::conformalVoronoiMesh::move()
 
     vectorField cartesianDirections(3);
 
-    cartesianDirections[0] = vector(0,0,1);
-    cartesianDirections[1] = vector(0,1,0);
-    cartesianDirections[2] = vector(1,0,0);
+    cartesianDirections[0] = vector(1, 0, 0);
+    cartesianDirections[1] = vector(0, 1, 0);
+    cartesianDirections[2] = vector(0, 0, 1);
 
     vectorField displacementAccumulator
     (
@@ -1498,25 +1517,29 @@ void Foam::conformalVoronoiMesh::move()
         Vertex_handle vA = c->vertex(eit->second);
         Vertex_handle vB = c->vertex(eit->third);
 
-        if (!vA->internalOrBoundaryPoint() && !vB->internalOrBoundaryPoint())
-        {
-            // At least one vertex has to be a real internalOrBoundaryPoint
-            continue;
-        }
-
         if
         (
-            vA->anyInternalOrBoundaryPoint()
-         && vB->anyInternalOrBoundaryPoint()
+            (
+                vA->internalPoint() && !vA->referred()
+             && vB->internalOrBoundaryPoint()
+            )
+         || (
+                vB->internalPoint() && !vB->referred()
+             && vA->internalOrBoundaryPoint()
+            )
         )
         {
-            face dualFace = buildDualFace(eit);
-
-            Foam::point dVA = topoint(vA->point());
-            Foam::point dVB = topoint(vB->point());
+            pointFromPoint dVA = topoint(vA->point());
+            pointFromPoint dVB = topoint(vB->point());
 
-            Field<vector> alignmentDirsA(vA->alignment() & cartesianDirections);
-            Field<vector> alignmentDirsB(vB->alignment() & cartesianDirections);
+            Field<vector> alignmentDirsA
+            (
+                vA->alignment().T() & cartesianDirections
+            );
+            Field<vector> alignmentDirsB
+            (
+                vB->alignment().T() & cartesianDirections
+            );
 
             Field<vector> alignmentDirs(3);
 
@@ -1551,7 +1574,11 @@ void Foam::conformalVoronoiMesh::move()
             {
                 // Removal of close points
 
-                if (vA->internalPoint() && vB->internalPoint())
+                if
+                (
+                    vA->internalPoint() && !vA->referred()
+                 && vB->internalPoint() && !vB->referred()
+                )
                 {
                     // Only insert a point at the midpoint of
                     // the short edge if neither attached
@@ -1566,17 +1593,17 @@ void Foam::conformalVoronoiMesh::move()
                     {
                         pointsToInsert.append
                         (
-                            toPoint(0.5*(dVA + dVB))
+                            toPoint<Point>(0.5*(dVA + dVB))
                         );
                     }
                 }
 
-                if (vA->internalPoint())
+                if (vA->internalPoint() && !vA->referred())
                 {
                     pointToBeRetained[vA->index()] = false;
                 }
 
-                if (vB->internalPoint())
+                if (vB->internalPoint() && !vB->referred())
                 {
                     pointToBeRetained[vB->index()] = false;
                 }
@@ -1590,14 +1617,17 @@ void Foam::conformalVoronoiMesh::move()
             {
                 vector& alignmentDir = alignmentDirs[aD];
 
-                if ((rAB & alignmentDir) < 0)
+                scalar dotProd = rAB & alignmentDir;
+
+                if (dotProd < 0)
                 {
                     // swap the direction of the alignment so that has the
                     // same sense as rAB
                     alignmentDir *= -1;
+                    dotProd *= -1;
                 }
 
-                const scalar alignmentDotProd = ((rAB/rABMag) & alignmentDir);
+                const scalar alignmentDotProd = dotProd/rABMag;
 
                 if
                 (
@@ -1605,19 +1635,55 @@ void Foam::conformalVoronoiMesh::move()
                   > cvMeshControls().cosAlignmentAcceptanceAngle()
                 )
                 {
-                    const scalar targetCellSize = averageCellSize(vA, vB);
+                    scalar targetCellSize = averageCellSize(vA, vB);
 
-                    const scalar targetFaceArea = sqr(targetCellSize);
+                    scalar targetFaceArea = sqr(targetCellSize);
 
-                    alignmentDir *= 0.5*targetCellSize;
+                    const vector originalAlignmentDir = alignmentDir;
+
+                    // Update cell size and face area
+                    cellShapeControls().aspectRatio().updateCellSizeAndFaceArea
+                    (
+                        alignmentDir,
+                        targetFaceArea,
+                        targetCellSize
+                    );
 
                     // Vector to move end points around middle of vector
                     // to align edge (i.e. dual face normal) with alignment
                     // directions.
                     vector delta = alignmentDir - 0.5*rAB;
 
+                    face dualFace = buildDualFace(eit);
+
                     const scalar faceArea = dualFace.mag(dualVertices);
 
+                    // Update delta vector
+                    cellShapeControls().aspectRatio().updateDeltaVector
+                    (
+                        originalAlignmentDir,
+                        targetCellSize,
+                        rABMag,
+                        delta
+                    );
+
+                    if (targetFaceArea == 0)
+                    {
+                        Pout<< vA->info() << vB->info();
+
+                        Cell_handle ch = locate(vA->point());
+                        if (is_infinite(ch))
+                        {
+                            Pout<< "vA " << vA->targetCellSize() << endl;
+                        }
+
+                        ch = locate(vB->point());
+                        if (is_infinite(ch))
+                        {
+                            Pout<< "vB " << vB->targetCellSize() << endl;
+                        }
+                    }
+
                     delta *= faceAreaWeightModel_->faceAreaWeight
                     (
                         faceArea/targetFaceArea
@@ -1625,8 +1691,15 @@ void Foam::conformalVoronoiMesh::move()
 
                     if
                     (
-                        vA->internalPoint()
-                     && vB->internalPoint()
+                        (
+                            (vA->internalPoint() && vB->internalPoint())
+                         && (!vA->referred() || !vB->referred())
+//                         ||
+//                            (
+//                                vA->referredInternalPoint()
+//                             && vB->referredInternalPoint()
+//                            )
+                        )
                      && rABMag
                       > cvMeshControls().insertionDistCoeff()*targetCellSize
                      && faceArea
@@ -1636,7 +1709,6 @@ void Foam::conformalVoronoiMesh::move()
                     )
                     {
                         // Point insertion
-
                         if
                         (
                             !geometryToConformTo_.findSurfaceAnyIntersection
@@ -1646,23 +1718,32 @@ void Foam::conformalVoronoiMesh::move()
                             )
                         )
                         {
-                            // Prevent insertions spanning surfaces
-                            pointsToInsert.append
-                            (
-                                toPoint(0.5*(dVA + dVB))
-                            );
+                            const Foam::point& newPt = 0.5*(dVA + dVB);
+
+                            if (positionOnThisProc(newPt))
+                            {
+                                // Prevent insertions spanning surfaces
+                                pointsToInsert.append(toPoint<Point>(newPt));
+                            }
                         }
                     }
                     else if
                     (
-                        (vA->internalPoint() || vB->internalPoint())
+                        (
+                            (vA->internalPoint() && !vA->referred())
+                         || (vB->internalPoint() && !vB->referred())
+                        )
                      && rABMag
-                      < cvMeshControls().removalDistCoeff()*targetCellSize
+                      < cvMeshControls().removalDistCoeff()
+                       *targetCellSize
                     )
                     {
                         // Point removal
-
-                        if (vA->internalPoint() && vB->internalPoint())
+                        if
+                        (
+                            vA->internalPoint() && !vA->referred()
+                         && vB->internalPoint() && !vB->referred()
+                        )
                         {
                             // Only insert a point at the midpoint of
                             // the short edge if neither attached
@@ -1676,31 +1757,31 @@ void Foam::conformalVoronoiMesh::move()
                             {
                                 pointsToInsert.append
                                 (
-                                    toPoint(0.5*(dVA + dVB))
+                                    toPoint<Point>(0.5*(dVA + dVB))
                                 );
                             }
                         }
 
-                        if (vA->internalPoint())
+                        if (vA->internalPoint() && !vA->referred())
                         {
                             pointToBeRetained[vA->index()] = false;
                         }
 
-                        if (vB->internalPoint())
+                        if (vB->internalPoint() && !vB->referred())
                         {
                             pointToBeRetained[vB->index()] = false;
                         }
                     }
                     else
                     {
-                        if (vA->internalPoint())
+                        if (vA->internalPoint() && !vA->referred())
                         {
                             displacementAccumulator[vA->index()] += delta;
                         }
 
-                        if (vB->internalPoint())
+                        if (vB->internalPoint() && !vB->referred())
                         {
-                            displacementAccumulator[vB->index()] += -delta;
+                            displacementAccumulator[vB->index()] -= delta;
                         }
                     }
                 }
@@ -1708,6 +1789,8 @@ void Foam::conformalVoronoiMesh::move()
         }
     }
 
+    Info<< "Limit displacements" << endl;
+
     // Limit displacements that pierce, or get too close to the surface
     for
     (
@@ -1716,22 +1799,26 @@ void Foam::conformalVoronoiMesh::move()
         ++vit
     )
     {
-        if (vit->internalPoint())
+        if (vit->internalPoint() && !vit->referred())
         {
-            limitDisplacement
-            (
-                vit,
-                displacementAccumulator[vit->index()]
-            );
+            if (pointToBeRetained[vit->index()] == true)
+            {
+                limitDisplacement
+                (
+                    vit,
+                    displacementAccumulator[vit->index()]
+                );
+            }
         }
     }
 
     vector totalDisp = gSum(displacementAccumulator);
     scalar totalDist = gSum(mag(displacementAccumulator));
 
-    // Relax the calculated displacement
     displacementAccumulator *= relaxation;
 
+    Info<< "Sum displacements" << endl;
+
     for
     (
         Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
@@ -1739,7 +1826,7 @@ void Foam::conformalVoronoiMesh::move()
         ++vit
     )
     {
-        if (vit->internalPoint())
+        if (vit->internalPoint() && !vit->referred())
         {
             if (pointToBeRetained[vit->index()] == true)
             {
@@ -1755,7 +1842,7 @@ void Foam::conformalVoronoiMesh::move()
 
                 pointsToInsert.append
                 (
-                    toPoint
+                    toPoint<Point>
                     (
                         topoint(vit->point())
                       + displacementAccumulator[vit->index()]
@@ -1780,7 +1867,7 @@ void Foam::conformalVoronoiMesh::move()
             ++vit
         )
         {
-            if (vit->internalPoint())
+            if (vit->internalPoint() && !vit->referred())
             {
                 if (pointToBeRetained[vit->index()] == true)
                 {
@@ -1797,45 +1884,44 @@ void Foam::conformalVoronoiMesh::move()
     }
 
     // Remove the entire tessellation
-    reset();
-
-    if (cvMeshControls().objOutput() && runTime_.outputTime())
-    {
-        writePoints("featurePoints_" + runTime_.timeName() + ".obj", false);
-    }
+    DelaunayMesh<Delaunay>::reset();
 
     timeCheck("Displacement calculated");
 
     Info<< nl << "Inserting displaced tessellation" << endl;
 
-    insertPoints(pointsToInsert);
-
-    // Remove internal points that have been inserted outside the surface.
-    label internalPtIsOutside = 0;
+    insertInternalPoints(pointsToInsert, true);
 
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        ++vit
-    )
-    {
-        if (vit->internalPoint())
-        {
-            bool inside
-                = geometryToConformTo_.inside(topoint(vit->point()));
-
-            if (!inside)
-            {
-                remove(vit);
-                internalPtIsOutside++;
-            }
-        }
-    }
+    reinsertFeaturePoints(false);
 
-    Info<< "    " << internalPtIsOutside
-        << " internal points were inserted outside the domain. "
-        << "They have been removed." << endl;
+    // Remove internal points that have been inserted outside the surface.
+//    label internalPtIsOutside = 0;
+//
+//    for
+//    (
+//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+//        vit != finite_vertices_end();
+//        ++vit
+//    )
+//    {
+//        if (vit->internalPoint() && !vit->referred())
+//        {
+//            bool inside = geometryToConformTo_.inside
+//            (
+//                topoint(vit->point())
+//            );
+//
+//            if (!inside)
+//            {
+//                remove(vit);
+//                internalPtIsOutside++;
+//            }
+//        }
+//    }
+//
+//    Info<< "    " << internalPtIsOutside
+//        << " internal points were inserted outside the domain. "
+//        << "They have been removed." << endl;
 
     // Fix points that have not been significantly displaced
 //    for
@@ -1858,15 +1944,39 @@ void Foam::conformalVoronoiMesh::move()
 //        }
 //    }
 
-    if (cvMeshControls().objOutput() && runTime_.outputTime())
+    timeCheck("Internal points inserted");
+
     {
-        writePoints("points_" + runTime_.timeName() + ".obj", true);
+        // Check that no index is shared between any of the local points
+        labelHashSet usedIndices;
+        for
+        (
+            Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+            vit != finite_vertices_end();
+            ++vit
+        )
+        {
+            if (!vit->referred() && !usedIndices.insert(vit->index()))
+            {
+                FatalErrorIn("Foam::conformalVoronoiMesh::move()")
+                    << "Index already used! Could not insert: " << nl
+                    << vit->info()
+                    << abort(FatalError);
+            }
+        }
     }
 
-    timeCheck("Internal points inserted");
-
     conformToSurface();
 
+    if (cvMeshControls().objOutput())
+    {
+        writePoints
+        (
+            "internalPoints_" + runTime_.timeName() + ".obj",
+            Foam::indexedVertexEnum::vtInternal
+        );
+    }
+
     if (cvMeshControls().objOutput() && runTime_.outputTime())
     {
         writeBoundaryPoints("boundaryPoints_" + runTime_.timeName() + ".obj");
@@ -1874,10 +1984,12 @@ void Foam::conformalVoronoiMesh::move()
 
     timeCheck("After conformToSurface");
 
+    printVertexInfo();
+
     // Write the intermediate mesh, do not filter the dual faces.
     if (runTime_.outputTime())
     {
-        writeMesh(runTime_.timeName(), false);
+        writeMesh(runTime_.timeName());
     }
 
     updateSizesAndAlignments(pointsToInsert);
@@ -1947,18 +2059,131 @@ Foam::conformalVoronoiMesh::intersectsProc
 }
 
 
-Foam::labelListList Foam::conformalVoronoiMesh::overlapsProc
-(
-    const List<Foam::point>& centres,
-    const List<scalar>& radiusSqrs
-) const
+//Foam::labelListList Foam::conformalVoronoiMesh::overlapsProc
+//(
+//    const List<Foam::point>& centres,
+//    const List<scalar>& radiusSqrs
+//) const
+//{
+//    if (!Pstream::parRun())
+//    {
+//        return labelListList(centres.size(), labelList(0));
+//    }
+//
+////    DynamicList<Foam::point> pts(number_of_vertices());
+//
+////    for
+////    (
+////        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+////        vit != finite_vertices_end();
+////        vit++
+////    )
+////    {
+////        pts.append(topoint(vit->point()));
+////    }
+////
+////    dynamicIndexedOctree<dynamicTreeDataPoint> vertexOctree
+////    (
+////        dynamicTreeDataPoint(pts),
+////        treeBoundBox(min(pts), max(pts)),
+////        10, // maxLevel
+////        10, // leafSize
+////        3.0 // duplicity
+////    );
+//
+//    return decomposition_().overlapsProcessors
+//    (
+//        centres,
+//        radiusSqrs,
+//        *this,
+//        false//,
+////        vertexOctree
+//    );
+//}
+
+
+void Foam::conformalVoronoiMesh::checkCoPlanarCells() const
 {
-    if (!Pstream::parRun())
+    typedef CGAL::Exact_predicates_exact_constructions_kernel   Kexact;
+    typedef CGAL::Point_3<Kexact>                               PointExact;
+
+    if (!is_valid())
     {
-        return labelListList(centres.size(), labelList(0));
+        Pout<< "Triangulation is invalid!" << endl;
+    }
+
+    OFstream str("badCells.obj");
+
+    label badCells = 0;
+
+    for
+    (
+        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
+        cit != finite_cells_end();
+        ++cit
+    )
+    {
+        const scalar quality = cvMeshChecks::coplanarTet(cit, 1e-16);
+
+        if (quality == 0)
+        {
+            Pout<< "COPLANAR: " << cit->info() << nl
+                << "    quality = " << quality << nl
+                << "    dual    = " << topoint(cit->dual()) << endl;
+
+            drawDelaunayCell(str, cit, badCells++);
+
+            FixedList<PointExact, 4> cellVerticesExact(PointExact(0,0,0));
+            forAll(cellVerticesExact, vI)
+            {
+                cellVerticesExact[vI] = PointExact
+                (
+                    cit->vertex(vI)->point().x(),
+                    cit->vertex(vI)->point().y(),
+                    cit->vertex(vI)->point().z()
+                );
+            }
+
+            PointExact synchronisedDual = CGAL::circumcenter<Kexact>
+            (
+                cellVerticesExact[0],
+                cellVerticesExact[1],
+                cellVerticesExact[2],
+                cellVerticesExact[3]
+            );
+
+            Foam::point exactPt
+            (
+                CGAL::to_double(synchronisedDual.x()),
+                CGAL::to_double(synchronisedDual.y()),
+                CGAL::to_double(synchronisedDual.z())
+            );
+
+            Info<< "inexact = " << cit->dual() << nl
+                << "exact   = " << exactPt << endl;
+        }
+    }
+
+    Pout<< "There are " << badCells << " bad cells out of "
+        << number_of_finite_cells() << endl;
+
+
+    label nNonGabriel = 0;
+    for
+    (
+        Delaunay::Finite_facets_iterator fit = finite_facets_begin();
+        fit != finite_facets_end();
+        ++fit
+    )
+    {
+        if (!is_Gabriel(*fit))
+        {
+            nNonGabriel++;//Pout<< "Non-gabriel face" << endl;
+        }
     }
 
-    return decomposition_().overlapsProcessors(centres, radiusSqrs, false);
+    Pout<< "There are " << nNonGabriel << " non-Gabriel faces out of "
+        << number_of_finite_facets() << endl;
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H
index 3be6dab81c208b927f333c57500ee7e958f7670b..7ff0e64170cd6c09efec87d9422b8f3038d03e62 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Class
     Foam::conformalVoronoiMesh
 
@@ -50,7 +45,7 @@ SourceFiles
 #include "ulong.H"
 #include "searchableSurfaces.H"
 #include "conformationSurfaces.H"
-#include "cellSizeControlSurfaces.H"
+#include "cellShapeControl.H"
 #include "cvControls.H"
 #include "DynamicList.H"
 #include "PackedBoolList.H"
@@ -77,6 +72,11 @@ SourceFiles
 #include "zeroGradientFvPatchFields.H"
 #include "globalIndex.H"
 #include "pointFeatureEdgesTypes.H"
+#include "pointConversion.H"
+#include "Tuple2.H"
+#include "DistributedDelaunayMesh.H"
+#include "tensorIOField.H"
+
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -98,24 +98,25 @@ class backgroundMeshDecomposition;
 
 class conformalVoronoiMesh
 :
-    public Delaunay
+    public DistributedDelaunayMesh<Delaunay>
 {
 public:
 
     enum reconformationMode
     {
-        rmNone,   // Do not rebuild the surface conformation
-        rmCoarse, // Rebuild the conformation with coarse tolerances (faster)
-        rmFine    // Rebuild the conformation with fine tolerances (slower)
+        rmOff,   // Do not rebuild the surface conformation
+        rmOn
     };
 
-    enum faceCollapseMode
-    {
-        fcmNone,             // Do not collapse face
-        fcmEdge,             // Collapse face to a single edge
-        fcmPoint,            // Collapse face to a point
-        fcmDeferredMultiEdge // Collapse face to several edges
-    };
+    typedef Delaunay::Vertex_handle    Vertex_handle;
+    typedef Delaunay::Cell_handle      Cell_handle;
+    typedef Delaunay::Point            Point;
+
+    typedef List<DynamicList<Pair<labelPair> > > labelPairPairDynListList;
+
+    typedef Tuple2<pointIndexHit, label>         pointIndexHitAndFeature;
+    typedef List<pointIndexHitAndFeature>        pointIndexHitAndFeatureList;
+    typedef DynamicList<pointIndexHitAndFeature> pointIndexHitAndFeatureDynList;
 
 
 private:
@@ -147,12 +148,8 @@ private:
         //- The surfaces to conform to
         conformationSurfaces geometryToConformTo_;
 
-        //- The cell size control object
-        cellSizeControlSurfaces cellSizeControl_;
-
-        //- Keep track of the start index of the internal points.  Needs
-        //  careful bookkeeping within several functions.
-        label startOfInternalPoints_;
+        //- The cell shape control object
+        cellShapeControl cellShapeControl_;
 
         //- Limiting bound box before infinity begins
         treeBoundBox limitBounds_;
@@ -167,11 +164,15 @@ private:
 
         //- Search tree for edge point locations
         mutable autoPtr<dynamicIndexedOctree<dynamicTreeDataPoint> >
-        edgeLocationTreePtr_;
+            edgeLocationTreePtr_;
+
+        mutable DynamicList<Foam::point> existingEdgeLocations_;
 
         //- Search tree for surface point locations
         mutable autoPtr<dynamicIndexedOctree<dynamicTreeDataPoint> >
-        surfacePtLocationTreePtr_;
+            surfacePtLocationTreePtr_;
+
+        mutable DynamicList<Foam::point> existingSurfacePtLocations_;
 
         //- Store locations where the cell size and alignments will be
         //  pre-calculated and looked up
@@ -205,6 +206,8 @@ private:
 
     // Private Member Functions
 
+        inline scalar defaultCellSize() const;
+
         //- Return the local target cell size at the given location.  Takes
         //  boolean argument to allow speed-up of queries if the point is going
         //  to be on a surface.
@@ -271,82 +274,82 @@ private:
         //- Return the required alignment directions at the given location
         tensor requiredAlignment(const Foam::point& pt) const;
 
-        //- Insert Foam::point and return its auto-generated index
-        inline label insertPoint
-        (
-            const Foam::point& p,
-            const label type
-        );
-
         //- Insert Point and return its auto-generated index
-        inline label insertPoint
+        inline bool insertPoint
         (
             const Point& P,
-            const label type
+            const indexedVertexEnum::vertexType type
         );
 
         //- Insert Foam::point with specified index and type
-        inline void insertPoint
+        inline bool insertPoint
         (
             const Foam::point& p,
-            const label index,
-            const label type
+            const indexedVertexEnum::vertexType type
         );
 
-        //- Insert Point with specified index and type
-        inline void insertPoint
+        //- Insert Point with specified index, type and original processor
+        inline bool insertReferredPoint
         (
             const Point& P,
             const label index,
-            const label type
+            const indexedVertexEnum::vertexType type,
+            const label processor
+        );
+
+        inline bool insertReferredPoint(const Vb& P);
+
+        //- Insert Foam::point with specified index, type and original processor
+        inline bool insertReferredPoint
+        (
+            const Foam::point& p,
+            const label index,
+            const indexedVertexEnum::vertexType type,
+            const label processor
         );
 
         //- Insert Delaunay vertices using the CGAL range insertion method,
         //  optionally check processor occupancy and distribute to other
         //  processors
-        void insertPoints
+        void insertInternalPoints
         (
             List<Point>& points,
-            bool distribute = true
+            const bool distribute = false
         );
 
-        //- Insert indexed and typed Delaunay vertices, optionally check
-        //  processor occupancy and distribute to other processors
         void insertPoints
         (
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types,
+            List<Vb>& vertices,
             bool distribute = true
         );
 
-        //- Insert a point-pair at a ppDist distance either side of
+        //- Create a point-pair at a ppDist distance either side of
         //  surface point surfPt, in the direction n
-        inline void insertPointPair
+        inline void createPointPair
         (
             const scalar ppDist,
             const Foam::point& surfPt,
-            const vector& n
+            const vector& n,
+            DynamicList<Vb>& pts
         );
 
+        inline Foam::point perturbPoint(const Foam::point& pt) const;
+
         //- Create a point-pair at a ppDist distance either side of
         //  surface point surfPt, in the direction n
-        inline void createPointPair
+        inline void createBafflePointPair
         (
             const scalar ppDist,
             const Foam::point& surfPt,
             const vector& n,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Insert pairs of points on the surface with the given normals, at the
         //  specified spacing
         void insertSurfacePointPairs
         (
-            const List<pointIndexHit>& surfaceHits,
-            const List<label>& hitSurfaces,
+            const pointIndexHitAndFeatureList& surfaceHits,
             const fileName fName = fileName::null
         );
 
@@ -355,8 +358,7 @@ private:
         //  to be conformed to on the corresponding entry in featureHit
         void insertEdgePointGroups
         (
-            const List<pointIndexHit>& edgeHits,
-            const labelList& featuresHit,
+            const pointIndexHitAndFeatureList& edgeHits,
             const fileName fName = fileName::null
         );
 
@@ -365,9 +367,7 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Create points to conform to an external edge
@@ -375,9 +375,7 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Create points to conform to an internal edge
@@ -385,9 +383,7 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Create points to conform to a flat edge
@@ -395,9 +391,7 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Create points to conform to an open edge
@@ -405,9 +399,7 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Create points to conform to multiply connected edge
@@ -415,39 +407,54 @@ private:
         (
             const extendedFeatureEdgeMesh& feMesh,
             const pointIndexHit& edHit,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Determine and insert point groups at the feature points
         void insertFeaturePoints();
 
-        bool edgesShareNormal(const label e1, const label e2) const;
+        //- Create point groups at mixed feature points
+        void createMixedFeaturePoints(DynamicList<Vb>& pts);
 
-        //- Create point groups at convex feature points
-        void createConvexFeaturePoints
+        void addMasterAndSlavePoints
         (
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
-        );
+            const DynamicList<Foam::point>& masterPoints,
+            const DynamicList<indexedVertexEnum::vertexType>&masterPointsTypes,
+            const Map<DynamicList<autoPtr<plane> > >& masterPointReflections,
+            DynamicList<Vb>& pts,
+            const label ptI
+        ) const;
+
+        label getSign(const extendedFeatureEdgeMesh::edgeStatus eStatus) const;
 
-        //- Create point groups at concave feature points
-        void createConcaveFeaturePoints
+        void createMasterAndSlavePoints
         (
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
-        );
+            const extendedFeatureEdgeMesh& feMesh,
+            const label ptI,
+            DynamicList<Vb>& pts
+        ) const;
 
-        //- Create point groups at mixed feature points
-        void createMixedFeaturePoints
+        void createFeaturePoints(DynamicList<Vb>& pts);
+
+        vector sharedFaceNormal
         (
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
-        );
+            const extendedFeatureEdgeMesh& feMesh,
+            const label edgeI,
+            const label nextEdgeI
+        ) const;
+
+        List<Foam::point> reflectPointInPlanes
+        (
+            const Foam::point p,
+            const DynamicList<autoPtr<plane> >& planes
+        ) const;
+
+        Foam::point reflectPointInPlane
+        (
+            const Foam::point p,
+            const plane& planeN
+        ) const;
+
 
         //- Fill the pointFeatureEdgesType struct with the types of feature
         //  edges that are attached to the point.
@@ -467,9 +474,7 @@ private:
             const pointFeatureEdgesTypes& pFEdgeTypes,
             const List<extendedFeatureEdgeMesh::edgeStatus>& allEdStat,
             const label ptI,
-            DynamicList<Foam::point>& pts,
-            DynamicList<label>& indices,
-            DynamicList<label>& types
+            DynamicList<Vb>& pts
         );
 
         //- Store the locations of all of the features to be conformed to
@@ -486,28 +491,24 @@ private:
         //- Check if a location is in exclusion range around a feature point
         bool nearFeaturePt(const Foam::point& pt) const;
 
-        //- Clear the entire tesselation
-        //  Reinsert bounding points, feature points and recalculate
-        //  startOfInternalPoints_
-        void reset(const bool distribute = false);
-
-        //- Insert far points in a large bounding box to avoid dual edges
-        //  spanning huge distances
-        void insertBoundingPoints();
-
-        //- Reinsert the bounding points
-        void reinsertBoundingPoints();
-
         //- Insert the initial points into the triangulation, based on the
         //  initialPointsMethod
         void insertInitialPoints();
 
+        //- Calculate the worst load balance
+        scalar calculateLoadUnbalance() const;
+
         //- In parallel redistribute the backgroundMeshDecomposition and
         //  vertices to balance the number of vertices on each processor.
         //  Returns true if the background mesh changes as this removes all
         //  referred vertices, so the parallel interface may need rebuilt.
         bool distributeBackground();
 
+        //-
+        void distribute();
+
+        void buildCellSizeAndAlignmentMesh();
+
         //- Store data for sizeAndAlignmentLocations_, storedSizes_ and
         //  storedAlignments_ and initialise the sizeAndAlignmentTreePtr_,
         //  determining the appropriate sizeAndAlignmentLocations_
@@ -568,9 +569,28 @@ private:
         //  conformation
         reconformationMode reconformationControl() const;
 
+        //- Determines geometrically whether a vertex is close to a surface
+        //  This is an optimisation
+        label findVerticesNearBoundaries();
+
         //- Create and insert the necessary point pairs to conform to the
         //  surface, then store the result
-        void buildSurfaceConformation(reconformationMode reconfMode);
+        void buildSurfaceConformation();
+
+        label synchroniseEdgeTrees
+        (
+            pointIndexHitAndFeatureList& featureEdgeHits
+        );
+
+        label synchroniseSurfaceTrees
+        (
+            pointIndexHitAndFeatureList& surfaceHits
+        );
+
+        bool locationConformsToInside
+        (
+            const pointIndexHitAndFeature& info
+        ) const;
 
         //- Check to see if dual cell specified by given vertex iterator
         //  intersects the boundary and hence reqires a point-pair
@@ -583,8 +603,7 @@ private:
         bool dualCellSurfaceAllIntersections
         (
             const Delaunay::Finite_vertices_iterator& vit,
-            DynamicList<pointIndexHit>& info,
-            DynamicList<label>& hitSurface
+            pointIndexHitAndFeatureDynList& info
         ) const;
 
         //- Return false if the line is entirely outside the current processor
@@ -599,64 +618,6 @@ private:
             Foam::point& b
         ) const;
 
-        label removeProcessorBoundarySeeds(bool reinsertBoundPts);
-
-        void seedProcessorBoundarySurfaces(bool seedProcessors);
-
-        label numberOfUnusedReferredPoints() const;
-
-        //- Build the parallelInterfaces of the mesh
-        void buildParallelInterface
-        (
-            const word& outputName
-        );
-
-        //- Build the parallelInterfaces of the mesh, supply hash sets
-        //  externally to allow updates
-        void buildParallelInterface
-        (
-            List<labelHashSet>& referralVertices,
-            List<labelHashSet>& receivedVertices,
-            bool initialEdgeReferral,
-            const word& outputName
-        );
-
-        //- Refer all vertices to all processors
-        void buildParallelInterfaceAll
-        (
-            List<labelHashSet>& referralVertices,
-            List<labelHashSet>& receivedVertices,
-            const word& outputName
-        );
-
-        //- Refer vertices where there dual edge pierces other processors
-        void buildParallelInterfaceIntersection
-        (
-            List<labelHashSet>& referralVertices,
-            List<labelHashSet>& receivedVertices,
-            const word& outputName
-        );
-
-        //- Refer vertices that are attached to Delaunay tets whose
-        //  circumspheres touch other processors
-        void buildParallelInterfaceInfluence
-        (
-            List<labelHashSet>& referralVertices,
-            List<labelHashSet>& receivedVertices,
-            const word& outputName
-        );
-
-        //- Refer vertices to their required processors
-        void referVertices
-        (
-            const DynamicList<label>& targetProcessor,
-            DynamicList<Foam::point>& parallelPoints,
-            DynamicList<label>& parallelIndices,
-            List<labelHashSet>& receivedVertices,
-            const word& stageName,
-            const word& outputName
-        );
-
         //- Find the "worst" protrusion of a dual cell through the surface,
         //  subject to the maxSurfaceProtrusion tolerance
         void dualCellLargestSurfaceProtrusion
@@ -681,7 +642,7 @@ private:
 
         //- Write out debugging information about the surface conformation
         //  quality
-        void reportSurfaceConformationQuality();
+//        void reportSurfaceConformationQuality();
 
         //- Limit the displacement of a point so that it doesn't penetrate the
         //  surface to be meshed or come too close to it
@@ -698,23 +659,19 @@ private:
         //- Check if a surface point is near another.
         bool nearSurfacePoint
         (
-            pointIndexHit& pHit,
-            label& surfaceHit,
-            DynamicList<Foam::point>& existingSurfacePtLocations
+            pointIndexHitAndFeature& pHit
         ) const;
 
         //- Append a point to the surface point tree and the existing list
         bool appendToSurfacePtTree
         (
-            const Foam::point& pt,
-            DynamicList<Foam::point>& existingSurfacePtLocations
+            const Foam::point& pt
         ) const;
 
         //- Append a point to the edge location tree and the existing list
         bool appendToEdgeLocationTree
         (
-            const Foam::point& pt,
-            DynamicList<Foam::point>& existingEdgeLocations
+            const Foam::point& pt
         ) const;
 
         //- Return a list of the nearest feature edge locations
@@ -745,8 +702,7 @@ private:
         //- edge conformation location
         bool nearFeatureEdgeLocation
         (
-            pointIndexHit& pHit,
-            DynamicList<Foam::point>& existingEdgeLocations
+            pointIndexHit& pHit
         ) const;
 
         //- Build or rebuild the edge location tree
@@ -769,18 +725,11 @@ private:
         void addSurfaceAndEdgeHits
         (
             const Delaunay::Finite_vertices_iterator& vit,
-            const Foam::point& vert,
-            const DynamicList<pointIndexHit>& surfHit,
-            const DynamicList<label>& hitSurface,
+            const pointIndexHitAndFeatureDynList& surfaceIntersections,
             scalar surfacePtReplaceDistCoeffSqr,
             scalar edgeSearchDistCoeffSqr,
-            DynamicList<pointIndexHit>& surfaceHits,
-            DynamicList<label>& hitSurfaces,
-            DynamicList<pointIndexHit>& featureEdgeHits,
-            DynamicList<label>& featureEdgeFeaturesHit,
-            DynamicList<Foam::point>& newEdgeLocations,
-            DynamicList<Foam::point>& existingEdgeLocations,
-            DynamicList<Foam::point>& existingSurfacePtLocations
+            pointIndexHitAndFeatureDynList& surfaceHits,
+            pointIndexHitAndFeatureDynList& featureEdgeHits
         ) const;
 
         //- Store the surface conformation with the indices offset to be
@@ -791,10 +740,19 @@ private:
         //  relative to new number of internal vertices
         void reinsertSurfaceConformation();
 
+        void checkCells();
+
+        void checkDuals();
+
+        void checkVertices();
+
+        void checkCoPlanarCells() const;
+
         //- Dual calculation
         void calcDualMesh
         (
             pointField& points,
+            labelList& boundaryPts,
             faceList& faces,
             labelList& owner,
             labelList& neighbour,
@@ -806,7 +764,7 @@ private:
             pointField& cellCentres,
             labelList& cellToDelaunayVertex,
             labelListList& patchToDelaunayVertex,
-            bool filterFaces
+            PackedBoolList& boundaryFacesToRemove
         );
 
         //- Tet mesh calculation
@@ -844,77 +802,27 @@ private:
             const Delaunay::Finite_facets_iterator& fit
         ) const;
 
-        //- Merge adjacent edges that are not attached to other faces
-        label mergeNearlyParallelEdges
+        //- Determines if the dual face constructed by the Delaunay
+        //  edge is a processor boundary face
+        inline bool isProcBoundaryEdge
         (
-            const pointField& pts,
-            const scalar maxCosAngle
-        );
+            const Delaunay::Finite_edges_iterator& eit
+        ) const;
 
-        //- Merge vertices that are very close together
-        void mergeCloseDualVertices
+        //- Merge vertices that are identical
+        void mergeIdenticalDualVertices
         (
             const pointField& pts,
-            const PackedBoolList& boundaryPts
+            const labelList& boundaryPts
         );
 
-        label mergeCloseDualVertices
+        label mergeIdenticalDualVertices
         (
             const pointField& pts,
-            const PackedBoolList& boundaryPts,
-            Map<label>& dualPtIndexMap
-        ) const;
-
-        //- Smooth the dual vertices of the dual faces on the boundary
-        //  so that they conform to the surface and remove any
-        //  small, normal oriented faces
-        void smoothSurface
-        (
-            pointField& pts,
-            const PackedBoolList& boundaryPts
-        );
-
-        label smoothSurfaceDualFaces
-        (
-            pointField& pts,
-            const PackedBoolList& boundaryPts,
+            const labelList& boundaryPts,
             Map<label>& dualPtIndexMap
         ) const;
 
-        //- Collapse a face to a point or an edge, modifying and
-        //  mapping the points, returns the true if the face was
-        //  collapsed in this operation
-        void collapseFaces
-        (
-            pointField& pts,
-            const PackedBoolList& boundaryPts,
-            HashSet<labelPair, labelPair::Hash<> >& deferredCollapseFaces
-        );
-
-        label collapseFaces
-        (
-            pointField& pts,
-            const PackedBoolList& boundaryPts,
-            Map<label>& dualPtIndexMap,
-            HashSet<labelPair, labelPair::Hash<> >& deferredCollapseFaces
-        ) const;
-
-        //- Collapse a face to an edge, updating the point and point
-        //  map. Returns the collapse mode that was applied.
-        faceCollapseMode collapseFace
-        (
-            const face& f,
-            pointField& pts,
-            const PackedBoolList& boundaryPts,
-            Map<label>& dualPtIndexMap,
-            scalar targetFaceSize,
-            scalar collapseSizeLimitCoeff,
-            label maxFC
-        ) const;
-
-        //- Identify the index of the longest edge on the face
-        label longestEdge(const face& f, const pointField& pts) const;
-
         //- Identify the face labels of the deferred collapse faces
         void deferredCollapseFaceSet
         (
@@ -943,12 +851,19 @@ private:
         void indexDualVertices
         (
             pointField& pts,
-            PackedBoolList& boundaryPts
+            labelList& boundaryPts
         );
 
-        //- Re-index all of the the Delaunay cells
+        //- Re-index all of the Delaunay cells
         void reindexDualVertices(const Map<label>& dualPtIndexMap);
 
+        label createPatchInfo
+        (
+            wordList& patchNames,
+            wordList& patchTypes,
+            labelList& procNeighbours
+        ) const;
+
         //- Create all of the internal and boundary faces
         void createFacesOwnerNeighbourAndPatches
         (
@@ -961,6 +876,7 @@ private:
             labelList& patchStarts,
             labelList& procNeighbours,
             labelListList& patchPointPairSlaves,
+            PackedBoolList& boundaryFacesToRemove,
             bool includeEmptyPatches = false
         ) const;
 
@@ -987,7 +903,7 @@ private:
             List<DynamicList<face> >& patchFaces,
             List<DynamicList<label> >& patchOwners,
             List<DynamicList<label> >& patchPointPairSlaves,
-            List<Pair<DynamicList<label> > >& patchSortingIndices
+            labelPairPairDynListList& patchSortingIndices
         ) const;
 
         //- Add the faces and owner information for the patches
@@ -998,15 +914,18 @@ private:
             labelList& owner,
             labelList& patchSizes,
             labelList& patchStarts,
+            PackedBoolList& boundaryFacesToRemove,
             const List<DynamicList<face> >& patchFaces,
-            const List<DynamicList<label> >& patchOwners
+            const List<DynamicList<label> >& patchOwners,
+            const List<DynamicList<bool> >& indirectPatchFace
         ) const;
 
         //- Remove points that are no longer used by any faces
         void removeUnusedPoints
         (
             faceList& faces,
-            pointField& pts
+            pointField& pts,
+            labelList& boundaryPts
         ) const;
 
         //- Remove dual cells that are not used by any faces. Return compaction
@@ -1031,6 +950,21 @@ private:
         //- Create a polyMesh from points.
         autoPtr<polyMesh> createPolyMeshFromPoints(const pointField& pts) const;
 
+        void checkProcessorPatchesMatch
+        (
+            const wordList& patchTypes,
+            const labelList& patchSizes,
+            const labelList& procNeighbours
+        ) const;
+
+        void reorderPoints
+        (
+            pointField& points,
+            labelList& boundaryPts,
+            faceList& faces,
+            const label nInternalFaces
+        ) const;
+
         //- Rotate the faces on processor patches if necessary
         void reorderProcessorPatches
         (
@@ -1078,6 +1012,8 @@ public:
         //  surface as required
         void move();
 
+        void printVertexInfo() const;
+
         //- Check if the point is in the domain handled by this processor
         bool positionOnThisProc(const Foam::point& pt) const;
 
@@ -1094,30 +1030,18 @@ public:
             const List<Foam::point>& ends
         ) const;
 
-        //- Which other processors does each sphere overlap
-        labelListList overlapsProc
-        (
-            const List<Foam::point>& centres,
-            const List<scalar>& radiusSqrs
-        ) const;
-
-        //- Conversion functions between point (FOAM::) and Point (CGAL)
-
-#       ifdef CGAL_INEXACT
-            typedef const Foam::point& pointFromPoint;
-            typedef const Point& PointFrompoint;
-#       else
-            typedef Foam::point pointFromPoint;
-            typedef Point PointFrompoint;
-#       endif
-
-        inline pointFromPoint topoint(const Point&) const;
-        inline PointFrompoint toPoint(const Foam::point&) const;
+//        //- Which other processors does each sphere overlap
+//        labelListList overlapsProc
+//        (
+//            const List<Foam::point>& centres,
+//            const List<scalar>& radiusSqrs
+//        ) const;
 
         typedef K::Vector_3 CGALVector;
 
         inline CGALVector toCGALVector(const Foam::vector& v) const;
 
+
         // Access
 
             //- Return the Time object
@@ -1135,8 +1059,8 @@ public:
             //- Return the backgroundMeshDecomposition
             inline const backgroundMeshDecomposition& decomposition() const;
 
-            //- Return the cellSizeControlSurfaces object
-            inline const cellSizeControlSurfaces& cellSizeControl() const;
+            //- Return the cellShapeControl object
+            inline const cellShapeControl& cellShapeControls() const;
 
             //- Return the cvMeshControls object
             inline const cvControls& cvMeshControls() const;
@@ -1159,8 +1083,21 @@ public:
                 label offset = 0
             ) const;
 
-            //- Write Delaunay points to .obj file
-            void writePoints(const fileName& fName, bool internalOnly) const;
+            //- Write Delaunay points in the range between (and including)
+            //  type startPointType and endPointType to .obj file
+            void writePoints
+            (
+                const fileName& fName,
+                const Foam::indexedVertexEnum::vertexType startPointType,
+                const Foam::indexedVertexEnum::vertexType endPointType
+            ) const;
+
+            //- Write Delaunay points of type pointType to .obj file
+            void writePoints
+            (
+                const fileName& fName,
+                const Foam::indexedVertexEnum::vertexType pointType
+            ) const;
 
             //- Write the boundary Delaunay points to .obj file
             void writeBoundaryPoints(const fileName& fName) const;
@@ -1172,17 +1109,20 @@ public:
                 const List<Foam::point>& points
             ) const;
 
+            //- Write list of points to file
+            void writePoints
+            (
+                const fileName& fName,
+                const List<Vb>& points
+            ) const;
+
             //- Write the internal Delaunay vertices of the tessellation as a
             //  pointField that may be used to restart the meshing process
             void writeInternalDelaunayVertices(const fileName& instance) const;
 
             //- Prepare data and call writeMesh for polyMesh and
             //  tetDualMesh
-            void writeMesh
-            (
-                const fileName& instance,
-                bool filterFaces = true
-            );
+            void writeMesh(const fileName& instance);
 
             //- Write mesh to disk
             void writeMesh
@@ -1190,6 +1130,7 @@ public:
                 const word& meshName,
                 const fileName& instance,
                 pointField& points,
+                labelList& boundaryPts,
                 faceList& faces,
                 labelList& owner,
                 labelList& neighbour,
@@ -1198,7 +1139,8 @@ public:
                 const labelList& patchSizes,
                 const labelList& patchStarts,
                 const labelList& procNeighbours,
-                const pointField& cellCentres
+                const pointField& cellCentres,
+                const PackedBoolList& boundaryFacesToRemove
             ) const;
 
             //- Write points and faces as .obj file
@@ -1214,6 +1156,8 @@ public:
             //  actual cell size (cbrt(actual cell volume)).
             void writeCellSizes(const fvMesh& mesh) const;
 
+            void writeCellAlignments(const fvMesh& mesh) const;
+
             //- Calculate and write the cell centres.
             void writeCellCentres(const fvMesh& mesh) const;
 
@@ -1226,90 +1170,6 @@ public:
                 const fileName& fName,
                 const faceList& faces
             ) const;
-
-            //- Function inserting points into a triangulation and setting the
-            //  index and type data of the point in the correct order. This is
-            //  faster than inserting points individually.
-            //
-            //  Adapted from a post on the CGAL lists: 2010-01/msg00004.html by
-            //  Sebastien Loriot (Geometry Factory).
-            //
-            //  @todo problems putting declaration in the .C file. Function
-            //        prototype is not recognised.
-            template<class Triangulation, class Point_iterator>
-            void rangeInsertWithInfo
-            (
-                Point_iterator begin,
-                Point_iterator end,
-                Triangulation& T,
-                DynamicList<label>& indices,
-                DynamicList<label>& types
-            )
-            {
-                typedef std::vector
-                <
-                    std::pair<const typename Triangulation::Point*, label>
-                > vectorPairPointIndex;
-
-                vectorPairPointIndex points;
-                label index = 0;
-
-                for (Point_iterator it = begin; it != end; ++it)
-                {
-                    points.push_back
-                    (
-                        std::make_pair(&(toPoint(*it)), index++)
-                    );
-                }
-
-                std::random_shuffle(points.begin(), points.end());
-
-                spatial_sort
-                (
-                    points.begin(),
-                    points.end(),
-                    Traits_for_spatial_sort<Triangulation>()
-                );
-
-                typename Triangulation::Vertex_handle hint;
-
-                for
-                (
-                    typename vectorPairPointIndex::const_iterator
-                    p = points.begin();
-                    p != points.end();
-                    ++p
-                )
-                {
-                    const size_t checkInsertion = T.number_of_vertices();
-
-                    hint = T.insert(*(p->first), hint);
-
-                    if (checkInsertion != T.number_of_vertices() - 1)
-                    {
-                        Pout<< "Failed to insert point "
-                            << topoint(*(p->first)) << endl;
-                    }
-                    else
-                    {
-                        label oldIndex = p->second;
-
-                        label type = types[oldIndex];
-
-                        if (type > Vb::vtFar)
-                        {
-                            // This is a member of a point pair, don't use the
-                            // type directly (note that this routine never gets
-                            // called for referredPoints so type will never be
-                            // -procI
-                            type += checkInsertion;
-                        }
-
-                        hint->index() = indices[oldIndex] + checkInsertion;
-                        hint->type() = type;
-                    }
-                }
-            }
 };
 
 
@@ -1321,10 +1181,6 @@ public:
 
 #include "conformalVoronoiMeshI.H"
 
-//#ifdef NoRepository
-//#   include "conformalVoronoiMeshTemplates.C"
-//#endif
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #endif
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C
index ec81b1e944a87fb5ce143b11443d6f430def8325..db9fb09ac0f3582040b8448f392fe5caf852cedd 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C
@@ -27,35 +27,21 @@ License
 #include "motionSmoother.H"
 #include "backgroundMeshDecomposition.H"
 #include "polyMeshGeometry.H"
+#include "indexedCellChecks.H"
+
+#include "CGAL/Exact_predicates_exact_constructions_kernel.h"
 
 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
 
-void Foam::conformalVoronoiMesh::calcDualMesh
-(
-    pointField& points,
-    faceList& faces,
-    labelList& owner,
-    labelList& neighbour,
-    wordList& patchTypes,
-    wordList& patchNames,
-    labelList& patchSizes,
-    labelList& patchStarts,
-    labelList& procNeighbours,
-    pointField& cellCentres,
-    labelList& cellToDelaunayVertex,
-    labelListList& patchToDelaunayVertex,
-    bool filterFaces
-)
+void Foam::conformalVoronoiMesh::checkCells()
 {
-    timeCheck("Start calcDualMesh");
-
-    setVertexSizeAndAlignment();
+    List<List<FixedList<Foam::point, 4> > > cellListList(Pstream::nProcs());
 
-    timeCheck("After setVertexSizeAndAlignment");
+    List<FixedList<Foam::point, 4> > cells(number_of_finite_cells());
 
-    // Make all filterCount values zero except on cells that are attached
-    // points that are on the parallel interface.  These will not be moved.
+    globalIndex gIndex(number_of_vertices());
 
+    label count = 0;
     for
     (
         Delaunay::Finite_cells_iterator cit = finite_cells_begin();
@@ -63,214 +49,507 @@ void Foam::conformalVoronoiMesh::calcDualMesh
         ++cit
     )
     {
-        if
-        (
-               !cit->vertex(0)->real()
-            || !cit->vertex(1)->real()
-            || !cit->vertex(2)->real()
-            || !cit->vertex(3)->real()
-        )
+        if (tetrahedron(cit).volume() == 0)
         {
-            cit->filterCount() =
-                 cvMeshControls().filterCountSkipThreshold() + 1;
+            Pout<< "ZERO VOLUME TET" << endl;
+            Pout<< cit->info();
+            Pout<< cit->dual();
         }
-        else
+
+        if (cit->hasFarPoint())
+        {
+            continue;
+        }
+
+        List<labelPair> cellVerticesPair(4);
+        List<Foam::point> cellVertices(4);
+
+        for (label vI = 0; vI < 4; ++vI)
+        {
+            cellVerticesPair[vI] = labelPair
+            (
+                cit->vertex(vI)->procIndex(),
+                cit->vertex(vI)->index()
+            );
+            cellVertices[vI] = topoint(cit->vertex(vI)->point());
+        }
+
+        List<Foam::point> cellVerticesOld(cellVertices);
+        labelList oldToNew;
+        sortedOrder(cellVerticesPair, oldToNew);
+        oldToNew = invert(oldToNew.size(), oldToNew);
+        inplaceReorder(oldToNew, cellVerticesPair);
+        inplaceReorder(oldToNew, cellVertices);
+
+//        Pout<< "old " << cellVerticesOld << nl << "new " << cellVertices << endl;
+
+//
+//        FixedList<label, 4> globalTetCell(cit->globallyOrderedCellVertices(gIndex));
+//
+//        FixedList<Point, 4> cellVertices(Point(0,0,0));
+//
+//        forAll(globalTetCell, gvI)
+//        {
+//            label gI = globalTetCell[gvI];
+//
+//            cellVertices[gvI] = cit->vertex(gI)->point();
+//        }
+
+//        if (cit->hasFarPoint())
+//        {
+//            continue;
+//        }
+
+        for (label i = 0; i < 4; ++i)
         {
-            cit->filterCount() = 0;
+            //cells[count][i] = topoint(cit->vertex(i)->point());
+            cells[count][i] = cellVertices[i];
         }
+
+        count++;
     }
 
-    // THIS CODE STOPS ALL FACES NEAR ANY PROCESSOR BOUNDARY BEING FILTERED.
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        vit++
-    )
+    cells.setSize(count);
+
+    cellListList[Pstream::myProcNo()] = cells;
+
+    Pstream::gatherList(cellListList);
+
+    if (Pstream::master())
     {
-        std::list<Cell_handle> cells;
-        incident_cells(vit, std::back_inserter(cells));
+        Info<< "Checking on master processor the cells of each " << nl
+            << "processor point list against the master cell list." << nl
+            << "There are " << cellListList.size() << " processors" << nl
+            << "The size of each processor's cell list is:" << endl;
 
-        bool hasProcPt = false;
+        forAll(cellListList, cfI)
+        {
+            Info<< "    Proc " << cfI << " has " << cellListList[cfI].size()
+                << " cells" << endl;
+        }
 
-        for
-        (
-            std::list<Cell_handle>::iterator cit = cells.begin();
-            cit != cells.end();
-            ++cit
-        )
+        label nMatches = 0, nMatchFoundDiffOrder = 0;
+
+        forAll(cellListList[0], cmI)
         {
-            // Allow filtering if any vertices are far points. Otherwise faces
-            // with boundary points attached to a cell with a far point will
-            // not be filtered.
-            if
-            (
-                (!(*cit)->vertex(0)->real() && !(*cit)->vertex(0)->farPoint())
-             || (!(*cit)->vertex(1)->real() && !(*cit)->vertex(1)->farPoint())
-             || (!(*cit)->vertex(2)->real() && !(*cit)->vertex(2)->farPoint())
-             || (!(*cit)->vertex(3)->real() && !(*cit)->vertex(3)->farPoint())
-            )
+            const FixedList<Foam::point, 4>& masterCell = cellListList[0][cmI];
+
+            bool matchFound = false;
+            bool matchFoundDiffOrder = false;
+
+            forAll(cellListList, cpI)
             {
-                hasProcPt = true;
+                if (cpI == 0)
+                {
+                    continue;
+                }
+
+                forAll(cellListList[cpI], csI)
+                {
+                    const FixedList<Foam::point, 4>& slaveCell
+                        = cellListList[cpI][csI];
+
+                    if (masterCell == slaveCell)
+                    {
+                        matchFound = true;
+                        break;
+                    }
+                    else
+                    {
+                        label samePt = 0;
+
+                        forAll(masterCell, mI)
+                        {
+                            const Foam::point& mPt = masterCell[mI];
+
+                            forAll(slaveCell, sI)
+                            {
+                                const Foam::point& sPt = slaveCell[sI];
+
+                                if (mPt == sPt)
+                                {
+                                    samePt++;
+                                }
+                            }
+                        }
 
-                break;
+                        if (samePt == 4)
+                        {
+                            matchFoundDiffOrder = true;
+
+                            Pout<< masterCell << nl << slaveCell << endl;
+
+                            break;
+                        }
+                    }
+                }
             }
-        }
 
-        if (hasProcPt)
-        {
-            for
-            (
-                std::list<Cell_handle>::iterator cit = cells.begin();
-                cit != cells.end();
-                ++cit
-            )
+            if (matchFound)
+            {
+                nMatches++;
+            }
+
+            if (matchFoundDiffOrder)
             {
-                (*cit)->filterCount() =
-                     cvMeshControls().filterCountSkipThreshold() + 1;
+                nMatchFoundDiffOrder++;
             }
         }
+
+        Info<< "Found " << nMatches << " matching cells and "
+            << nMatchFoundDiffOrder << " matching cells with different "
+            << "vertex ordering"<< endl;
     }
+}
 
-    PackedBoolList boundaryPts(number_of_cells(), false);
 
-    indexDualVertices(points, boundaryPts);
+void Foam::conformalVoronoiMesh::checkDuals()
+{
+    List<List<Point> > pointFieldList(Pstream::nProcs());
+
+    List<Point> duals(number_of_finite_cells());
+
+    typedef CGAL::Exact_predicates_exact_constructions_kernel   EK2;
+    typedef CGAL::Regular_triangulation_euclidean_traits_3<EK2> EK;
+    typedef CGAL::Cartesian_converter<typename baseK::Kernel, EK2>  To_exact;
+    typedef CGAL::Cartesian_converter<EK2, typename baseK::Kernel>  Back_from_exact;
+
+//    PackedBoolList bPoints(number_of_finite_cells());
 
+//    indexDualVertices(duals, bPoints);
+
+    label count = 0;//duals.size();
+
+    duals.setSize(number_of_finite_cells());
+
+    globalIndex gIndex(number_of_vertices());
+
+    for
+    (
+        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
+        cit != finite_cells_end();
+        ++cit
+    )
     {
-        // Ideally requires a no-risk face filtering to get rid of zero area
-        // faces and establish if the mesh can be produced at all to the
-        // specified criteria
+        if (cit->hasFarPoint())
+        {
+            continue;
+        }
 
-        Info<< nl << "Merging close points" << endl;
+        duals[count++] = cit->circumcenter();
 
-        // There is no guarantee that a merge of close points is no-risk
-        mergeCloseDualVertices(points, boundaryPts);
+//        List<labelPair> cellVerticesPair(4);
+//        List<Point> cellVertices(4);
+//
+//        for (label vI = 0; vI < 4; ++vI)
+//        {
+//            cellVerticesPair[vI] = labelPair
+//            (
+//                cit->vertex(vI)->procIndex(),
+//                cit->vertex(vI)->index()
+//            );
+//            cellVertices[vI] = cit->vertex(vI)->point();
+//        }
+//
+//        labelList oldToNew;
+//        sortedOrder(cellVerticesPair, oldToNew);
+//        oldToNew = invert(oldToNew.size(), oldToNew);
+//        inplaceReorder(oldToNew, cellVerticesPair);
+//        inplaceReorder(oldToNew, cellVertices);
+//
+//        duals[count++] = CGAL::circumcenter
+//        (
+//            cellVertices[0],
+//            cellVertices[1],
+//            cellVertices[2],
+//            cellVertices[3]
+//        );
+
+//        To_exact to_exact;
+//        Back_from_exact back_from_exact;
+//        EK::Construct_circumcenter_3 exact_circumcenter =
+//            EK().construct_circumcenter_3_object();
+//
+//        duals[count++] = topoint
+//        (
+//            back_from_exact
+//            (
+//                exact_circumcenter
+//                (
+//                    to_exact(cit->vertex(0)->point()),
+//                    to_exact(cit->vertex(1)->point()),
+//                    to_exact(cit->vertex(2)->point()),
+//                    to_exact(cit->vertex(3)->point())
+//                )
+//            )
+//        );
     }
 
-    timeCheck("After initial close point merge");
+    Pout<< "Duals Calculated " << count << endl;
 
-    if (filterFaces)
-    {
-        label nInitialBadQualityFaces = checkPolyMeshQuality(points).size();
+    duals.setSize(count);
 
-        reduce(nInitialBadQualityFaces, sumOp<label>());
+    pointFieldList[Pstream::myProcNo()] = duals;
 
-        Info<< nl << "Initial check before face collapse, found "
-            << nInitialBadQualityFaces << " bad quality faces"
-            << endl;
+    Pstream::gatherList(pointFieldList);
 
-        HashSet<labelPair, labelPair::Hash<> > deferredCollapseFaces;
+    if (Pstream::master())
+    {
+        Info<< "Checking on master processor the dual locations of each " << nl
+            << "processor point list against the master dual list." << nl
+            << "There are " << pointFieldList.size() << " processors" << nl
+            << "The size of each processor's dual list is:" << endl;
 
-        if (nInitialBadQualityFaces > 0)
+        forAll(pointFieldList, pfI)
         {
-            Info<< nl
-                << "A mesh could not be produced to satisfy the specified "
-                << "quality criteria." << nl
-                << "The quality and the surface conformation controls "
-                << "can be altered and the " << nl
-                << "internalDelaunayVertices read in to try again, or more "
-                << "cell size resolution " << nl
-                << "and motion iterations can be applied in areas where "
-                << "problems are occurring."
-                << endl;
+            Info<< "    Proc " << pfI << " has " << pointFieldList[pfI].size()
+                << " duals" << endl;
         }
 
-        if
-        (
-            nInitialBadQualityFaces == 0
-         || cvMeshControls().continueFilteringOnBadInitialPolyMesh()
-        )
+        label nNonMatches = 0;
+        label nNearMatches = 0;
+        label nExactMatches = 0;
+
+        forAll(pointFieldList[0], pI)
         {
-            label nBadQualityFaces = 0;
+            const Point& masterPoint = pointFieldList[0][pI];
 
-            labelHashSet lastWrongFaces;
+            bool foundMatch = false;
+            bool foundNearMatch = false;
 
-            label nConsecutiveEqualFaceSets = 0;
+            scalar minCloseness = GREAT;
+            Point closestPoint(0, 0, 0);
 
-            do
+            forAll(pointFieldList, pfI)
             {
-                // Reindexing the Delaunay cells and regenerating the
-                // points resets the mesh to the starting condition.
+                if (pfI == 0)
+                {
+                    continue;
+                }
 
-                indexDualVertices(points, boundaryPts);
+//                label pfI = 1;
 
+                forAll(pointFieldList[pfI], pISlave)
                 {
-                    Info<< nl << "Merging close points" << endl;
+                    const Point& slavePoint
+                        = pointFieldList[pfI][pISlave];
+
+                    if (masterPoint == slavePoint)
+                    {
+                        foundMatch = true;
+                        break;
+                    }
+
+                    const scalar closeness = mag
+                    (
+                        topoint(masterPoint) - topoint(slavePoint)
+                    );
 
-                    mergeCloseDualVertices(points, boundaryPts);
+                    if (closeness < 1e-12)
+                    {
+                        foundNearMatch = true;
+                    }
+                    else
+                    {
+                        if (closeness < minCloseness)
+                        {
+                            minCloseness = closeness;
+                            closestPoint = slavePoint;
+                        }
+                    }
                 }
 
+                if (!foundMatch)
                 {
-                    // Risky and undo-able face filtering to reduce
-                    // the face count as much as possible, staying
-                    // within the specified criteria
+                    if (foundNearMatch)
+                    {
+                        CGAL::Gmpq x(CGAL::to_double(masterPoint.x()));
+                        CGAL::Gmpq y(CGAL::to_double(masterPoint.y()));
+                        CGAL::Gmpq z(CGAL::to_double(masterPoint.z()));
 
-                    Info<< nl << "Smoothing surface" << endl;
+                        std::cout<< "master = " << x << " " << y << " " << z
+                            << std::endl;
 
-                    smoothSurface(points, boundaryPts);
 
-                    Info<< nl << "Collapsing unnecessary faces" << endl;
+                        CGAL::Gmpq xs(CGAL::to_double(closestPoint.x()));
+                        CGAL::Gmpq ys(CGAL::to_double(closestPoint.y()));
+                        CGAL::Gmpq zs(CGAL::to_double(closestPoint.z()));
+                        std::cout<< "slave  = " << xs << " " << ys << " " << zs
+                            << std::endl;
 
-                    collapseFaces(points, boundaryPts, deferredCollapseFaces);
+                        nNearMatches++;
+                    }
+                    else
+                    {
+                        nNonMatches++;
+                        Info<< "    Closest point to " << masterPoint << " is "
+                            << closestPoint << nl
+                            << "    Separation is " << minCloseness << endl;
 
-                    const scalar maxCosAngle
-                        = cos(degToRad(cvMeshControls().edgeMergeAngle()));
+                        CGAL::Gmpq x(CGAL::to_double(masterPoint.x()));
+                        CGAL::Gmpq y(CGAL::to_double(masterPoint.y()));
+                        CGAL::Gmpq z(CGAL::to_double(masterPoint.z()));
 
-                    Info<< nl << "Merging adjacent edges which have an angle "
-                        << "of greater than "
-                        << cvMeshControls().edgeMergeAngle() << ": " << endl;
+                        std::cout<< "master = " << x << " " << y << " " << z << endl;
 
-                    label nRemovedEdges =
-                        mergeNearlyParallelEdges(points, maxCosAngle);
 
-                    reduce(nRemovedEdges, sumOp<label>());
+                        CGAL::Gmpq xs(CGAL::to_double(closestPoint.x()));
+                        CGAL::Gmpq ys(CGAL::to_double(closestPoint.y()));
+                        CGAL::Gmpq zs(CGAL::to_double(closestPoint.z()));
+                        std::cout<< "slave  = " << xs << " " << ys << " " << zs << endl;
 
-                    Info<< "    Merged " << nRemovedEdges << " edges" << endl;
+                    }
+                }
+                else
+                {
+                    nExactMatches++;
                 }
+            }
+        }
+
+        Info<< "Found " << nNonMatches << " non-matching duals" << nl
+            << " and " << nNearMatches << " near matches"
+            << " and " << nExactMatches << " exact matches" << endl;
+    }
+}
+
+
+void Foam::conformalVoronoiMesh::checkVertices()
+{
+    List<pointField> pointFieldList(Pstream::nProcs());
+
+    pointField points(number_of_vertices());
+
+    labelPairHashSet duplicateVertices;
+
+    label count = 0;
+    for
+    (
+        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (duplicateVertices.found(labelPair(vit->procIndex(), vit->index())))
+        {
+            Pout<< "DUPLICATE " << vit->procIndex() << vit->index() << endl;
+        }
+        else
+        {
+            duplicateVertices.insert(labelPair(vit->procIndex(), vit->index()));
+        }
 
-                labelHashSet wrongFaces = checkPolyMeshQuality(points);
+        points[count++] = topoint(vit->point());
+    }
+
+    pointFieldList[Pstream::myProcNo()] = points;
 
-                nBadQualityFaces = wrongFaces.size();
+    Pstream::gatherList(pointFieldList);
 
-                reduce(nBadQualityFaces, sumOp<label>());
+    OFstream str("missingPoints.obj");
+
+    if (Pstream::master())
+    {
+        Info<< "Checking on master processor the point locations of each " << nl
+            << "processor point list against the master point list." << nl
+            << "There are " << pointFieldList.size() << " processors" << nl
+            << "The size of each processor's point list is:" << endl;
 
-                Info<< nl << "Found " << nBadQualityFaces
-                    << " bad quality faces" << endl;
+        forAll(pointFieldList, pfI)
+        {
+            Info<< "    Proc " << pfI << " has " << pointFieldList[pfI].size()
+                << " points" << endl;
+        }
 
-                bool sameFacesAsLastTime(lastWrongFaces == wrongFaces);
+        label nNonMatches = 0;
 
-                reduce(sameFacesAsLastTime, andOp<bool>());
+        forAll(pointFieldList[0], pI)
+        {
+            const Foam::point& masterPoint = pointFieldList[0][pI];
 
-                if (sameFacesAsLastTime)
+            forAll(pointFieldList, pfI)
+            {
+                if (pI == 0)
                 {
-                    Info<< nl << "Consecutive iterations found the same set "
-                        << "of bad quality faces." << endl;
+                    continue;
+                }
 
-                    if
-                    (
-                        ++nConsecutiveEqualFaceSets
-                     >= cvMeshControls().maxConsecutiveEqualFaceSets()
-                    )
-                    {
-                        Info<< nl << nConsecutiveEqualFaceSets
-                            << " consecutive iterations produced the same "
-                            << "bad quality faceSet, stopping filtering"
-                            << endl;
+                bool foundMatch = false;
+
+                forAll(pointFieldList[pfI], pISlave)
+                {
+                    const Foam::point& slavePoint
+                        = pointFieldList[pfI][pISlave];
 
+                    if (masterPoint == slavePoint)
+                    {
+                        foundMatch = true;
                         break;
                     }
                 }
-                else
+
+                if (!foundMatch)
                 {
-                    nConsecutiveEqualFaceSets = 0;
+                    Info<< "    Proc " << pfI << " Master != Slave -> "
+                        << masterPoint << endl;
 
-                    lastWrongFaces = wrongFaces;
+                    meshTools::writeOBJ(str, masterPoint);
+
+                    nNonMatches++;
                 }
+            }
+        }
+
+        Info<< "Found a total of " << nNonMatches << " non-matching points"
+            << endl;
+    }
+}
 
-                timeCheck("End of filtering iteration");
 
-            } while (nBadQualityFaces > 0); //nInitialBadQualityFaces);
-        }
+void Foam::conformalVoronoiMesh::calcDualMesh
+(
+    pointField& points,
+    labelList& boundaryPts,
+    faceList& faces,
+    labelList& owner,
+    labelList& neighbour,
+    wordList& patchTypes,
+    wordList& patchNames,
+    labelList& patchSizes,
+    labelList& patchStarts,
+    labelList& procNeighbours,
+    pointField& cellCentres,
+    labelList& cellToDelaunayVertex,
+    labelListList& patchToDelaunayVertex,
+    PackedBoolList& boundaryFacesToRemove
+)
+{
+    timeCheck("Start calcDualMesh");
+
+//    if (debug)
+//    {
+//        Pout<< nl << "Perfoming some checks . . ." << nl << nl
+//            << "Total number of vertices = " << number_of_vertices() << nl
+//            << "Total number of cells    = " << number_of_finite_cells() << endl;
+//
+//        checkVertices();
+//        checkCells();
+//        checkDuals();
+//
+//        Info<< nl << "Finished checks" << nl << endl;
+//    }
+
+    setVertexSizeAndAlignment();
+
+    timeCheck("After setVertexSizeAndAlignment");
+
+    indexDualVertices(points, boundaryPts);
+
+    {
+        Info<< nl << "Merging identical points" << endl;
+
+        // There is no guarantee that a merge of close points is no-risk
+        mergeIdenticalDualVertices(points, boundaryPts);
     }
 
     // Final dual face and owner neighbour construction
@@ -288,6 +567,7 @@ void Foam::conformalVoronoiMesh::calcDualMesh
         patchStarts,
         procNeighbours,
         patchToDelaunayVertex,  // from patch face to Delaunay vertex (slavePp)
+        boundaryFacesToRemove,
         false
     );
 
@@ -299,7 +579,7 @@ void Foam::conformalVoronoiMesh::calcDualMesh
 
     cellCentres = pointField(cellCentres, cellToDelaunayVertex);
 
-    removeUnusedPoints(faces, points);
+    removeUnusedPoints(faces, points, boundaryPts);
 
     timeCheck("End of calcDualMesh");
 }
@@ -332,7 +612,7 @@ void Foam::conformalVoronoiMesh::calcTetMesh
         ++vit
     )
     {
-        if (vit->internalPoint() || vit->pairPoint())
+        if (vit->internalPoint() || vit->boundaryPoint())
         {
             vertexMap[vit->index()] = vertI;
             points[vertI] = topoint(vit->point());
@@ -376,11 +656,11 @@ void Foam::conformalVoronoiMesh::calcTetMesh
 
     List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
 
-    faces.setSize(number_of_facets());
+    faces.setSize(number_of_finite_facets());
 
-    owner.setSize(number_of_facets());
+    owner.setSize(number_of_finite_facets());
 
-    neighbour.setSize(number_of_facets());
+    neighbour.setSize(number_of_finite_facets());
 
     label faceI = 0;
 
@@ -399,7 +679,7 @@ void Foam::conformalVoronoiMesh::calcTetMesh
         const int oppositeVertex = fit->second;
         const Cell_handle c2(c1->neighbor(oppositeVertex));
 
-        if (c1->farCell() && c2->farCell())
+        if (c1->hasFarPoint() && c2->hasFarPoint())
         {
             // Both tets are outside, skip
             continue;
@@ -421,10 +701,10 @@ void Foam::conformalVoronoiMesh::calcTetMesh
 
         newFace = face(verticesOnTriFace);
 
-        if (c1->farCell() || c2->farCell())
+        if (c1->hasFarPoint() || c2->hasFarPoint())
         {
             // Boundary face...
-            if (c1->farCell())
+            if (c1->hasFarPoint())
             {
                 //... with c1 outside
                 ownerCell = c2I;
@@ -490,23 +770,23 @@ void Foam::conformalVoronoiMesh::calcTetMesh
 
     sortFaces(faces, owner, neighbour);
 
-    addPatches
-    (
-        nInternalFaces,
-        faces,
-        owner,
-        patchSizes,
-        patchStarts,
-        patchFaces,
-        patchOwners
-    );
+//    addPatches
+//    (
+//        nInternalFaces,
+//        faces,
+//        owner,
+//        patchSizes,
+//        patchStarts,
+//        patchFaces,
+//        patchOwners
+//    );
 }
 
 
-void Foam::conformalVoronoiMesh::mergeCloseDualVertices
+void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices
 (
     const pointField& pts,
-    const PackedBoolList& boundaryPts
+    const labelList& boundaryPts
 )
 {
     // Assess close points to be merged
@@ -518,18 +798,13 @@ void Foam::conformalVoronoiMesh::mergeCloseDualVertices
     {
         Map<label> dualPtIndexMap;
 
-        nPtsMerged = mergeCloseDualVertices
+        nPtsMerged = mergeIdenticalDualVertices
         (
             pts,
             boundaryPts,
             dualPtIndexMap
         );
 
-        // if (nPtsMerged > 0)
-        // {
-        //     Pout<< "    Merged " << nPtsMerged << " points " << endl;
-        // }
-
         reindexDualVertices(dualPtIndexMap);
 
         reduce(nPtsMerged, sumOp<label>());
@@ -545,30 +820,15 @@ void Foam::conformalVoronoiMesh::mergeCloseDualVertices
 }
 
 
-Foam::label Foam::conformalVoronoiMesh::mergeCloseDualVertices
+Foam::label Foam::conformalVoronoiMesh::mergeIdenticalDualVertices
 (
     const pointField& pts,
-    const PackedBoolList& boundaryPts,
+    const labelList& boundaryPts,
     Map<label>& dualPtIndexMap
 ) const
 {
     label nPtsMerged = 0;
 
-    label nIdentical = 0;
-    label nProcEdge = 0;
-
-    // Relative distance for points to be merged
-    scalar closenessTolerance = cvMeshControls().mergeClosenessCoeff();
-
-    // Absolute distance for points to be considered coincident. Bit adhoc
-    // but points were seen with distSqr ~ 1e-30 which is SMALL^2. Add a few
-    // digits to account for truncation errors.
-    scalar coincidentDistanceSqr = sqr
-    (
-        SMALL*1E2*geometryToConformTo_.globalBounds().mag()
-    );
-
-
     for
     (
         Delaunay::Finite_facets_iterator fit = finite_facets_begin();
@@ -580,1260 +840,309 @@ Foam::label Foam::conformalVoronoiMesh::mergeCloseDualVertices
         const int oppositeVertex = fit->second;
         const Cell_handle c2(c1->neighbor(oppositeVertex));
 
-        label& c1I = c1->cellIndex();
-        label& c2I = c2->cellIndex();
-
-        if (dualPtIndexMap.found(c1I) || dualPtIndexMap.found(c2I))
+        if (is_infinite(c1) || is_infinite(c2))
         {
-            // One of the points of this edge has already been
-            // merged this sweep, leave for next sweep
-
             continue;
         }
 
-        if ((c1I != c2I) && !c1->farCell() && !c2->farCell())
-        {
-            scalar distSqr = magSqr(pts[c1I] - pts[c2I]);
-
-            if (pts[c1I] == pts[c2I] || distSqr < coincidentDistanceSqr)
-            {
-                nIdentical++;
-
-                if (boundaryPts[c2I] == true)
-                {
-                    // If c2I is a boundary point, then it is kept.
-                    // If both are boundary points then c2I is chosen
-                    // arbitrarily to be kept.
+        label& c1I = c1->cellIndex();
+        label& c2I = c2->cellIndex();
 
-                    dualPtIndexMap.insert(c1I, c2I);
-                    dualPtIndexMap.insert(c2I, c2I);
-                    nPtsMerged++;
-                }
-                else
-                {
-                    dualPtIndexMap.insert(c1I, c1I);
-                    dualPtIndexMap.insert(c2I, c1I);
-                    nPtsMerged++;
-                }
+        if ((c1I != c2I) && !c1->hasFarPoint() && !c2->hasFarPoint())
+        {
+            const Foam::point& p1 = pts[c1I];
+            const Foam::point& p2 = pts[c2I];
 
-            }
-            else if (distSqr < sqr(averageAnyCellSize(fit)*closenessTolerance))
+            if (p1 == p2)
             {
-                if (c1->parallelDualVertex() || c2->parallelDualVertex())
-                //if (isParallelDualEdge(fit))
-                {
-                    // Skip if face uses any edge that becomes a processor
-                    // dual face.
-                    // Note: the real test should be whether the Delaunay edge
-                    //  will form a processor patch.
-                    nProcEdge++;
-                }
-                else if (boundaryPts[c2I] == true)
-                {
-                    // If c2I is a boundary point, then it is kept.
-                    // If both are boundary points then c2I is chosen
-                    // arbitrarily to be kept.
-
-                    dualPtIndexMap.insert(c1I, c2I);
-                    dualPtIndexMap.insert(c2I, c2I);
-                    nPtsMerged++;
-                }
-                else
+                if (c1I < c2I)
                 {
                     dualPtIndexMap.insert(c1I, c1I);
                     dualPtIndexMap.insert(c2I, c1I);
-                    nPtsMerged++;
-                }
-            }
-        }
-    }
-
-    if (debug)
-    {
-        Info<< "mergeCloseDualVertices:"
-            << " coincident distance:" << coincidentDistanceSqr
-            << " closenessTolerance:" << closenessTolerance << endl
-            << "    zero-length edges         : "
-            << returnReduce(nIdentical, sumOp<label>()) << endl
-            << "    protected processor edges : "
-            << returnReduce(nProcEdge, sumOp<label>()) << endl
-            << "    collapsed edges           : "
-            << returnReduce(nPtsMerged, sumOp<label>()) << endl
-            << endl;
-    }
-
-    return nPtsMerged;
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::mergeNearlyParallelEdges
-(
-    const pointField& pts,
-    const scalar maxCosAngle
-)
-{
-    List<HashSet<label> > pointFaceCount(number_of_cells());
-    labelList pointNeighbour(number_of_cells(), -1);
-
-    Map<label> dualPtIndexMap;
-
-    for
-    (
-        Delaunay::Finite_edges_iterator eit = finite_edges_begin();
-        eit != finite_edges_end();
-        ++eit
-    )
-    {
-        Cell_handle c = eit->first;
-        Vertex_handle vA = c->vertex(eit->second);
-        Vertex_handle vB = c->vertex(eit->third);
-
-        if (isBoundaryDualFace(eit))
-        {
-            const face f = buildDualFace(eit);
-
-            forAll(f, pI)
-            {
-                const label pIndex = f[pI];
-
-                const label prevPointI = f.prevLabel(pI);
-                const label nextPointI = f.nextLabel(pI);
-
-                pointFaceCount[pIndex].insert(prevPointI);
-                pointFaceCount[pIndex].insert(nextPointI);
-                pointNeighbour[pIndex] = nextPointI;
-            }
-        }
-        else if
-        (
-            vA->internalOrBoundaryPoint()
-         || vB->internalOrBoundaryPoint()
-        )
-        {
-            const face f = buildDualFace(eit);
-            const boolList faceBoundaryPoints = dualFaceBoundaryPoints(eit);
-
-            forAll(f, pI)
-            {
-                const label pIndex = f[pI];
-
-                const label prevPointI = f.prevLabel(pI);
-                const label nextPointI = f.nextLabel(pI);
-
-                pointFaceCount[pIndex].insert(prevPointI);
-                pointFaceCount[pIndex].insert(nextPointI);
-
-                if (faceBoundaryPoints[pI] == false)
-                {
-                    pointNeighbour[pIndex] = nextPointI;
                 }
                 else
                 {
-                    if (faceBoundaryPoints[prevPointI] == true)
-                    {
-                        pointNeighbour[pIndex] = prevPointI;
-                    }
-                    else if (faceBoundaryPoints[nextPointI] == true)
-                    {
-                        pointNeighbour[pIndex] = nextPointI;
-                    }
-                    else
-                    {
-                        pointNeighbour[pIndex] = pIndex;
-                    }
-                }
-            }
-        }
-    }
-
-    forAll(pointFaceCount, pI)
-    {
-        if (pointFaceCount[pI].size() == 2)
-        {
-            List<vector> edges(2, vector(0, 0, 0));
-
-            label count = 0;
-            forAllConstIter(HashSet<label>, pointFaceCount[pI], iter)
-            {
-                edges[count] = pts[pI] - pts[iter.key()];
-                edges[count] /= mag(edges[count]) + VSMALL;
-                count++;
-            }
-
-            if (mag(edges[0] & edges[1]) > maxCosAngle)
-            {
-                dualPtIndexMap.insert(pI, pointNeighbour[pI]);
-            }
-        }
-    }
-
-    reindexDualVertices(dualPtIndexMap);
-
-    return dualPtIndexMap.size();
-}
-
-
-void Foam::conformalVoronoiMesh::smoothSurface
-(
-    pointField& pts,
-    const PackedBoolList& boundaryPts
-)
-{
-    label nCollapsedFaces = 0;
-
-    label iterI = 0;
-
-    do
-    {
-        Map<label> dualPtIndexMap;
-
-        nCollapsedFaces = smoothSurfaceDualFaces
-        (
-            pts,
-            boundaryPts,
-            dualPtIndexMap
-        );
-
-        reduce(nCollapsedFaces, sumOp<label>());
-
-        reindexDualVertices(dualPtIndexMap);
-
-        mergeCloseDualVertices(pts, boundaryPts);
-
-        if (nCollapsedFaces > 0)
-        {
-            Info<< "    Collapsed " << nCollapsedFaces << " boundary faces"
-                << endl;
-        }
-
-        if (++iterI > cvMeshControls().maxCollapseIterations())
-        {
-            Info<< "    maxCollapseIterations reached, stopping collapse"
-                << endl;
-
-            break;
-        }
-
-    } while (nCollapsedFaces > 0);
-
-    // Force all points of boundary faces to be on the surface
-    for
-    (
-        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-        cit != finite_cells_end();
-        ++cit
-    )
-    {
-        label ptI = cit->cellIndex();
-
-        label fC = cit->filterCount();
-
-        if (fC > cvMeshControls().filterCountSkipThreshold())
-        {
-            // This vertex has been limited too many times, skip
-            continue;
-        }
-
-        // Only cells with indices > -1 are valid
-        if (ptI > -1)
-        {
-            if (boundaryPts[ptI] == true)
-            {
-                Foam::point& pt = pts[ptI];
-
-                pointIndexHit surfHit;
-                label hitSurface;
-
-                geometryToConformTo_.findSurfaceNearest
-                (
-                    pt,
-                    sqr(GREAT),
-                    surfHit,
-                    hitSurface
-                );
-
-                if (surfHit.hit())
-                {
-                    pt +=
-                        (surfHit.hitPoint() - pt)
-                       *pow(cvMeshControls().filterErrorReductionCoeff(), fC);
-                }
-            }
-        }
-    }
-
-    mergeCloseDualVertices(pts, boundaryPts);
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
-(
-    pointField& pts,
-    const PackedBoolList& boundaryPts,
-    Map<label>& dualPtIndexMap
-) const
-{
-    label nCollapsedFaces = 0;
-
-    const scalar cosPerpendicularToleranceAngle = cos
-    (
-        degToRad(cvMeshControls().surfaceStepFaceAngle())
-    );
-
-    for
-    (
-        Delaunay::Finite_edges_iterator eit = finite_edges_begin();
-        eit != finite_edges_end();
-        ++eit
-    )
-    {
-        Cell_circulator ccStart = incident_cells(*eit);
-        Cell_circulator cc = ccStart;
-
-        bool skipFace = false;
-
-        do
-        {
-            if (dualPtIndexMap.found(cc->cellIndex()))
-            {
-                // One of the points of this face has already been
-                // collapsed this sweep, leave for next sweep
-
-                skipFace = true;
-
-                break;
-            }
-
-        } while (++cc != ccStart);
-
-        if (skipFace)
-        {
-            continue;
-        }
-
-        if (isBoundaryDualFace(eit))
-        {
-            face dualFace = buildDualFace(eit);
-
-            if (dualFace.size() < 3)
-            {
-                // This face has been collapsed already
-                continue;
-            }
-
-            label maxFC = maxFilterCount(eit);
-
-            if (maxFC > cvMeshControls().filterCountSkipThreshold())
-            {
-                // A vertex on this face has been limited too many
-                // times, skip
-                continue;
-            }
-
-            pointIndexHit surfHit;
-            label hitSurface;
-
-            geometryToConformTo_.findSurfaceNearest
-            (
-                dualFace.centre(pts),
-                sqr(GREAT),
-                surfHit,
-                hitSurface
-            );
-
-            vectorField norm(1);
-
-            allGeometry_[hitSurface].getNormal
-            (
-                List<pointIndexHit>(1, surfHit),
-                norm
-            );
-
-            const vector& surfaceNormal = norm[0];
-
-            // Orient the face correctly before calculating the normal
-
-            Cell_handle c = eit->first;
-            Vertex_handle vA = c->vertex(eit->second);
-            Vertex_handle vB = c->vertex(eit->third);
-
-            if (!vA->internalOrBoundaryPoint())
-            {
-                reverse(dualFace);
-            }
-
-            vector faceNormal = dualFace.normal(pts);
-
-            if (mag(faceNormal) < VSMALL)
-            {
-                // If the face is essentially zero area, then force it
-                // to be collapsed by making the dot product result -1
-                faceNormal = -surfaceNormal;
-            }
-            else
-            {
-                faceNormal /= mag(faceNormal);
-            }
-
-            if ((faceNormal & surfaceNormal) < cosPerpendicularToleranceAngle)
-            {
-                scalar targetFaceSize = averageAnyCellSize(vA, vB);
-
-                // Selecting faces to collapse based on angle to
-                // surface, so set collapseSizeLimitCoeff to GREAT to
-                // allow collapse of all faces
-
-                faceCollapseMode mode = collapseFace
-                (
-                    dualFace,
-                    pts,
-                    boundaryPts,
-                    dualPtIndexMap,
-                    targetFaceSize,
-                    GREAT,
-                    maxFC
-                );
-
-                if (mode == fcmPoint || mode == fcmEdge)
-                {
-                    nCollapsedFaces++;
-                }
-            }
-        }
-    }
-
-    return nCollapsedFaces;
-}
-
-
-void Foam::conformalVoronoiMesh::collapseFaces
-(
-    pointField& pts,
-    const PackedBoolList& boundaryPts,
-    HashSet<labelPair, labelPair::Hash<> >& deferredCollapseFaces
-)
-{
-    label nCollapsedFaces = 0;
-
-    label iterI = 0;
-
-    do
-    {
-        Map<label> dualPtIndexMap;
-
-        deferredCollapseFaces.clear();
-
-        nCollapsedFaces = collapseFaces
-        (
-            pts,
-            boundaryPts,
-            dualPtIndexMap,
-            deferredCollapseFaces
-        );
-
-        reduce(nCollapsedFaces, sumOp<label>());
-
-        reindexDualVertices(dualPtIndexMap);
-
-        mergeCloseDualVertices(pts, boundaryPts);
-
-
-        if (nCollapsedFaces > 0)
-        {
-            Info<< "    Collapsed " << nCollapsedFaces << " faces" << endl;
-            // Info<< "dualPtIndexMap" << nl << dualPtIndexMap << endl;
-        }
-
-        if (++iterI > cvMeshControls().maxCollapseIterations())
-        {
-            Info<< nl << "maxCollapseIterations reached, stopping collapse"
-                << endl;
-
-            break;
-        }
-
-    } while (nCollapsedFaces > 0);
-
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::collapseFaces
-(
-    pointField& pts,
-    const PackedBoolList& boundaryPts,
-    Map<label>& dualPtIndexMap,
-    HashSet<labelPair, labelPair::Hash<> >& deferredCollapseFaces
-) const
-{
-    label nCollapsedFaces = 0;
-
-    scalar collapseSizeLimitCoeff = cvMeshControls().filterSizeCoeff();
-
-    for
-    (
-        Delaunay::Finite_edges_iterator eit = finite_edges_begin();
-        eit != finite_edges_end();
-        ++eit
-    )
-    {
-        Cell_circulator ccStart = incident_cells(*eit);
-        Cell_circulator cc = ccStart;
-
-        bool skipFace = false;
-
-        do
-        {
-            if (dualPtIndexMap.found(cc->cellIndex()))
-            {
-                // One of the points of this face has already been
-                // collapsed this sweep, leave for next sweep
-
-                skipFace = true;
-
-                break;
-            }
-
-        } while (++cc != ccStart);
-
-        if (skipFace)
-        {
-            continue;
-        }
-
-        Cell_handle c = eit->first;
-        Vertex_handle vA = c->vertex(eit->second);
-        Vertex_handle vB = c->vertex(eit->third);
-
-        if
-        (
-            vA->internalOrBoundaryPoint()
-         || vB->internalOrBoundaryPoint()
-        )
-        {
-            face dualFace = buildDualFace(eit);
-
-            if (dualFace.size() < 3)
-            {
-                continue;
-            }
-
-            label maxFC = maxFilterCount(eit);
-
-            if (maxFC > cvMeshControls().filterCountSkipThreshold())
-            {
-                continue;
-            }
-
-            scalar targetFaceSize = averageAnyCellSize(vA, vB);
-
-            faceCollapseMode mode = collapseFace
-            (
-                dualFace,
-                pts,
-                boundaryPts,
-                dualPtIndexMap,
-                targetFaceSize,
-                collapseSizeLimitCoeff,
-                maxFC
-            );
-
-            if (mode != fcmNone)
-            {
-                if (mode == fcmDeferredMultiEdge)
-                {
-                    // Determine the owner and neighbour labels
-
-                    Pair<label> ownAndNei(-1, -1);
-
-                    ownerAndNeighbour
-                    (
-                        vA,
-                        vB,
-                        ownAndNei.first(),
-                        ownAndNei.second()
-                    );
-
-                    // Record the owner and neighbour of this face for a
-                    // deferredMultiEdge collapse
-
-                    deferredCollapseFaces.insert(ownAndNei);
-                }
-                else
-                {
-                    nCollapsedFaces++;
-                }
-            }
-        }
-    }
-
-    return nCollapsedFaces;
-}
-
-
-Foam::conformalVoronoiMesh::faceCollapseMode
-Foam::conformalVoronoiMesh::collapseFace
-(
-    const face& f,
-    pointField& pts,
-    const PackedBoolList& boundaryPts,
-    Map<label>& dualPtIndexMap,
-    scalar targetFaceSize,
-    scalar collapseSizeLimitCoeff,
-    label maxFC
-) const
-{
-    bool limitToQuadsOrTris = false;
-
-    bool allowEarlyCollapseToPoint = true;
-
-
-//    // Quick exit
-//    label smallEdges = 0;
-//    const edgeList& fEdges = f.edges();
-//    forAll(fEdges, eI)
-//    {
-//        const edge& e = fEdges[eI];
-//
-//        if (e.mag(pts) < 0.2*targetFaceSize)
-//        {
-//            smallEdges++;
-//        }
-//    }
-//    if (smallEdges == 0)
-//    {
-//        return fcmNone;
-//    }
-
-
-    // if (maxFC > cvMeshControls().filterCountSkipThreshold() - 3)
-    // {
-    //     limitToQuadsOrTris = true;
-
-    //     allowEarlyCollapseToPoint = false;
-    // }
-
-
-    collapseSizeLimitCoeff *= pow
-    (
-        cvMeshControls().filterErrorReductionCoeff(),
-        maxFC
-    );
-
-    labelList facePts(f);
-
-    const Foam::point fC = f.centre(pts);
-
-    vector fN = f.normal(pts);
-
-    const scalar fA = mag(fN);
-
-    tensor J = f.inertia(pts, fC);
-
-    // Find the dominant collapse direction by finding the eigenvector
-    // that corresponds to the normal direction, discarding it.  The
-    // eigenvector corresponding to the smaller of the two remaining
-    // eigenvalues is the dominant axis in a high aspect ratio face.
-
-    scalar magJ = mag(J);
-
-    scalar detJ = SMALL;
-
-    if (magJ > VSMALL)
-    {
-        // Normalise inertia tensor to remove problems with small values
-
-        J /= mag(J);
-        // J /= cmptMax(J);
-        // J /= max(eigenValues(J).x(), SMALL);
-
-        // Calculating determinant, including stabilisation for zero or
-        // small negative values
-
-        detJ = max(det(J), SMALL);
-    }
-
-    vector collapseAxis = vector::zero;
-
-    scalar aspectRatio = 1.0;
-
-    if (detJ < 1e-5)
-    {
-        collapseAxis = f.edges()[longestEdge(f, pts)].vec(pts);
-
-        collapseAxis /= mag(collapseAxis);
-
-        // Empirical correlation for high aspect ratio faces
-
-        aspectRatio = sqrt(0.35/detJ);
-    }
-    else
-    {
-        vector eVals = eigenValues(J);
-
-        if (mag(eVals.y() - eVals.x()) < 100*SMALL)
-        {
-            // First two eigenvalues are the same: i.e. a square face
-
-            // Cannot necessarily determine linearly independent
-            // eigenvectors, or any at all, use longest edge direction.
-
-            collapseAxis = f.edges()[longestEdge(f, pts)].vec(pts);
-
-            collapseAxis /= mag(collapseAxis);
-
-            aspectRatio = 1.0;
-        }
-        else
-        {
-            // The maximum eigenvalue (z()) must be the direction of the
-            // normal, as it has the greatest value.  The minimum eigenvalue
-            // is the dominant collapse axis for high aspect ratio faces.
-
-            collapseAxis = eigenVector(J, eVals.x());
-
-            // The inertia calculation describes the mass distribution as a
-            // function of distance squared to the axis, so the square root of
-            // the ratio of face-plane moments gives a good indication of the
-            // aspect ratio.
-
-            aspectRatio = sqrt(eVals.y()/max(eVals.x(), SMALL));
-        }
-    }
-
-
-    scalar maxDist = 0;
-    scalar minDist = GREAT;
-//
-//    if (f.size() <= 3)
-//    {
-//        const edgeList& fEdges = f.edges();
-//
-//        forAll(fEdges, eI)
-//        {
-//            const edge& e = fEdges[eI];
-//            const scalar d = e.mag(pts);
-//
-//            if (d > maxDist)
-//            {
-//                maxDist = d;
-//                collapseAxis = e.vec(pts);
-//            }
-//            else if (d < minDist && d != 0)
-//            {
-//                minDist = d;
-//            }
-//        }
-//    }
-//    else
-//    {
-//        forAll(f, pI)
-//        {
-//            for (label i = pI + 1; i < f.size(); ++i)
-//            {
-//                if
-//                (
-//                    f[i] != f.nextLabel(pI)
-//                 && f[i] != f.prevLabel(pI)
-//                )
-//                {
-//                    scalar d = mag(pts[f[pI]] - pts[f[i]]);
-//
-//                    if (d > maxDist)
-//                    {
-//                        maxDist = d;
-//                        collapseAxis = pts[f[pI]] - pts[f[i]];
-//                    }
-//                    else if (d < minDist && d != 0)
-//                    {
-//                        minDist = d;
-//                    }
-//                }
-//            }
-//        }
-//    }
-//
-//    const edgeList& fEdges = f.edges();
-//
-//    scalar perimeter = 0;
-//
-//    forAll(fEdges, eI)
-//    {
-//        const edge& e = fEdges[eI];
-//        const scalar d = e.mag(pts);
-//
-//        perimeter += d;
-//
-////        collapseAxis += e.vec(pts);
-//
-//        if (d > maxDist)
-//        {
-//            collapseAxis = e.vec(pts);
-//            maxDist = d;
-//        }
-//        else if (d < minDist && d != 0)
-//        {
-//            minDist = d;
-//        }
-//    }
-//
-//    collapseAxis /= mag(collapseAxis);
-//
-////    Info<< f.size() << " " << minDist << " " << maxDist << " | "
-////        << collapseAxis << endl;
-//
-//    aspectRatio = maxDist/minDist;
-//
-//    aspectRatio = min(aspectRatio, sqr(perimeter)/(16.0*fA));
-
-    if (magSqr(collapseAxis) < VSMALL)
-    {
-        WarningIn
-        (
-            "Foam::conformalVoronoiMesh::collapseFace"
-        )
-            << "No collapse axis found for face, not collapsing."
-            << endl;
-
-        // Output face and collapse axis for visualisation
-
-        Pout<< "# Aspect ratio = " << aspectRatio << nl
-//            << "# inertia = " << J << nl
-//            << "# determinant = " << detJ << nl
-//            << "# eigenvalues = " << eigenValues(J) << nl
-            << "# collapseAxis = " << collapseAxis << nl
-            << "# facePts = " << facePts << nl
-            << endl;
-
-        forAll(f, fPtI)
-        {
-            meshTools::writeOBJ(Pout, pts[f[fPtI]]);
-        }
-
-        Pout<< "f";
-
-        forAll(f, fPtI)
-        {
-            Pout << " " << fPtI + 1;
-        }
-
-        Pout<< endl;
-
-        return fcmNone;
-    }
-
-    // The signed distance along the collapse axis passing through the
-    // face centre that each vertex projects to.
-
-    Field<scalar> d(f.size());
-
-    forAll(f, fPtI)
-    {
-        const Foam::point& pt = pts[f[fPtI]];
-
-        d[fPtI] = (collapseAxis & (pt - fC));
-    }
-
-    // Sort the projected distances and the corresponding vertex
-    // indices along the collapse axis
-
-    labelList oldToNew;
-
-    sortedOrder(d, oldToNew);
-
-    oldToNew = invert(oldToNew.size(), oldToNew);
-
-    inplaceReorder(oldToNew, d);
-
-    inplaceReorder(oldToNew, facePts);
-
-    // Shift the points so that they are relative to the centre of the
-    // collapse line.
-
-    scalar dShift = -0.5*(d.first() + d.last());
-
-    d += dShift;
-
-    // Form two lists, one for each half of the set of points
-    // projected along the collapse axis.
-
-    // Middle value, index of first entry in the second half
-    label middle = -1;
-
-    forAll(d, dI)
-    {
-        if (d[dI] > 0)
-        {
-            middle = dI;
-
-            break;
-        }
-    }
-
-    // Negative half
-    SubList<scalar> dNeg(d, middle, 0);
-    SubList<label> facePtsNeg(facePts, middle, 0);
-
-    // Positive half
-    SubList<scalar> dPos(d, d.size() - middle, middle);
-    SubList<label> facePtsPos(facePts, d.size() - middle, middle);
-
-    // Defining how close to the midpoint (M) of the projected
-    // vertices line a projected vertex (X) can be before making this
-    // an invalid edge collapse
-    //
-    // X---X-g----------------M----X-----------g----X--X
-    //
-    // Only allow a collapse if all projected vertices are outwith
-    // guardFraction (g) of the distance form the face centre to the
-    // furthest vertex in the considered direction
-
-    if (dNeg.size() == 0 || dPos.size() == 0)
-    {
-        WarningIn
-        (
-            "Foam::conformalVoronoiMesh::collapseFace"
-        )
-            << "All points on one side of face centre, not collapsing."
-            << endl;
-    }
-
-    faceCollapseMode mode = fcmNone;
-
-    if
-    (
-        (fA < aspectRatio*sqr(targetFaceSize*collapseSizeLimitCoeff))
-     && (!limitToQuadsOrTris || f.size() <= 4)
-    )
-    {
-        scalar guardFraction = cvMeshControls().edgeCollapseGuardFraction();
-
-        if
-        (
-            allowEarlyCollapseToPoint
-         && (d.last() - d.first())
-          < targetFaceSize
-           *0.2*cvMeshControls().maxCollapseFaceToPointSideLengthCoeff()
-        )
-        {
-            mode = fcmPoint;
-        }
-        else if
-        (
-            (dNeg.last() < guardFraction*dNeg.first())
-         && (dPos.first() > guardFraction*dPos.last())
-        )
-        {
-            mode = fcmEdge;
-        }
-        else if
-        (
-            (d.last() - d.first())
-          < targetFaceSize
-           *cvMeshControls().maxCollapseFaceToPointSideLengthCoeff()
-        )
-        {
-            // If the face can't be collapsed to an edge, and it has a
-            // small enough span, collapse it to a point.
-
-            mode = fcmPoint;
-        }
-        else
-        {
-            // Alternatively, do not topologically collapse face here,
-            // but push all points onto a line, so that the face area
-            // is zero and then collapse to a string of edges later.
-            // The fcmDeferredMultiEdge collapse must be performed at
-            // the polyMesh stage as this type of collapse can't be
-            // performed and still maintain topological dual
-            // consistency with the Delaunay structure
-
-            mode = fcmDeferredMultiEdge;
-        }
-    }
-
-    switch (mode)
-    {
-        case fcmEdge:
-        {
-            // Negative half
-
-            label collapseToPtI = facePtsNeg.first();
-
-            Foam::point collapseToPt =
-                collapseAxis*(sum(dNeg)/dNeg.size() - dShift) + fC;
-
-//            DynamicList<label> faceBoundaryPts(f.size());
-
-            forAll(facePtsNeg, fPtI)
-            {
-                if (boundaryPts[facePtsNeg[fPtI]] == true)
-                {
-                    // If there is a point which is on the boundary,
-                    // use it as the point to collapse others to, will
-                    // use the first boundary point encountered if
-                    // there are multiple boundary points.
-
-                    collapseToPtI = facePtsNeg[fPtI];
-
-                    collapseToPt = pts[collapseToPtI];
-
-                    break;
-
-//                    faceBoundaryPts.append(facePtsNeg[fPtI]);
-                }
-            }
-
-//            if (!faceBoundaryPts.empty())
-//            {
-//                if (faceBoundaryPts.size() == 2)
-//                {
-//                    collapseToPtI = faceBoundaryPts[0];
-//
-//                    collapseToPt =
-//                        0.5
-//                       *(
-//                            pts[faceBoundaryPts[0]]
-//                          + pts[faceBoundaryPts[1]]
-//                        );
-//                }
-//                else if (faceBoundaryPts.size() < f.size())
-//                {
-//                    face bFace(faceBoundaryPts);
-//
-//                    collapseToPtI = faceBoundaryPts.first();
-//
-//                    collapseToPt = bFace.centre(pts);
-//                }
-//            }
-//
-//            faceBoundaryPts.clear();
-
-            // ...otherwise arbitrarily choosing the most distant
-            // point as the index to collapse to.
-
-            forAll(facePtsNeg, fPtI)
-            {
-                dualPtIndexMap.insert(facePtsNeg[fPtI], collapseToPtI);
-            }
-
-            pts[collapseToPtI] = collapseToPt;
-
-            // Positive half
-
-            collapseToPtI = facePtsPos.last();
-
-            collapseToPt = collapseAxis*(sum(dPos)/dPos.size() - dShift) + fC;
-
-            forAll(facePtsPos, fPtI)
-            {
-                if (boundaryPts[facePtsPos[fPtI]] == true)
-                {
-                    // If there is a point which is on the boundary,
-                    // use it as the point to collapse others to, will
-                    // use the first boundary point encountered if
-                    // there are multiple boundary points.
-
-                    collapseToPtI = facePtsPos[fPtI];
-
-                    collapseToPt = pts[collapseToPtI];
-
-                    break;
-
-//                    faceBoundaryPts.append(facePtsNeg[fPtI]);
-                }
-            }
-
-//            if (!faceBoundaryPts.empty())
-//            {
-//                if (faceBoundaryPts.size() == 2)
-//                {
-//                    collapseToPtI = faceBoundaryPts[0];
-//
-//                    collapseToPt =
-//                        0.5
-//                       *(
-//                            pts[faceBoundaryPts[0]]
-//                          + pts[faceBoundaryPts[1]]
-//                        );
-//                }
-//                else if (faceBoundaryPts.size() < f.size())
-//                {
-//                    face bFace(faceBoundaryPts);
-//
-//                    collapseToPtI = faceBoundaryPts.first();
-//
-//                    collapseToPt = bFace.centre(pts);
-//                }
-//            }
-
-            // ...otherwise arbitrarily choosing the most distant
-            // point as the index to collapse to.
-
-            forAll(facePtsPos, fPtI)
-            {
-                dualPtIndexMap.insert(facePtsPos[fPtI], collapseToPtI);
-            }
-
-            pts[collapseToPtI] = collapseToPt;
-
-            break;
-        }
-
-        case fcmPoint:
-        {
-            label collapseToPtI = facePts.first();
-
-            Foam::point collapseToPt = fC;
-
-            DynamicList<label> faceBoundaryPts(f.size());
-
-            forAll(facePts, fPtI)
-            {
-                if (boundaryPts[facePts[fPtI]] == true)
-                {
-                    // If there is a point which is on the boundary,
-                    // use it as the point to collapse others to, will
-                    // use the first boundary point encountered if
-                    // there are multiple boundary points.
-
-//                    collapseToPtI = facePts[fPtI];
-//
-//                    collapseToPt = pts[collapseToPtI];
-//
-//                    break;
-
-                    faceBoundaryPts.append(facePts[fPtI]);
-                }
-            }
-
-            if (!faceBoundaryPts.empty())
-            {
-                if (faceBoundaryPts.size() == 2)
-                {
-                    collapseToPtI = faceBoundaryPts[0];
-
-                    collapseToPt =
-                        0.5*(pts[faceBoundaryPts[0]] + pts[faceBoundaryPts[1]]);
-                }
-                else if (faceBoundaryPts.size() < f.size())
-                {
-                    face bFace(faceBoundaryPts);
-
-                    collapseToPtI = faceBoundaryPts.first();
-
-                    collapseToPt = bFace.centre(pts);
-                }
-            }
-
-            // ...otherwise arbitrarily choosing the first point as
-            // the index to collapse to.  Collapse to the face centre.
-
-            forAll(facePts, fPtI)
-            {
-                dualPtIndexMap.insert(facePts[fPtI], collapseToPtI);
-            }
-
-            pts[collapseToPtI] = collapseToPt;
-
-            break;
-        }
-
-        case fcmDeferredMultiEdge:
-        {
-            // forAll(facePts, fPtI)
-            // {
-            //     label ptI = facePts[fPtI];
-
-            //     pts[ptI] = collapseAxis*(d[fPtI] - dShift) + fC;
-
-            //     dualPtIndexMap.insert(ptI, ptI);
-            // }
-
-            break;
-        }
-
-        case fcmNone:
-        {
-            break;
-        }
-    }
-
-    // if (mode == fcmDeferredMultiEdge)
-    // if (mode != fcmNone)
-    // {
-    //     // Output face and collapse axis for visualisation
-
-    //     Pout<< "# Aspect ratio = " << aspectRatio << nl
-    //         << "# determinant = " << detJ << nl
-    //         << "# collapseAxis = " << collapseAxis << nl
-    //         << "# mode = " << mode << nl
-    //         << "# facePts = " << facePts << nl
-    //     //        << "# eigenvalues = " << eVals
-    //         << endl;
-
-    //     scalar scale = 2.0*mag(fC - pts[f[0]]);
-
-    //     meshTools::writeOBJ(Pout, fC);
-    //     meshTools::writeOBJ(Pout, fC + scale*collapseAxis);
-
-    //     Pout<< "f 1 2" << endl;
-
-    //     forAll(f, fPtI)
-    //     {
-    //         meshTools::writeOBJ(Pout, pts[f[fPtI]]);
-    //     }
-
-    //     Pout<< "f";
-
-    //     forAll(f, fPtI)
-    //     {
-    //         Pout << " " << fPtI + 3;
-    //     }
-
-    //     Pout<< nl << "# " << d << endl;
-
-    //     Pout<< "# " << d.first() << " " << d.last() << endl;
-
-    //     forAll(d, dI)
-    //     {
-    //         meshTools::writeOBJ(Pout, fC + (d[dI] - dShift)*collapseAxis);
-    //     }
-
-    //     Pout<< endl;
-    // }
-
-    return mode;
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::longestEdge
-(
-    const face& f,
-    const pointField& pts
-) const
-{
-    const edgeList& eds = f.edges();
-
-    label longestEdgeI = -1;
+                    dualPtIndexMap.insert(c1I, c2I);
+                    dualPtIndexMap.insert(c2I, c2I);
+                }
 
-    scalar longestEdgeLength = -SMALL;
+                nPtsMerged++;
+            }
+        }
+    }
 
-    forAll(eds, edI)
+    if (debug)
     {
-        scalar edgeLength = eds[edI].mag(pts);
-
-        if (edgeLength > longestEdgeLength)
-        {
-            longestEdgeI = edI;
-
-            longestEdgeLength = edgeLength;
-        }
+        Info<< "mergeIdenticalDualVertices:" << endl
+            << "    zero-length edges     : "
+            << returnReduce(nPtsMerged, sumOp<label>()) << endl
+            << endl;
     }
 
-    return longestEdgeI;
+    return nPtsMerged;
 }
 
 
+//void Foam::conformalVoronoiMesh::smoothSurface
+//(
+//    pointField& pts,
+//    const labelList& boundaryPts
+//)
+//{
+//    label nCollapsedFaces = 0;
+//
+//    label iterI = 0;
+//
+//    do
+//    {
+//        Map<label> dualPtIndexMap;
+//
+//        nCollapsedFaces = smoothSurfaceDualFaces
+//        (
+//            pts,
+//            boundaryPts,
+//            dualPtIndexMap
+//        );
+//
+//        reduce(nCollapsedFaces, sumOp<label>());
+//
+//        reindexDualVertices(dualPtIndexMap);
+//
+//        mergeIdenticalDualVertices(pts, boundaryPts);
+//
+//        if (nCollapsedFaces > 0)
+//        {
+//            Info<< "    Collapsed " << nCollapsedFaces << " boundary faces"
+//                << endl;
+//        }
+//
+//        if (++iterI > cvMeshControls().maxCollapseIterations())
+//        {
+//            Info<< "    maxCollapseIterations reached, stopping collapse"
+//                << endl;
+//
+//            break;
+//        }
+//
+//    } while (nCollapsedFaces > 0);
+//
+//    // Force all points of boundary faces to be on the surface
+////    for
+////    (
+////        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
+////        cit != finite_cells_end();
+////        ++cit
+////    )
+////    {
+////        label ptI = cit->cellIndex();
+////
+////        label fC = cit->filterCount();
+////
+////        if (fC > cvMeshControls().filterCountSkipThreshold())
+////        {
+////            // This vertex has been limited too many times, skip
+////            continue;
+////        }
+////
+////        // Only cells with indices > -1 are valid
+////        if (ptI > -1)
+////        {
+////            if (boundaryPts[ptI] != -1)
+////            {
+////                Foam::point& pt = pts[ptI];
+////
+////                pointIndexHit surfHit;
+////                label hitSurface;
+////
+////                geometryToConformTo_.findSurfaceNearest
+////                (
+////                    pt,
+////                    sqr(GREAT),
+////                    surfHit,
+////                    hitSurface
+////                );
+////
+////                if (surfHit.hit())
+////                {
+////                    pt +=
+////                        (surfHit.hitPoint() - pt)
+////                       *pow(cvMeshControls().filterErrorReductionCoeff(), fC);
+////                }
+////            }
+////        }
+////    }
+////
+////    mergeCloseDualVertices(pts, boundaryPts);
+//}
+//
+//
+//Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
+//(
+//    pointField& pts,
+//    const labelList& boundaryPts,
+//    Map<label>& dualPtIndexMap
+//) const
+//{
+//    label nCollapsedFaces = 0;
+//
+//    const scalar cosPerpendicularToleranceAngle = cos
+//    (
+//        degToRad(cvMeshControls().surfaceStepFaceAngle())
+//    );
+//
+//    for
+//    (
+//        Delaunay::Finite_edges_iterator eit = finite_edges_begin();
+//        eit != finite_edges_end();
+//        ++eit
+//    )
+//    {
+//        Cell_circulator ccStart = incident_cells(*eit);
+//        Cell_circulator cc = ccStart;
+//
+//        bool skipFace = false;
+//
+//        do
+//        {
+//            if (dualPtIndexMap.found(cc->cellIndex()))
+//            {
+//                // One of the points of this face has already been
+//                // collapsed this sweep, leave for next sweep
+//
+//                skipFace = true;
+//
+//                break;
+//            }
+//
+//        } while (++cc != ccStart);
+//
+//        if (skipFace)
+//        {
+//            continue;
+//        }
+//
+//        if (isBoundaryDualFace(eit))
+//        {
+//            face dualFace = buildDualFace(eit);
+//
+//            if (dualFace.size() < 3)
+//            {
+//                // This face has been collapsed already
+//                continue;
+//            }
+//
+//            label maxFC = maxFilterCount(eit);
+//
+//            if (maxFC > cvMeshControls().filterCountSkipThreshold())
+//            {
+//                // A vertex on this face has been limited too many
+//                // times, skip
+//                continue;
+//            }
+//
+//            Cell_handle c = eit->first;
+//            Vertex_handle vA = c->vertex(eit->second);
+//            Vertex_handle vB = c->vertex(eit->third);
+//
+//            if
+//            (
+//                vA->internalBoundaryPoint() && vA->surfacePoint()
+//             && vB->externalBoundaryPoint() && vB->surfacePoint()
+//            )
+//            {
+//                if (vA->index() == vB->index() - 1)
+//                {
+//                    continue;
+//                }
+//            }
+//            else if
+//            (
+//                vA->externalBoundaryPoint() && vA->surfacePoint()
+//             && vB->internalBoundaryPoint() && vB->surfacePoint()
+//            )
+//            {
+//                if (vA->index() == vB->index() + 1)
+//                {
+//                    continue;
+//                }
+//            }
+////            else if
+////            (
+////                vA->internalBoundaryPoint() && vA->featureEdgePoint()
+////             && vB->externalBoundaryPoint() && vB->featureEdgePoint()
+////            )
+////            {
+////                if (vA->index() == vB->index() - 1)
+////                {
+////                    continue;
+////                }
+////            }
+////            else if
+////            (
+////                vA->externalBoundaryPoint() && vA->featureEdgePoint()
+////             && vB->internalBoundaryPoint() && vB->featureEdgePoint()
+////            )
+////            {
+////                if (vA->index() == vB->index() + 1)
+////                {
+////                    continue;
+////                }
+////            }
+////            else if
+////            (
+////                vA->internalBoundaryPoint() && vA->featurePoint()
+////             && vB->externalBoundaryPoint() && vB->featurePoint()
+////            )
+////            {
+////                if (vA->index() == vB->index() - 1)
+////                {
+////                    continue;
+////                }
+////            }
+////            else if
+////            (
+////                vA->externalBoundaryPoint() && vA->featurePoint()
+////             && vB->internalBoundaryPoint() && vB->featurePoint()
+////            )
+////            {
+////                if (vA->index() == vB->index() + 1)
+////                {
+////                    continue;
+////                }
+////            }
+//
+//
+////            if ((faceNormal & surfaceNormal) < cosPerpendicularToleranceAngle)
+////            {
+//                scalar targetFaceSize = averageAnyCellSize(vA, vB);
+//
+//                // Selecting faces to collapse based on angle to
+//                // surface, so set collapseSizeLimitCoeff to GREAT to
+//                // allow collapse of all faces
+//
+//                faceCollapseMode mode = collapseFace
+//                (
+//                    dualFace,
+//                    pts,
+//                    boundaryPts,
+//                    dualPtIndexMap,
+//                    targetFaceSize,
+//                    GREAT,
+//                    maxFC
+//                );
+//
+//                if (mode == fcmPoint || mode == fcmEdge)
+//                {
+//                    nCollapsedFaces++;
+//                }
+////            }
+//        }
+//    }
+//
+//    return nCollapsedFaces;
+//}
+
+
 void Foam::conformalVoronoiMesh::deferredCollapseFaceSet
 (
     labelList& owner,
@@ -1871,6 +1180,7 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
     labelList procNeighbours;
     pointField cellCentres;
     labelListList patchToDelaunayVertex;
+    PackedBoolList boundaryFacesToRemove;
 
     timeCheck("Start of checkPolyMeshQuality");
 
@@ -1887,6 +1197,7 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
         patchStarts,
         procNeighbours,
         patchToDelaunayVertex,
+        boundaryFacesToRemove,
         false
     );
 
@@ -1926,7 +1237,6 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
        if (patchTypes[p] == processorPolyPatch::typeName)
        {
            // Do not create empty processor patches
-
            if (patchSizes[p] > 0)
            {
                patches[nValidPatches] = new processorPolyPatch
@@ -1937,7 +1247,8 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
                    nValidPatches,
                    pMesh.boundaryMesh(),
                    Pstream::myProcNo(),
-                   procNeighbours[p]
+                   procNeighbours[p],
+                   coupledPolyPatch::COINCIDENTFULLMATCH
                );
 
                nValidPatches++;
@@ -1991,13 +1302,13 @@ void Foam::conformalVoronoiMesh::checkCellSizing()
 
     timeCheck("Start of Cell Sizing");
 
-    PackedBoolList boundaryPts(number_of_cells(), false);
+    labelList boundaryPts(number_of_finite_cells(), -1);
     pointField ptsField;
 
     indexDualVertices(ptsField, boundaryPts);
 
     // Merge close dual vertices.
-    mergeCloseDualVertices(ptsField, boundaryPts);
+    mergeIdenticalDualVertices(ptsField, boundaryPts);
 
     autoPtr<polyMesh> meshPtr = createPolyMeshFromPoints(ptsField);
     const polyMesh& pMesh = meshPtr();
@@ -2092,10 +1403,10 @@ void Foam::conformalVoronoiMesh::checkCellSizing()
             }
         }
 
-        Info<< "    Automatically re-sizing " << cellsToResize.size()
+        Info<< "    DISABLED: Automatically re-sizing " << cellsToResize.size()
             << " cells that are attached to the bad faces: " << endl;
 
-        cellSizeControl_.setCellSizes(cellsToResize);
+        //cellSizeControl_.setCellSizes(cellsToResize);
     }
 
     timeCheck("End of Cell Sizing");
@@ -2181,8 +1492,6 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::checkPolyMeshQuality
 
     labelHashSet wrongFaces(pMesh.nFaces()/100);
 
-    Info << endl;
-
     DynamicList<label> checkFaces(pMesh.nFaces());
 
     const vectorField& fAreas = pMesh.faceAreas();
@@ -2197,7 +1506,7 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::checkPolyMeshQuality
         }
     }
 
-    Info<< "Excluding "
+    Info<< nl << "Excluding "
         << returnReduce(fAreas.size() - checkFaces.size(), sumOp<label>())
         << " faces from check, < " << faceAreaLimit << " area" << endl;
 
@@ -2371,18 +1680,16 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::checkPolyMeshQuality
 void Foam::conformalVoronoiMesh::indexDualVertices
 (
     pointField& pts,
-    PackedBoolList& boundaryPts
+    labelList& boundaryPts
 )
 {
     // Indexing Delaunay cells, which are the dual vertices
 
-    label dualVertI = 0;
-
-    pts.setSize(number_of_cells());
+    this->resetCellCount();
 
-    boundaryPts.setSize(number_of_cells(), false);
+    pts.setSize(number_of_finite_cells());
 
-    boundaryPts = false;
+    boundaryPts.setSize(number_of_finite_cells(), -1);
 
     for
     (
@@ -2391,19 +1698,83 @@ void Foam::conformalVoronoiMesh::indexDualVertices
         ++cit
     )
     {
-        if (cit->internalOrBoundaryDualVertex())
+//        if (tetrahedron(cit).volume() == 0)
+//        {
+//            Pout<< "ZERO VOLUME TET" << endl;
+//            Pout<< cit->info();
+//            Pout<< "Dual = " << cit->dual();
+//        }
+
+        if (!cit->hasFarPoint())
         {
-            cit->cellIndex() = dualVertI;
+            cit->cellIndex() = getNewCellIndex();
 
-            pts[dualVertI] = cit->dual();
+            // For nearly coplanar Delaunay cells that are present on different
+            // processors the result of the circumcentre calculation depends on
+            // the ordering of the vertices, so synchronise it across processors
 
-            if (cit->boundaryDualVertex())
+            if (Pstream::parRun() && cit->parallelDualVertex())
+            {
+                typedef CGAL::Exact_predicates_exact_constructions_kernel Exact;
+                typedef CGAL::Point_3<Exact> ExactPoint;
+
+                List<labelPair> cellVerticesPair(4);
+                List<ExactPoint> cellVertices(4);
+
+                for (label vI = 0; vI < 4; ++vI)
+                {
+                    cellVerticesPair[vI] = labelPair
+                    (
+                        cit->vertex(vI)->procIndex(),
+                        cit->vertex(vI)->index()
+                    );
+
+                    cellVertices[vI] = ExactPoint
+                    (
+                        cit->vertex(vI)->point().x(),
+                        cit->vertex(vI)->point().y(),
+                        cit->vertex(vI)->point().z()
+                    );
+                }
+
+                // Sort the vertices so that they will be in the same order on
+                // each processor
+                labelList oldToNew;
+                sortedOrder(cellVerticesPair, oldToNew);
+                oldToNew = invert(oldToNew.size(), oldToNew);
+                inplaceReorder(oldToNew, cellVertices);
+
+                ExactPoint synchronisedDual = CGAL::circumcenter
+                (
+                    cellVertices[0],
+                    cellVertices[1],
+                    cellVertices[2],
+                    cellVertices[3]
+                );
+
+                pts[cit->cellIndex()] = Foam::point
+                (
+                    CGAL::to_double(synchronisedDual.x()),
+                    CGAL::to_double(synchronisedDual.y()),
+                    CGAL::to_double(synchronisedDual.z())
+                );
+            }
+            else
             {
-                // This is a boundary dual vertex
-                boundaryPts[dualVertI] = true;
+                pts[cit->cellIndex()] = cit->dual();
             }
 
-            dualVertI++;
+            if (cit->boundaryDualVertex())
+            {
+                if (cit->featureEdgeDualVertex())
+                {
+                    boundaryPts[cit->cellIndex()] = 1;
+                }
+                else
+                {
+                    boundaryPts[cit->cellIndex()] = 0;
+                }
+            }
         }
         else
         {
@@ -2411,9 +1782,9 @@ void Foam::conformalVoronoiMesh::indexDualVertices
         }
     }
 
-    pts.setSize(dualVertI);
+    pts.setSize(this->cellCount());
 
-    boundaryPts.setSize(dualVertI);
+    boundaryPts.setSize(this->cellCount());
 }
 
 
@@ -2437,18 +1808,11 @@ void Foam::conformalVoronoiMesh::reindexDualVertices
 }
 
 
-void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
+Foam::label Foam::conformalVoronoiMesh::createPatchInfo
 (
-    faceList& faces,
-    labelList& owner,
-    labelList& neighbour,
-    wordList& patchTypes,
     wordList& patchNames,
-    labelList& patchSizes,
-    labelList& patchStarts,
-    labelList& procNeighbours,
-    labelListList& patchPointPairSlaves,
-    bool includeEmptyPatches
+    wordList& patchTypes,
+    labelList& procNeighbours
 ) const
 {
     patchNames = geometryToConformTo_.patchNames();
@@ -2467,7 +1831,13 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
 
     if (Pstream::parRun())
     {
-        boolList procUsed(Pstream::nProcs(), false);
+        List<boolList> procUsedList
+        (
+            Pstream::nProcs(),
+            boolList(Pstream::nProcs(), false)
+        );
+
+        boolList& procUsed = procUsedList[Pstream::myProcNo()];
 
         // Determine which processor patches are required
         for
@@ -2477,12 +1847,30 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
             vit++
         )
         {
+            // This test is not sufficient if one of the processors does
+            // not receive a referred vertex from another processor, but does
+            // send one to the other processor.
             if (vit->referred())
             {
                 procUsed[vit->procIndex()] = true;
             }
         }
 
+        // Because the previous test was insufficient, combine the lists.
+        Pstream::gatherList(procUsedList);
+        Pstream::scatterList(procUsedList);
+
+        forAll(procUsedList, procI)
+        {
+            if (procI != Pstream::myProcNo())
+            {
+                if (procUsedList[procI][Pstream::myProcNo()])
+                {
+                    procUsed[procI] = true;
+                }
+            }
+        }
+
         forAll(procUsed, pUI)
         {
             if (procUsed[pUI])
@@ -2493,9 +1881,9 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
 
         label nNonProcPatches = patchNames.size();
 
+        patchNames.setSize(nNonProcPatches + nProcPatches);
         patchTypes.setSize(nNonProcPatches + nProcPatches);
         procNeighbours.setSize(nNonProcPatches + nProcPatches, -1);
-        patchNames.setSize(nNonProcPatches + nProcPatches);
 
         label procAddI = 0;
 
@@ -2519,25 +1907,46 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
         }
     }
 
-    // Pout<< patchTypes << " " << patchNames << endl;
+    return defaultPatchIndex;
+}
 
-    label nPatches = patchNames.size();
 
-    List<DynamicList<face> > patchFaces(nPatches, DynamicList<face>(0));
+void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
+(
+    faceList& faces,
+    labelList& owner,
+    labelList& neighbour,
+    wordList& patchTypes,
+    wordList& patchNames,
+    labelList& patchSizes,
+    labelList& patchStarts,
+    labelList& procNeighbours,
+    labelListList& patchPointPairSlaves,
+    PackedBoolList& boundaryFacesToRemove,
+    bool includeEmptyPatches
+) const
+{
+    const label defaultPatchIndex = createPatchInfo
+    (
+        patchNames,
+        patchTypes,
+        procNeighbours
+    );
 
-    List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
+    const label nPatches = patchNames.size();
 
+    List<DynamicList<face> > patchFaces(nPatches, DynamicList<face>(0));
+    List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
     // Per patch face the index of the slave node of the point pair
     List<DynamicList<label> > patchPPSlaves(nPatches, DynamicList<label>(0));
 
+    List<DynamicList<bool> > indirectPatchFace(nPatches, DynamicList<bool>(0));
 
-    faces.setSize(number_of_edges());
+    faces.setSize(number_of_finite_edges());
+    owner.setSize(number_of_finite_edges());
+    neighbour.setSize(number_of_finite_edges());
 
-    owner.setSize(number_of_edges());
-
-    neighbour.setSize(number_of_edges());
-
-    List<Pair<DynamicList<label> > > procPatchSortingIndex(nPatches);
+    labelPairPairDynListList procPatchSortingIndex(nPatches);
 
     label dualFaceI = 0;
 
@@ -2554,8 +1963,8 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
 
         if
         (
-            vA->internalOrBoundaryPoint()
-         || vB->internalOrBoundaryPoint()
+            (vA->internalOrBoundaryPoint() && !vA->referred())
+         || (vB->internalOrBoundaryPoint() && !vB->referred())
         )
         {
             face newDualFace = buildDualFace(eit);
@@ -2574,44 +1983,56 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
                 {
                     // boundary face
 
-                    Foam::point ptA = topoint(vA->point());
-                    Foam::point ptB = topoint(vB->point());
+                    pointFromPoint ptA = topoint(vA->point());
+                    pointFromPoint ptB = topoint(vB->point());
 
                     label patchIndex = -1;
 
-                    if
-                    (
-                        vA->referredInternalOrBoundaryPoint()
-                     || vB->referredInternalOrBoundaryPoint()
-                    )
+                    if (isProcBoundaryEdge(eit))
                     {
                         // One (and only one) of the points is an internal
                         // point from another processor
 
                         label procIndex = max(vA->procIndex(), vB->procIndex());
 
-                        patchIndex = findIndex(procNeighbours, procIndex);
+                        patchIndex = max
+                        (
+                            findIndex(procNeighbours, vA->procIndex()),
+                            findIndex(procNeighbours, vB->procIndex())
+                        );
 
                         // The lower processor index is the owner of the
-                        // two for the purposed of sorting the patch faces.
+                        // two for the purpose of sorting the patch faces.
 
                         if (Pstream::myProcNo() < procIndex)
                         {
                             // Use this processor's vertex index as the master
                             // for sorting
 
-                           Pair<DynamicList<label> >& sortingIndex =
-                               procPatchSortingIndex[patchIndex];
+                            DynamicList<Pair<labelPair> >& sortingIndex =
+                                procPatchSortingIndex[patchIndex];
 
-                            if (vB->referredInternalOrBoundaryPoint())
+                            if (vB->internalOrBoundaryPoint() && vB->referred())
                             {
-                                sortingIndex.first().append(vA->index());
-                                sortingIndex.second().append(vB->index());
+                                sortingIndex.append
+                                (
+                                    Pair<labelPair>
+                                    (
+                                        labelPair(vA->index(), vA->procIndex()),
+                                        labelPair(vB->index(), vB->procIndex())
+                                    )
+                                );
                             }
                             else
                             {
-                                sortingIndex.first().append(vB->index());
-                                sortingIndex.second().append(vA->index());
+                                sortingIndex.append
+                                (
+                                    Pair<labelPair>
+                                    (
+                                        labelPair(vB->index(), vB->procIndex()),
+                                        labelPair(vA->index(), vA->procIndex())
+                                    )
+                                );
                             }
                         }
                         else
@@ -2619,30 +2040,42 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
                             // Use the other processor's vertex index as the
                             // master for sorting
 
-                            Pair<DynamicList<label> >& sortingIndex =
+                            DynamicList<Pair<labelPair> >& sortingIndex =
                                 procPatchSortingIndex[patchIndex];
 
-                            if (vA->referredInternalOrBoundaryPoint())
+                            if (vA->internalOrBoundaryPoint() && vA->referred())
                             {
-                                sortingIndex.first().append(vA->index());
-                                sortingIndex.second().append(vB->index());
+                                sortingIndex.append
+                                (
+                                    Pair<labelPair>
+                                    (
+                                        labelPair(vA->index(), vA->procIndex()),
+                                        labelPair(vB->index(), vB->procIndex())
+                                    )
+                                );
                             }
                             else
                             {
-                                sortingIndex.first().append(vB->index());
-                                sortingIndex.second().append(vA->index());
+                                sortingIndex.append
+                                (
+                                    Pair<labelPair>
+                                    (
+                                        labelPair(vB->index(), vB->procIndex()),
+                                        labelPair(vA->index(), vA->procIndex())
+                                    )
+                                );
                             }
                         }
 
-                        // Pout<< ptA << " " << ptB
-                        //     << " proc indices "
-                        //     << vA->procIndex() << " " << vB->procIndex()
-                        //     << " indices " << vA->index()
-                        //     << " " << vB->index()
-                        //     << " my proc " << Pstream::myProcNo()
-                        //     << " addedIndex "
-                        //     << procPatchSortingIndex[patchIndex].last()
-                        //     << endl;
+//                        Pout<< ptA << " " << ptB
+//                            << " proc indices "
+//                            << vA->procIndex() << " " << vB->procIndex()
+//                            << " indices " << vA->index()
+//                            << " " << vB->index()
+//                            << " my proc " << Pstream::myProcNo()
+//                            << " addedIndex "
+//                            << procPatchSortingIndex[patchIndex].last()
+//                            << endl;
                     }
                     else
                     {
@@ -2667,6 +2100,17 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
                     patchFaces[patchIndex].append(newDualFace);
                     patchOwners[patchIndex].append(own);
 
+                    // If the two vertices are a pair, then the patch face is
+                    // a desired one.
+                    if (vA->type() == vB->index())
+                    {
+                        indirectPatchFace[patchIndex].append(true);
+                    }
+                    else
+                    {
+                        indirectPatchFace[patchIndex].append(false);
+                    }
+
                     // Store the non-internal or boundary point
                     if (vA->internalOrBoundaryPoint())
                     {
@@ -2680,7 +2124,6 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
                 else
                 {
                     // internal face
-
                     faces[dualFaceI] = newDualFace;
                     owner[dualFaceI] = own;
                     neighbour[dualFaceI] = nei;
@@ -2727,8 +2170,10 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
         owner,
         patchSizes,
         patchStarts,
+        boundaryFacesToRemove,
         patchFaces,
-        patchOwners
+        patchOwners,
+        indirectPatchFace
     );
 
     // Return     patchPointPairSlaves.setSize(nPatches);
@@ -2738,14 +2183,28 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
         patchPointPairSlaves[patchI].transfer(patchPPSlaves[patchI]);
     }
 
-    if (cvMeshControls().objOutput())
+//    if (cvMeshControls().objOutput())
     {
+        Info<< "Writing processor interfaces" << endl;
+
         forAll(procNeighbours, nbI)
         {
             if (patchFaces[nbI].size() > 0)
             {
                 const label neighbour = procNeighbours[nbI];
 
+                faceList procPatchFaces = patchFaces[nbI];
+
+                // Reverse faces as it makes it easier to analyse the output
+                // using a diff
+                if (neighbour < Pstream::myProcNo())
+                {
+                    forAll(procPatchFaces, fI)
+                    {
+                        procPatchFaces[fI] = procPatchFaces[fI].reverseFace();
+                    }
+                }
+
                 if (neighbour != -1)
                 {
                     word fName =
@@ -2755,11 +2214,7 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
                       + name(neighbour)
                       + "_interface.obj";
 
-                    writeProcessorInterface
-                    (
-                        fName,
-                        patchFaces[nbI]
-                    );
+                    writeProcessorInterface(fName, procPatchFaces);
                 }
             }
         }
@@ -2785,9 +2240,7 @@ void Foam::conformalVoronoiMesh::createCellCentres
     {
         if (vit->internalOrBoundaryPoint())
         {
-            cellCentres[vit->index()] = topoint(vit->point());
-
-            vertI++;
+            cellCentres[vertI++] = topoint(vit->point());
         }
     }
 
@@ -2800,6 +2253,8 @@ Foam::tmp<Foam::pointField> Foam::conformalVoronoiMesh::allPoints() const
     tmp<pointField> tpts(new pointField(number_of_vertices(), point::max));
     pointField& pts = tpts();
 
+    label nVert = 0;
+
     for
     (
         Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
@@ -2809,7 +2264,7 @@ Foam::tmp<Foam::pointField> Foam::conformalVoronoiMesh::allPoints() const
     {
         if (vit->internalOrBoundaryPoint())
         {
-            pts[vit->index()] = topoint(vit->point());
+            pts[nVert++] = topoint(vit->point());
         }
     }
 
@@ -2838,8 +2293,12 @@ void Foam::conformalVoronoiMesh::sortFaces
     // 1     | 24
     // 1     | 91
 
-    // Two stage sort:
-    // 1) sort by owner
+    List<labelPair> ownerNeighbourPair(owner.size());
+
+    forAll(ownerNeighbourPair, oNI)
+    {
+        ownerNeighbourPair[oNI] = labelPair(owner[oNI], neighbour[oNI]);
+    }
 
     Info<< nl
         << "Sorting faces, owner and neighbour into upper triangular order"
@@ -2847,71 +2306,13 @@ void Foam::conformalVoronoiMesh::sortFaces
 
     labelList oldToNew;
 
-    sortedOrder(owner, oldToNew);
+    sortedOrder(ownerNeighbourPair, oldToNew);
 
     oldToNew = invert(oldToNew.size(), oldToNew);
 
     inplaceReorder(oldToNew, faces);
     inplaceReorder(oldToNew, owner);
     inplaceReorder(oldToNew, neighbour);
-
-    // 2) in each block of owners sort by neighbour
-
-    // Reset map.  Elements that are not sorted will retain their -1
-    // value, which will mean that they are ignored by inplaceReorder
-
-    oldToNew = -1;
-
-    label blockStart = 0;
-
-    for (label i = 1; i < owner.size(); i++)
-    {
-        label blockLength = -1;
-
-        if (owner[i] > owner[i - 1])
-        {
-            blockLength = i - blockStart;
-        }
-        else if (i == owner.size() - 1)
-        {
-            // If the last element is not a jump in owner, then it
-            // needs to trigger a sort of the last block, but with a
-            // block length that is one element longer so that it
-            // sorts itself.
-
-            // If it is a jump in owner, then it will form a block of
-            // length one, and so will not need sorted.
-
-            blockLength = i - blockStart + 1;
-        }
-
-        if (blockLength >= 1)
-        {
-            labelList blockIndices = identity(blockLength) + blockStart;
-
-            SubList<label> neighbourBlock
-            (
-                neighbour,
-                blockLength,
-                blockStart
-            );
-
-            sortedOrder(neighbourBlock, blockIndices);
-
-            blockIndices = invert(blockIndices.size(), blockIndices);
-
-            forAll(blockIndices, b)
-            {
-                oldToNew[blockStart + b] = blockIndices[b] + blockStart;
-            }
-
-            blockStart = i;
-        }
-    }
-
-    // owner does not need re-sorted
-    inplaceReorder(oldToNew, faces);
-    inplaceReorder(oldToNew, neighbour);
 }
 
 
@@ -2920,7 +2321,7 @@ void Foam::conformalVoronoiMesh::sortProcPatches
     List<DynamicList<face> >& patchFaces,
     List<DynamicList<label> >& patchOwners,
     List<DynamicList<label> >& patchPointPairSlaves,
-    List<Pair<DynamicList<label> > >& patchSortingIndices
+    labelPairPairDynListList& patchSortingIndices
 ) const
 {
     if (!Pstream::parRun())
@@ -2934,18 +2335,16 @@ void Foam::conformalVoronoiMesh::sortProcPatches
         labelList& owner = patchOwners[patchI];
         DynamicList<label>& slaves = patchPointPairSlaves[patchI];
 
-        Pair<DynamicList<label> >& sortingIndices = patchSortingIndices[patchI];
-
-        List<label>& primary = sortingIndices.first();
-        List<label>& secondary = sortingIndices.second();
+        DynamicList<Pair<labelPair> >& sortingIndices
+            = patchSortingIndices[patchI];
 
-        if (!primary.empty())
+        if (!sortingIndices.empty())
         {
             if
             (
-                faces.size() != primary.size()
-             || owner.size() != primary.size()
-             || slaves.size() != primary.size()
+                faces.size() != sortingIndices.size()
+             || owner.size() != sortingIndices.size()
+             || slaves.size() != sortingIndices.size()
             )
             {
                 FatalErrorIn
@@ -2962,80 +2361,18 @@ void Foam::conformalVoronoiMesh::sortProcPatches
                     << " faces.size() " << faces.size() << nl
                     << " owner.size() " << owner.size() << nl
                     << " slaves.size() " << slaves.size() << nl
-                    << " sortingIndices.first().size() "
-                    << sortingIndices.first().size()
+                    << " sortingIndices.size() "
+                    << sortingIndices.size()
                     << exit(FatalError) << endl;
             }
 
-            // Two stage sort:
-            // 1) sort by primary
-
             labelList oldToNew;
 
-            sortedOrder(primary, oldToNew);
+            sortedOrder(sortingIndices, oldToNew);
 
             oldToNew = invert(oldToNew.size(), oldToNew);
 
-            inplaceReorder(oldToNew, primary);
-            inplaceReorder(oldToNew, secondary);
-            inplaceReorder(oldToNew, faces);
-            inplaceReorder(oldToNew, owner);
-            inplaceReorder(oldToNew, slaves);
-
-            // 2) in each block of primary sort by secondary
-
-            // Reset map.  Elements that are not sorted will retain their -1
-            // value, which will mean that they are ignored by inplaceReorder
-
-            oldToNew = -1;
-
-            label blockStart = 0;
-
-            for (label i = 1; i < primary.size(); i++)
-            {
-                label blockLength = -1;
-
-                if (primary[i] > primary[i - 1])
-                {
-                    blockLength = i - blockStart;
-                }
-                else if (i == primary.size() - 1)
-                {
-                    // If the last element is not a jump in index, then it
-                    // needs to trigger a sort of the last block, but with a
-                    // block length that is one element longer so that it
-                    // sorts itself.
-
-                    // If it is a jump in index, then it will form a block of
-                    // length one, and so will not need sorted.
-
-                    blockLength = i - blockStart + 1;
-                }
-
-                if (blockLength >= 1)
-                {
-                    labelList blockIndices = identity(blockLength) + blockStart;
-
-                    SubList<label> secondaryBlock
-                    (
-                        secondary,
-                        blockLength,
-                        blockStart
-                    );
-
-                    sortedOrder(secondaryBlock, blockIndices);
-
-                    blockIndices = invert(blockIndices.size(), blockIndices);
-
-                    forAll(blockIndices, b)
-                    {
-                        oldToNew[blockStart + b] = blockIndices[b] + blockStart;
-                    }
-
-                    blockStart = i;
-                }
-            }
-
+            inplaceReorder(oldToNew, sortingIndices);
             inplaceReorder(oldToNew, faces);
             inplaceReorder(oldToNew, owner);
             inplaceReorder(oldToNew, slaves);
@@ -3051,8 +2388,10 @@ void Foam::conformalVoronoiMesh::addPatches
     labelList& owner,
     labelList& patchSizes,
     labelList& patchStarts,
+    PackedBoolList& boundaryFacesToRemove,
     const List<DynamicList<face> >& patchFaces,
-    const List<DynamicList<label> >& patchOwners
+    const List<DynamicList<label> >& patchOwners,
+    const List<DynamicList<bool> >& indirectPatchFace
 ) const
 {
     label nPatches = patchFaces.size();
@@ -3081,6 +2420,7 @@ void Foam::conformalVoronoiMesh::addPatches
         {
             faces[faceI] = patchFaces[p][f];
             owner[faceI] = patchOwners[p][f];
+            boundaryFacesToRemove[faceI] = indirectPatchFace[p][f];
 
             faceI++;
         }
@@ -3091,7 +2431,8 @@ void Foam::conformalVoronoiMesh::addPatches
 void Foam::conformalVoronoiMesh::removeUnusedPoints
 (
     faceList& faces,
-    pointField& pts
+    pointField& pts,
+    labelList& boundaryPts
 ) const
 {
     Info<< nl << "Removing unused points" << endl;
@@ -3126,6 +2467,7 @@ void Foam::conformalVoronoiMesh::removeUnusedPoints
     }
 
     inplaceReorder(oldToNew, pts);
+    inplaceReorder(oldToNew, boundaryPts);
 
     Info<< "    Removing "
         << returnReduce(pts.size() - pointI, sumOp<label>())
@@ -3133,6 +2475,7 @@ void Foam::conformalVoronoiMesh::removeUnusedPoints
         << endl;
 
     pts.setSize(pointI);
+    boundaryPts.setSize(pointI);
 
     // Renumber the faces to use the new point numbers
 
@@ -3198,8 +2541,9 @@ Foam::labelList Foam::conformalVoronoiMesh::removeUnusedCells
 
     if (unusedCells.size() > 0)
     {
-        // Pout<< "Removing " << unusedCells.size() <<  " unused cell labels"
-        //     << endl;
+        Info<< "    Removing "
+            << returnReduce(unusedCells.size(), sumOp<label>())
+            <<  " unused cell labels" << endl;
 
         forAll(owner, oI)
         {
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C
index 2d850aff09fbde354f69a752082cd99b3d3815e0..14c5428c816f2941e2889eb16fe92f8b128a1978 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C
@@ -26,6 +26,8 @@ License
 #include "conformalVoronoiMesh.H"
 #include "backgroundMeshDecomposition.H"
 #include "vectorTools.H"
+#include "indexedCellChecks.H"
+#include "IOmanip.H"
 
 using namespace Foam::vectorTools;
 
@@ -35,34 +37,44 @@ const Foam::scalar Foam::conformalVoronoiMesh::searchConeAngle
 const Foam::scalar Foam::conformalVoronoiMesh::searchAngleOppositeSurface
     = Foam::cos(degToRad(150));
 
+
 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
 
 void Foam::conformalVoronoiMesh::conformToSurface()
 {
-    reconformationMode reconfMode = reconformationControl();
-
-//    if (Pstream::parRun())
-//    {
-//        seedProcessorBoundarySurfaces(true);
-//    }
+    this->resetCellCount();
+    // Index the cells
+    for
+    (
+        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
+        cit != finite_cells_end();
+        ++cit
+    )
+    {
+        cit->cellIndex() = Cb::ctUnassigned;
+    }
 
-    if (reconfMode == rmNone)
+    if (reconformationControl() == rmOff)
     {
         // Reinsert stored surface conformation
         reinsertSurfaceConformation();
 
-        buildParallelInterface("move_" + runTime_.timeName());
+        if (Pstream::parRun())
+        {
+            sync(decomposition_().procBounds());
+        }
     }
     else
     {
         // Rebuild, insert and store new surface conformation
-        buildSurfaceConformation(reconfMode);
+        buildSurfaceConformation();
 
         if (distributeBackground())
         {
-            // distributeBackground has destroyed all referred vertices, so the
-            // parallel interface needs to be rebuilt.
-            buildParallelInterface("rebuild");
+            if (Pstream::parRun())
+            {
+                sync(decomposition_().procBounds());
+            }
 
             // Use storeSizesAndAlignments with no feed points because all
             // background points may have been distributed.
@@ -74,16 +86,6 @@ void Foam::conformalVoronoiMesh::conformToSurface()
         storeSurfaceConformation();
     }
 
-//    if (Pstream::parRun())
-//    {
-//        label nFarPoints = removeProcessorBoundarySeeds(true);
-//
-//        reduce(nFarPoints, sumOp<label>());
-//
-//        Info<< "    Removed " << nFarPoints
-//            << " far points from the mesh." << endl;
-//    }
-
     // reportSurfaceConformationQuality();
 }
 
@@ -91,47 +93,143 @@ void Foam::conformalVoronoiMesh::conformToSurface()
 Foam::conformalVoronoiMesh::reconformationMode
 Foam::conformalVoronoiMesh::reconformationControl() const
 {
-    if (!runTime_.run())
-    {
-        Info<< nl << "Rebuilding surface conformation for final output"
-            << endl;
-
-        return rmFine;
-    }
-    else if
+    if
     (
         runTime_.timeIndex()
       % cvMeshControls().surfaceConformationRebuildFrequency() == 0
     )
     {
-        Info<< nl << "Rebuilding surface conformation for more iterations"
-            << endl;
-
-        return rmCoarse;
+        return rmOn;
     }
 
-    return rmNone;
+    return rmOff;
 }
 
 
-void Foam::conformalVoronoiMesh::buildSurfaceConformation
-(
-    reconformationMode reconfMode
-)
+// @todo Investigate topological tests
+Foam::label Foam::conformalVoronoiMesh::findVerticesNearBoundaries()
 {
-    timeCheck("Start buildSurfaceConformation");
+    label countNearBoundaryVertices = 0;
 
-    if (reconfMode == rmCoarse)
+    for
+    (
+        Delaunay::Finite_facets_iterator fit = finite_facets_begin();
+        fit != finite_facets_end();
+        ++fit
+    )
     {
-        Info<< nl << "Build coarse surface conformation" << endl;
+        if
+        (
+            is_infinite(fit->first)
+         || is_infinite(fit->first->neighbor(fit->second))
+        )
+        {
+            continue;
+        }
+
+        Cell_handle c1 = fit->first;
+        Cell_handle c2 = fit->first->neighbor(fit->second);
+
+        pointFromPoint dE0 = c1->dual();
+        pointFromPoint dE1 = c2->dual();
+
+        if (!geometryToConformTo_.findSurfaceAnyIntersection(dE0, dE1))
+        {
+            continue;
+        }
+
+        for (label cellI = 0; cellI < 4; ++cellI)
+        {
+            Vertex_handle v = c1->vertex(cellI);
+
+            if
+            (
+                !is_infinite(v)
+             && v->internalPoint()
+             && fit->second != cellI
+            )
+            {
+                v->setNearBoundary();
+            }
+        }
+
+        for (label cellI = 0; cellI < 4; ++cellI)
+        {
+            Vertex_handle v = c2->vertex(cellI);
+
+            if
+            (
+                !is_infinite(v)
+             && v->internalPoint()
+             && fit->second != cellI
+            )
+            {
+                v->setNearBoundary();
+            }
+        }
     }
-    else if (reconfMode == rmFine)
+
+    for
+    (
+        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
     {
-        Info<< nl << "Build fine surface conformation" << endl;
+        if (vit->nearBoundary())
+        {
+            countNearBoundaryVertices++;
+        }
     }
-    else if (reconfMode == rmNone)
+
+    // Geometric test.
+//    for
+//    (
+//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+//        vit != finite_vertices_end();
+//        ++vit
+//    )
+//    {
+//        if (vit->internalPoint() && !vit->nearBoundary())
+//        {
+//            pointFromPoint pt = topoint(vit->point());
+//
+//            const scalar range = sqr
+//            (
+//                cvMeshControls().nearBoundaryDistanceCoeff()
+//               *targetCellSize(pt)
+//            );
+//
+//            pointIndexHit pHit;
+//            label hitSurface;
+//
+//            geometryToConformTo_.findSurfaceNearest
+//            (
+//                pt,
+//                range,
+//                pHit,
+//                hitSurface
+//            );
+//
+//            if (pHit.hit())
+//            {
+//                vit->setNearBoundary();
+//                countNearBoundaryVertices++;
+//            }
+//        }
+//    }
+
+    return countNearBoundaryVertices;
+}
+
+
+void Foam::conformalVoronoiMesh::buildSurfaceConformation()
+{
+    timeCheck("Start buildSurfaceConformation");
+
+    if (reconformationControl() == rmOff)
     {
-        WarningIn("buildSurfaceConformation(reconformationMode reconfMode)")
+        WarningIn("buildSurfaceConformation()")
             << "reconformationMode rmNone specified, not building conformation"
             << endl;
 
@@ -139,21 +237,15 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
     }
     else
     {
-        WarningIn("buildSurfaceConformation(reconformationMode reconfMode)")
-            << "Unknown reconformationMode " << reconfMode
-            << " not building conformation" << endl;
-
-        return;
+        Info<< nl << "Rebuilding surface conformation for more iterations"
+            << endl;
     }
 
-    // Initialise containers to store the edge conformation locations
-    DynamicList<Foam::point> newEdgeLocations;
-
-    DynamicList<Foam::point> existingEdgeLocations;
-    DynamicList<Foam::point> existingSurfacePtLocations;
+    existingEdgeLocations_.clearStorage();
+    existingSurfacePtLocations_.clearStorage();
 
-    buildEdgeLocationTree(existingEdgeLocations);
-    buildSurfacePtLocationTree(existingSurfacePtLocations);
+    buildEdgeLocationTree(existingEdgeLocations_);
+    buildSurfacePtLocationTree(existingSurfacePtLocations_);
 
     label initialTotalHits = 0;
 
@@ -177,7 +269,7 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
     //     --------
     //
     // Shoot ray and find intersection with outside segment (x) and
-    // introduce pointpair (..)
+    // introduce point pair (..)
     //
     //        |
     // \      .      /
@@ -185,57 +277,27 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
     //   \    .    /
     //     ---x----
 
-    label countNearBoundaryVertices = 0;
-
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        vit++
-    )
-    {
-        if (vit->internalPoint() && !vit->nearBoundary())
-        {
-            pointFromPoint pt = topoint(vit->point());
-            const scalar range = sqr(2.0*targetCellSize(pt));
-
-            pointIndexHit pHit;
-            label hitSurface;
-
-            geometryToConformTo_.findSurfaceNearest
-            (
-                pt,
-                range,
-                pHit,
-                hitSurface
-            );
-
-            if (pHit.hit())
-            {
-                vit->setNearBoundary();
-                countNearBoundaryVertices++;
-            }
-        }
-    }
+    // Find vertices near boundaries to speed up subsequent checks.
+    label countNearBoundaryVertices = findVerticesNearBoundaries();
 
     Info<< "    Vertices marked as being near a boundary: "
-        << countNearBoundaryVertices << " (estimated)" << endl;
+        << returnReduce(countNearBoundaryVertices, sumOp<label>())
+        << " (estimated)" << endl;
 
     timeCheck("After set near boundary");
 
-    // Initial surface protrusion conformation - nearest surface point
-    {
-        const scalar edgeSearchDistCoeffSqr =
-            cvMeshControls().edgeSearchDistCoeffSqrInitial(reconfMode);
+    const scalar edgeSearchDistCoeffSqr =
+        cvMeshControls().edgeSearchDistCoeffSqr();
 
-        const scalar surfacePtReplaceDistCoeffSqr =
-            cvMeshControls().surfacePtReplaceDistCoeffSqrInitial(reconfMode);
+    const scalar surfacePtReplaceDistCoeffSqr =
+        cvMeshControls().surfacePtReplaceDistCoeffSqr();
 
-        DynamicList<pointIndexHit> surfaceHits;
-        DynamicList<label> hitSurfaces;
+    const label AtoV = label(6/Foam::pow(scalar(number_of_vertices()), 3));
 
-        DynamicList<pointIndexHit> featureEdgeHits;
-        DynamicList<label> featureEdgeFeaturesHit;
+    // Initial surface protrusion conformation - nearest surface point
+    {
+        pointIndexHitAndFeatureDynList featureEdgeHits(AtoV/4);
+        pointIndexHitAndFeatureDynList surfaceHits(AtoV);
 
         for
         (
@@ -244,25 +306,16 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
             vit++
         )
         {
-            if (vit->internalPoint() && vit->nearBoundary())
+            if (vit->nearBoundary())
             {
-                const Foam::point vert = topoint(vit->point());
-
-                if (!positionOnThisProc(vert))
-                {
-                    continue;
-                }
-
-                DynamicList<pointIndexHit> surfHitList;
-                DynamicList<label> hitSurfaceList;
+                pointIndexHitAndFeatureDynList surfaceIntersections(AtoV);
 
                 if
                 (
                     dualCellSurfaceAllIntersections
                     (
                         vit,
-                        surfHitList,
-                        hitSurfaceList
+                        surfaceIntersections
                     )
                 )
                 {
@@ -273,18 +326,11 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
                     addSurfaceAndEdgeHits
                     (
                         vit,
-                        vert,
-                        surfHitList,
-                        hitSurfaceList,
+                        surfaceIntersections,
                         surfacePtReplaceDistCoeffSqr,
                         edgeSearchDistCoeffSqr,
                         surfaceHits,
-                        hitSurfaces,
-                        featureEdgeHits,
-                        featureEdgeFeaturesHit,
-                        newEdgeLocations,
-                        existingEdgeLocations,
-                        existingSurfacePtLocations
+                        featureEdgeHits
                     );
                 }
                 else
@@ -296,7 +342,7 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
         }
 
         Info<< "    Vertices marked as being near a boundary: "
-            << countNearBoundaryVertices
+            << returnReduce(countNearBoundaryVertices, sumOp<label>())
             << " (after dual surface intersection)" << endl;
 
         label nVerts = number_of_vertices();
@@ -316,17 +362,27 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
             << "    Number of edge hits " << nFeatEdHits
             << endl;
 
+        // In parallel, synchronise the surface trees
+        if (Pstream::parRun())
+        {
+            synchroniseSurfaceTrees(surfaceHits);
+        }
+
         insertSurfacePointPairs
         (
             surfaceHits,
-            hitSurfaces,
             "surfaceConformationLocations_initial.obj"
         );
 
+        // In parallel, synchronise the edge trees
+        if (Pstream::parRun())
+        {
+            synchroniseEdgeTrees(featureEdgeHits);
+        }
+
         insertEdgePointGroups
         (
             featureEdgeHits,
-            featureEdgeFeaturesHit,
             "edgeConformationLocations_initial.obj"
         );
 
@@ -337,32 +393,56 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
 
     // Remember which vertices were referred to each processor so only updates
     // are sent.
-    List<labelHashSet> referralVertices(Pstream::nProcs());
+    PtrList<labelPairHashSet> referralVertices(Pstream::nProcs());
 
     // Store the vertices that have been received and added from each processor
     // already so that there is no attempt to add them more than once.
-    List<labelHashSet> receivedVertices(Pstream::nProcs());
+    autoPtr<labelPairHashSet> receivedVertices;
+
+    if (Pstream::parRun())
+    {
+        forAll(referralVertices, procI)
+        {
+            if (procI != Pstream::myProcNo())
+            {
+                referralVertices.set
+                (
+                    procI,
+                    new labelPairHashSet(number_of_vertices()/Pstream::nProcs())
+                );
+            }
+        }
+
+        receivedVertices.set
+        (
+            new labelPairHashSet(number_of_vertices()/Pstream::nProcs())
+        );
 
-    // Build the parallel interface the initial surface conformation
-    buildParallelInterface(referralVertices, receivedVertices, true, "initial");
+        // Build the parallel interface the initial surface conformation
+        sync
+        (
+            decomposition_().procBounds(),
+            referralVertices,
+            receivedVertices()
+        );
+    }
 
     label iterationNo = 0;
 
-    label maxIterations =
-        cvMeshControls().maxConformationIterations(reconfMode);
+    label maxIterations = cvMeshControls().maxConformationIterations();
 
     scalar iterationToInitialHitRatioLimit =
-        cvMeshControls().iterationToInitialHitRatioLimit(reconfMode);
+        cvMeshControls().iterationToInitialHitRatioLimit();
 
     label hitLimit = label(iterationToInitialHitRatioLimit*initialTotalHits);
 
     Info<< nl << "Stopping iterations when: " << nl
-        <<"    total number of hits drops below "
-        << iterationToInitialHitRatioLimit << " of initial hits ("
-        << hitLimit << ")" << nl
+        << "    total number of hits drops below "
+        << iterationToInitialHitRatioLimit
+        << " of initial hits (" << hitLimit << ")" << nl
         << " or " << nl
-        << "    maximum number of iterations ("
-        << maxIterations << ") is reached"
+        << "    maximum number of iterations (" << maxIterations
+        << ") is reached"
         << endl;
 
     // Set totalHits to a large enough positive value to enter the while loop on
@@ -376,17 +456,8 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
      && iterationNo < maxIterations
     )
     {
-        scalar edgeSearchDistCoeffSqr =
-            cvMeshControls().edgeSearchDistCoeffSqrIteration(reconfMode);
-
-        scalar surfacePtReplaceDistCoeffSqr =
-            cvMeshControls().surfacePtReplaceDistCoeffSqrIteration(reconfMode);
-
-        DynamicList<pointIndexHit> surfaceHits;
-        DynamicList<label> hitSurfaces;
-
-        DynamicList<pointIndexHit> featureEdgeHits;
-        DynamicList<label> featureEdgeFeaturesHit;
+        pointIndexHitAndFeatureDynList surfaceHits(0.5*AtoV);
+        pointIndexHitAndFeatureDynList featureEdgeHits(0.25*AtoV);
 
         for
         (
@@ -402,11 +473,11 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
             if
             (
                 vit->nearBoundary()
-             || vit->ppMaster()
-             || vit->referredInternalOrBoundaryPoint()
+             || vit->internalBoundaryPoint()
+             || (vit->internalOrBoundaryPoint() && vit->referred())
             )
             {
-                const Foam::point vert = topoint(vit->point());
+                pointIndexHitAndFeatureDynList surfaceIntersections(0.5*AtoV);
 
                 pointIndexHit surfHit;
                 label hitSurface;
@@ -417,37 +488,34 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
 
                 if (surfHit.hit())
                 {
-                    DynamicList<pointIndexHit> tmpPIH;
-                    tmpPIH.append(surfHit);
-
-                    DynamicList<label> tmpHS;
-                    tmpHS.append(hitSurface);
+                    surfaceIntersections.append
+                    (
+                        pointIndexHitAndFeature(surfHit, hitSurface)
+                    );
 
                     addSurfaceAndEdgeHits
                     (
                         vit,
-                        vert,
-                        tmpPIH,
-                        tmpHS,
+                        surfaceIntersections,
                         surfacePtReplaceDistCoeffSqr,
                         edgeSearchDistCoeffSqr,
                         surfaceHits,
-                        hitSurfaces,
-                        featureEdgeHits,
-                        featureEdgeFeaturesHit,
-                        newEdgeLocations,
-                        existingEdgeLocations,
-                        existingSurfacePtLocations
+                        featureEdgeHits
                     );
                 }
-//                else
-//                {
-//                    vit->setInternal();
-//                }
+                else
+                {
+                    // No surface hit detected so if internal then don't check
+                    // again
+                    if (vit->nearBoundary())
+                    {
+                        vit->setInternal();
+                    }
+                }
             }
-            else if (vit->ppSlave() || vit->referredExternal())
+            else if (vit->externalBoundaryPoint())
             {
-                const Foam::point vert = topoint(vit->point());
+                pointIndexHitAndFeatureDynList surfaceIntersections(0.5*AtoV);
 
                 pointIndexHit surfHit;
                 label hitSurface;
@@ -458,33 +526,21 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
 
                 if (surfHit.hit())
                 {
-                    DynamicList<pointIndexHit> tmpPIH;
-                    tmpPIH.append(surfHit);
-
-                    DynamicList<label> tmpHS;
-                    tmpHS.append(hitSurface);
+                    surfaceIntersections.append
+                    (
+                        pointIndexHitAndFeature(surfHit, hitSurface)
+                    );
 
                     addSurfaceAndEdgeHits
                     (
                         vit,
-                        vert,
-                        tmpPIH,
-                        tmpHS,
+                        surfaceIntersections,
                         surfacePtReplaceDistCoeffSqr,
                         edgeSearchDistCoeffSqr,
                         surfaceHits,
-                        hitSurfaces,
-                        featureEdgeHits,
-                        featureEdgeFeaturesHit,
-                        newEdgeLocations,
-                        existingEdgeLocations,
-                        existingSurfacePtLocations
+                        featureEdgeHits
                     );
                 }
-//                else
-//                {
-//                    vit->setInternal();
-//                }
             }
         }
 
@@ -507,41 +563,47 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
 
         totalHits = nSurfHits + nFeatEdHits;
 
+        label nNotInserted = 0;
+
         if (totalHits > 0)
         {
+            // In parallel, synchronise the surface trees
+            if (Pstream::parRun())
+            {
+                nNotInserted += synchroniseSurfaceTrees(surfaceHits);
+            }
+
             insertSurfacePointPairs
             (
                 surfaceHits,
-                hitSurfaces,
-                fileName
-                (
-                    "surfaceConformationLocations_" + name(iterationNo) + ".obj"
-                )
+                "surfaceConformationLocations_" + name(iterationNo) + ".obj"
             );
 
+            // In parallel, synchronise the edge trees
+            if (Pstream::parRun())
+            {
+                nNotInserted += synchroniseEdgeTrees(featureEdgeHits);
+            }
+
             insertEdgePointGroups
             (
                 featureEdgeHits,
-                featureEdgeFeaturesHit,
                 "edgeConformationLocations_" + name(iterationNo) + ".obj"
             );
+
+            if (Pstream::parRun())
+            {
+                sync
+                (
+                    decomposition_().procBounds(),
+                    referralVertices,
+                    receivedVertices()
+                );
+            }
         }
 
         timeCheck("Conformation iteration " + name(iterationNo));
 
-        // Only need to update the interface if there are surface/edge hits
-        if (totalHits > 0)
-        {
-            // Update the parallel interface
-            buildParallelInterface
-            (
-                referralVertices,
-                receivedVertices,
-                false,
-                name(iterationNo)
-            );
-        }
-
         iterationNo++;
 
         if (iterationNo == maxIterations)
@@ -551,6 +613,14 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
                 << maxIterations <<  ") reached." << endl;
         }
 
+        if (totalHits <= nNotInserted)
+        {
+            Info<< nl << "Total hits (" << totalHits
+                << ") less than number of failed insertions (" << nNotInserted
+                << "), stopping iterations" << endl;
+            break;
+        }
+
         if (totalHits < hitLimit)
         {
             Info<< nl << "Total hits (" << totalHits
@@ -558,76 +628,286 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation
                 << "), stopping iterations" << endl;
         }
     }
+
+    edgeLocationTreePtr_.clear();
+    surfacePtLocationTreePtr_.clear();
 }
 
 
-bool Foam::conformalVoronoiMesh::dualCellSurfaceAnyIntersection
+Foam::label Foam::conformalVoronoiMesh::synchroniseSurfaceTrees
 (
-    const Delaunay::Finite_vertices_iterator& vit
-) const
+    pointIndexHitAndFeatureList& surfaceHits
+)
 {
-    std::list<Facet> facets;
-    incident_facets(vit, std::back_inserter(facets));
+    Info<< "    Surface tree synchronisation" << endl;
 
-    for
+    pointIndexHitAndFeatureDynList synchronisedSurfLocations
     (
-        std::list<Facet>::iterator fit=facets.begin();
-        fit != facets.end();
-        ++fit
-    )
+        surfaceHits.size()
+    );
+
+    List<pointIndexHitAndFeatureDynList> procSurfLocations(Pstream::nProcs());
+
+    procSurfLocations[Pstream::myProcNo()] = surfaceHits;
+
+    Pstream::gatherList(procSurfLocations);
+    Pstream::scatterList(procSurfLocations);
+
+    List<labelHashSet> hits(Pstream::nProcs());
+
+    label nStoppedInsertion = 0;
+
+    // Do the nearness tests here
+    for (label procI = 0; procI < Pstream::nProcs(); ++procI)
     {
-        if
-        (
-            is_infinite(fit->first)
-         || is_infinite(fit->first->neighbor(fit->second))
-        )
+        // Skip own points
+        if (procI >= Pstream::myProcNo())
         {
             continue;
         }
 
-        Foam::point dE0 = fit->first->dual();
-        Foam::point dE1 = fit->first->neighbor(fit->second)->dual();
+        const pointIndexHitAndFeatureList& otherSurfEdges =
+            procSurfLocations[procI];
 
-        if (Pstream::parRun())
+        forAll(otherSurfEdges, peI)
         {
-            Foam::point& a = dE0;
-            Foam::point& b = dE1;
+            const Foam::point& pt = otherSurfEdges[peI].first().hitPoint();
 
-            bool inProc = clipLineToProc(topoint(vit->point()), a, b);
+            pointIndexHit nearest;
+            pointIsNearSurfaceLocation(pt, nearest);
 
-            // Check for the edge passing through a surface
-            if
-            (
-                inProc
-             && geometryToConformTo_.findSurfaceAnyIntersection(a, b)
-            )
+            pointIndexHit nearestEdge;
+            pointIsNearFeatureEdgeLocation(pt, nearestEdge);
+
+            bool isNearFeaturePt = nearFeaturePt(pt);
+
+            if (nearest.hit() || nearestEdge.hit() || isNearFeaturePt)
             {
-                // Pout<< "# findSurfaceAnyIntersection" << endl;
-                // meshTools::writeOBJ(Pout, a);
-                // meshTools::writeOBJ(Pout, b);
-                // Pout<< "l cr0 cr1" << endl;
+                nStoppedInsertion++;
 
-                return true;
+                if (!hits[procI].found(peI))
+                {
+                    hits[procI].insert(peI);
+                }
             }
         }
-        else
+    }
+
+    Pstream::listCombineGather(hits, plusEqOp<labelHashSet>());
+    Pstream::listCombineScatter(hits);
+
+    forAll(surfaceHits, eI)
+    {
+        if (!hits[Pstream::myProcNo()].found(eI))
         {
-            if (geometryToConformTo_.findSurfaceAnyIntersection(dE0, dE1))
-            {
-                return true;
-            }
+            synchronisedSurfLocations.append(surfaceHits[eI]);
         }
     }
 
-    return false;
+    forAll(synchronisedSurfLocations, pI)
+    {
+        appendToSurfacePtTree
+        (
+            synchronisedSurfLocations[pI].first().hitPoint()
+        );
+    }
+
+    const label nNotInserted = returnReduce(nStoppedInsertion, sumOp<label>());
+
+    Info<< "        Not inserting total of " << nNotInserted << " locations"
+        << endl;
+
+    surfaceHits = synchronisedSurfLocations;
+
+    return nNotInserted;
+}
+
+
+Foam::label Foam::conformalVoronoiMesh::synchroniseEdgeTrees
+(
+    pointIndexHitAndFeatureList& featureEdgeHits
+)
+{
+    Info<< "    Edge tree synchronisation" << endl;
+
+    pointIndexHitAndFeatureDynList synchronisedEdgeLocations
+    (
+        featureEdgeHits.size()
+    );
+
+    List<pointIndexHitAndFeatureDynList> procEdgeLocations(Pstream::nProcs());
+
+    procEdgeLocations[Pstream::myProcNo()] = featureEdgeHits;
+
+    Pstream::gatherList(procEdgeLocations);
+    Pstream::scatterList(procEdgeLocations);
+
+    List<labelHashSet> hits(Pstream::nProcs());
+
+    label nStoppedInsertion = 0;
+
+    // Do the nearness tests here
+    for (label procI = 0; procI < Pstream::nProcs(); ++procI)
+    {
+        // Skip own points
+        if (procI >= Pstream::myProcNo())
+        {
+            continue;
+        }
+
+        pointIndexHitAndFeatureList& otherProcEdges = procEdgeLocations[procI];
+
+        forAll(otherProcEdges, peI)
+        {
+            const Foam::point& pt = otherProcEdges[peI].first().hitPoint();
+
+            pointIndexHit nearest;
+            pointIsNearFeatureEdgeLocation(pt, nearest);
+
+            bool isNearFeaturePt = nearFeaturePt(pt);
+
+            if (nearest.hit() || isNearFeaturePt)
+            {
+                nStoppedInsertion++;
+
+                if (!hits[procI].found(peI))
+                {
+                    hits[procI].insert(peI);
+                }
+            }
+        }
+    }
+
+    Pstream::listCombineGather(hits, plusEqOp<labelHashSet>());
+    Pstream::listCombineScatter(hits);
+
+    forAll(featureEdgeHits, eI)
+    {
+        if (!hits[Pstream::myProcNo()].found(eI))
+        {
+            synchronisedEdgeLocations.append(featureEdgeHits[eI]);
+        }
+    }
+
+    forAll(synchronisedEdgeLocations, pI)
+    {
+        appendToEdgeLocationTree
+        (
+            synchronisedEdgeLocations[pI].first().hitPoint()
+        );
+    }
+
+    const label nNotInserted = returnReduce(nStoppedInsertion, sumOp<label>());
+
+    Info<< "        Not inserting total of " << nNotInserted << " locations"
+        << endl;
+
+    featureEdgeHits = synchronisedEdgeLocations;
+
+    return nNotInserted;
+}
+
+
+bool Foam::conformalVoronoiMesh::locationConformsToInside
+(
+    const pointIndexHitAndFeature& info
+) const
+{
+    bool keepLocation = true;
+
+    if (info.first().hit())
+    {
+        vectorField norm(1);
+
+        allGeometry_[info.second()].getNormal
+        (
+            List<pointIndexHit>(1, info.first()),
+            norm
+        );
+
+        const vector& n = norm[0];
+
+        const scalar ppDist = pointPairDistance(info.first().hitPoint());
+
+        const Foam::point innerPoint = info.first().hitPoint() - ppDist*n;
+
+        if (!geometryToConformTo_.inside(innerPoint))
+        {
+            keepLocation = false;
+        }
+    }
+    else
+    {
+        keepLocation = false;
+    }
+
+    return keepLocation;
+}
+
+
+bool Foam::conformalVoronoiMesh::dualCellSurfaceAnyIntersection
+(
+    const Delaunay::Finite_vertices_iterator& vit
+) const
+{
+    std::list<Facet> facets;
+    incident_facets(vit, std::back_inserter(facets));
+
+    for
+    (
+        std::list<Facet>::iterator fit=facets.begin();
+        fit != facets.end();
+        ++fit
+    )
+    {
+        if
+        (
+            is_infinite(fit->first)
+         || is_infinite(fit->first->neighbor(fit->second))
+         || !fit->first->hasInternalPoint()
+         || !fit->first->neighbor(fit->second)->hasInternalPoint()
+        )
+        {
+            continue;
+        }
+
+        Foam::point dE0 = fit->first->dual();
+        Foam::point dE1 = fit->first->neighbor(fit->second)->dual();
+
+        if (Pstream::parRun())
+        {
+            Foam::point& a = dE0;
+            Foam::point& b = dE1;
+
+            bool inProc = clipLineToProc(topoint(vit->point()), a, b);
+
+            // Check for the edge passing through a surface
+            if
+            (
+                inProc
+             && geometryToConformTo_.findSurfaceAnyIntersection(a, b)
+            )
+            {
+                return true;
+            }
+        }
+        else
+        {
+            if (geometryToConformTo_.findSurfaceAnyIntersection(dE0, dE1))
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
 }
 
 
 bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
 (
     const Delaunay::Finite_vertices_iterator& vit,
-    DynamicList<pointIndexHit>& infoList,
-    DynamicList<label>& hitSurfaceList
+    pointIndexHitAndFeatureDynList& infoList
 ) const
 {
     bool flagIntersection = false;
@@ -646,6 +926,10 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
         (
             is_infinite(fit->first)
          || is_infinite(fit->first->neighbor(fit->second))
+         || !fit->first->hasInternalPoint()
+         || !fit->first->neighbor(fit->second)->hasInternalPoint()
+//         || fit->first->hasFarPoint()
+//         || fit->first->neighbor(fit->second)->hasFarPoint()
         )
         {
             continue;
@@ -689,7 +973,7 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
 
             const vector& n = norm[0];
 
-            const Foam::point vertex = topoint(vit->point());
+            pointFromPoint vertex = topoint(vit->point());
 
             const plane p(infoIntersection.hitPoint(), n);
 
@@ -699,36 +983,45 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
 
             const Foam::point newPoint = vertex + d*n;
 
-            pointIndexHit info;
-            label hitSurface = -1;
+            pointIndexHitAndFeature info;
 
             geometryToConformTo_.findSurfaceNearest
             (
                 newPoint,
                 surfaceSearchDistanceSqr(newPoint),
-                info,
-                hitSurface
+                info.first(),
+                info.second()
             );
 
             bool rejectPoint = false;
 
-            if (info.hit())
+            if (!locationConformsToInside(info))
+            {
+                rejectPoint = true;
+            }
+
+            if (!rejectPoint && info.first().hit())
             {
                 if (!infoList.empty())
                 {
                     forAll(infoList, hitI)
                     {
                         // Reject point if the point is already added
-                        if (infoList[hitI].index() == info.index())
+                        if
+                        (
+                            infoList[hitI].first().index()
+                         == info.first().index()
+                        )
                         {
                             rejectPoint = true;
                             break;
                         }
 
-                        const Foam::point& p = infoList[hitI].hitPoint();
+                        const Foam::point& p
+                            = infoList[hitI].first().hitPoint();
 
                         const scalar separationDistance =
-                            mag(p - info.hitPoint());
+                            mag(p - info.first().hitPoint());
 
                         const scalar minSepDist =
                             sqr
@@ -751,1059 +1044,59 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
 
             // The normal ray from the vertex will not always result in a hit
             // because another surface may be in the way.
-            if (!rejectPoint && info.hit())
+            if (!rejectPoint && info.first().hit())
             {
                 flagIntersection = true;
                 infoList.append(info);
-                hitSurfaceList.append(hitSurface);
             }
         }
     }
 
-    return flagIntersection;
-}
-
-
-bool Foam::conformalVoronoiMesh::clipLineToProc
-(
-    const Foam::point& pt,
-    Foam::point& a,
-    Foam::point& b
-) const
-{
-    bool inProc = false;
-
-    pointIndexHit findAnyIntersection = decomposition_().findLine(a, b);
-
-    if (!findAnyIntersection.hit())
-    {
-        pointIndexHit info = decomposition_().findLine(a, pt);
-
-        if (!info.hit())
-        {
-            inProc = true;
-        }
-        else
-        {
-            inProc = false;
-        }
-    }
-    else
-    {
-        pointIndexHit info = decomposition_().findLine(a, pt);
-
-        if (!info.hit())
-        {
-            inProc = true;
-            b = findAnyIntersection.hitPoint();
-        }
-        else
-        {
-            inProc = true;
-            a = findAnyIntersection.hitPoint();
-        }
-    }
-
-    return inProc;
-}
-
-
-void Foam::conformalVoronoiMesh::buildParallelInterface
-(
-    const word& outputName
-)
-{
-    List<labelHashSet> referralVertices(Pstream::nProcs());
-    List<labelHashSet> receivedVertices(Pstream::nProcs());
-
-    buildParallelInterface
-    (
-        referralVertices,
-        receivedVertices,
-        true,
-        outputName
-    );
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::removeProcessorBoundarySeeds
-(
-    bool reinsertBoundPts
-)
-{
-    label nFarPoints = 0;
-
-
-
-    std::list<Vertex_handle> toRemove;
-
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        ++vit
-    )
-    {
-        if (vit->farPoint())
-        {
-            //remove(vit);
-            toRemove.push_back(vit);
-            nFarPoints++;
-        }
-    }
-
-    // This function removes the points in the iterator range and then
-    // retriangulates.
-    timeCheck("Start Removing Seeded Points " + name(toRemove.size()));
-
-    remove_cluster(toRemove.begin(), toRemove.end());
-
-
-    // Need to do this to make sure the triangulation is well-behaved
-    if (reinsertBoundPts)
-    {
-        reinsertBoundingPoints();
-    }
-
-
-
-//    DynamicList<Foam::point> toAdd;
-//    DynamicList<label> indices;
-//    DynamicList<label> types;
-//
-//    for
-//    (
-//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-//        vit != finite_vertices_end();
-//        ++vit
-//    )
-//    {
-//        if (!vit->farPoint())
-//        {
-//            toAdd.append(topoint(vit->point()));
-//            indices.append(vit->index());
-//            types.append(vit->type());
-//
-//            nFarPoints++;
-//        }
-//    }
-//
-//    this->clear();
-//
-//    // Need to do this to make sure the triangulation is well-behaved
-//    if (reinsertBoundPts)
-//    {
-//        reinsertBoundingPoints();
-//    }
-//
-//    forAll(toAdd, pI)
-//    {
-//        insertPoint(toAdd[pI], indices[pI], types[pI]);
-//    }
-
-
-    timeCheck("End Removing Seeded Points");
-
-    return nFarPoints;
-}
-
-
-void Foam::conformalVoronoiMesh::seedProcessorBoundarySurfaces
-(
-    bool seedProcessors
-)
-{
-    //removeProcessorBoundarySeeds(false);
-
-    // Loop over processor patch faces and insert a point in the centre of the
-    // face
-    const fvMesh& mesh = decomposition_().mesh();
-    const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
-
-    DynamicList<Foam::point> pts;
-    DynamicList<label> indices;
-    DynamicList<label> types;
-
-    label nFarPoints = 0;
-
-    const scalar normalDistance = 2.0;
-    const scalar pert = 0.1*(rndGen_.scalar01() - 0.5);
-
-    forAll(bMesh, patchI)
-    {
-        const polyPatch& patch = bMesh[patchI];
-
-        if (!seedProcessors && isA<processorPolyPatch>(patch))
-        {
-            continue;
-        }
-
-        forAll(patch, faceI)
-        {
-            if (faceI % 1 == 0)
-            {
-                const face& f = patch[faceI];
-
-                pts.append
-                (
-                    f.centre(mesh.points())
-                  + pert*normalDistance*f.normal(mesh.points())
-                );
-                indices.append(nFarPoints++);
-                types.append(Vb::vtFar);
-            }
-        }
-    }
-
-    insertPoints(pts, indices, types, false);
-
-    reduce(nFarPoints, sumOp<label>());
-
-    Info<< "    Inserted " << nFarPoints
-        << " far points into the mesh." << endl;
-}
-
-
-void Foam::conformalVoronoiMesh::buildParallelInterface
-(
-    List<labelHashSet>& referralVertices,
-    List<labelHashSet>& receivedVertices,
-    bool initialEdgeReferral,
-    const word& outputName
-)
-{
-    if (!Pstream::parRun())
-    {
-        return;
-    }
-
-    Info<< nl << "Parallel interface construction" << endl;
-
-    timeCheck("Before buildParallelInterface");
-
-    // Hard coded switch, can be turned on for testing and debugging purposes -
-    // all vertices will be referred to all processors, use with caution for
-    // big cases.
-    bool allPointReferral = false;
-
-    if (allPointReferral)
-    {
-        buildParallelInterfaceAll
-        (
-            referralVertices,
-            receivedVertices,
-            outputName
-        );
-
-        timeCheck("After buildParallelInterfaceAll");
-    }
-
-
-    // Reject points that are not near the boundary from the subsequent
-    // searches
-
-//    label nearProcCount = 0;
-//    label notNearProcCount = 0;
-//    boundBox quickRejectionBox(decomposition_().procBounds());
-//
-////    Pout<< "Processor boundBox: " << quickRejectionBox << endl;
-//
-//    quickRejectionBox.inflate(-0.1);
-//
-//    OFstream str("rejectionBox_" + name(Pstream::myProcNo()) + ".obj");
-//
-//    meshTools::writeOBJ
-//    (
-//        str,
-//        boundBox::faces(),
-//        quickRejectionBox.points()
-//    );
-//
-//    Pout<< "Inflated rejection boundBox: " << quickRejectionBox << endl;
-
-//    for
-//    (
-//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-//        vit != finite_vertices_end();
-//        vit++
-//    )
-//    {
-//        if (vit->real() && !vit->nearProcBoundary())
-//        {
-//            const Foam::point& pt = topoint(vit->point());
-//            const scalar range = targetCellSize(pt);
-//
-////            if
-////            (
-////                decomposition_().overlapsThisProcessor
-////                (
-////                    pt,
-////                    range
-////                )
-////            )
-//            if (!quickRejectionBox.contains(pt))
-//            {
-//                vit->setNearProcBoundary();
-//                nearProcCount++;
-//            }
-//            else
-//            {
-//                //vit->setNearProcBoundary();
-//                notNearProcCount++;
-//            }
-//        }
-//    }
-//
-//    reduce(nearProcCount, sumOp<label>());
-//    reduce(notNearProcCount, sumOp<label>());
-//
-//    timeCheck
-//    (
-//        "End of potential intersection search. "
-//      + name(nearProcCount) + " are near a processor boundary. "
-//      + name(notNearProcCount) + " are not."
-//    );
-
-//    if (initialEdgeReferral)
-//    {
-//        // Used as an initial pass to localise the vertex referring - find
-//        // vertices whose dual edges pierce nearby processor volumes and refer
-//        // them to establish a sensible boundary interface region before
-//        // running a circumsphere assessment.
-//
-//        buildParallelInterfaceIntersection
-//        (
-//            referralVertices,
-//            receivedVertices,
-//            outputName
-//        );
-//
-//        timeCheck("After buildParallelInterfaceIntersection");
-//    }
-
-    buildParallelInterfaceInfluence
-    (
-        referralVertices,
-        receivedVertices,
-        outputName
-    );
-
-    timeCheck("After buildParallelInterface");
-
-    // Check all referred vertices are actually used on the processor.
-    label nUnusedReferred = numberOfUnusedReferredPoints();
-
-    reduce(nUnusedReferred, sumOp<label>());
-
-    Info<< "    Number of referred points that are not used : "
-        << nUnusedReferred << " (approximate)" << endl;
-}
-
-
-Foam::label Foam::conformalVoronoiMesh::numberOfUnusedReferredPoints() const
-{
-    label nUnusedPoints = 0;
-
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        ++vit
-    )
-    {
-        if (vit->referred())
-        {
-            std::list<Vertex_handle> adjVertices;
-            finite_adjacent_vertices(vit, std::back_inserter(adjVertices));
-
-            bool isUsed = false;
-
-            for
-            (
-                std::list<Vertex_handle>::iterator adjVit = adjVertices.begin();
-                adjVit != adjVertices.end();
-                ++adjVit
-            )
-            {
-                if ((*adjVit)->real())
-                {
-                    isUsed = true;
-                }
-            }
-
-            if (!isUsed)
-            {
-                nUnusedPoints++;
-            }
-        }
-    }
-
-    return nUnusedPoints;
-}
-
-
-void Foam::conformalVoronoiMesh::buildParallelInterfaceAll
-(
-    List<labelHashSet>& referralVertices,
-    List<labelHashSet>& receivedVertices,
-    const word& outputName
-)
-{
-    // Refer all points to all processors
-
-    DynamicList<Foam::point> parallelAllPoints;
-    DynamicList<label> targetProcessor;
-    DynamicList<label> parallelAllIndices;
-
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        ++vit
-    )
-    {
-        if (!vit->farPoint())
-        {
-            for (label procI = 0; procI < Pstream::nProcs(); procI++)
-            {
-                if (procI == Pstream::myProcNo())
-                {
-                    continue;
-                }
-
-                label vIndex = vit->index();
-
-                // Using the hashSet to ensure that each vertex is
-                // only referred once to each processor
-                if (!referralVertices[procI].found(vIndex))
-                {
-                    referralVertices[procI].insert(vIndex);
-
-                    parallelAllPoints.append
-                    (
-                        topoint(vit->point())
-                    );
-
-                    targetProcessor.append(procI);
-
-                    if (vit->internalOrBoundaryPoint())
-                    {
-                        parallelAllIndices.append(vIndex);
-                    }
-                    else
-                    {
-                        parallelAllIndices.append(-vIndex);
-                    }
-                }
-            }
-        }
-    }
-
-    referVertices
-    (
-        targetProcessor,
-        parallelAllPoints,
-        parallelAllIndices,
-        receivedVertices,
-        "all",
-        outputName
-    );
-}
-
-void Foam::conformalVoronoiMesh::buildParallelInterfaceIntersection
-(
-    List<labelHashSet>& referralVertices,
-    List<labelHashSet>& receivedVertices,
-    const word& outputName
-)
-{
-    DynamicList<Foam::point> parallelIntersectionPoints;
-    DynamicList<label> targetProcessor;
-    DynamicList<label> parallelIntersectionIndices;
-
-    // End points of dual edges.  Some of these values will not be used,
-    // i.e. for edges with non-real vertices.
-    DynamicList<Foam::point> dE0;
-    DynamicList<Foam::point> dE1;
-
-    PackedBoolList testFacetIntersection(number_of_facets(), false);
-
-    // Index outer (all) Delaunauy facets for whether they are potential
-    // intersections, index (inner) the list of tests an results.
-    label fIInner = 0;
-    label fIOuter = 0;
-
-    for
-    (
-        Delaunay::Finite_facets_iterator fit = finite_facets_begin();
-        fit != finite_facets_end();
-        ++fit
-    )
-    {
-        const Cell_handle c1(fit->first);
-        const Cell_handle c2(c1->neighbor(fit->second));
-
-        // If either Delaunay cell at the end of the Dual edge is infinite,
-        // skip.
-        if
-        (
-            !is_infinite(c1) && !is_infinite(c2)
-        )
-        {
-            // The Delaunauy cells at either end of the dual edge need to be
-            // real, i.e. all vertices form part of the internal or boundary
-            // definition
-            if
-            (
-                c1->internalOrBoundaryDualVertex()
-             && c2->internalOrBoundaryDualVertex()
-            )
-            {
-                const Foam::point& a = c1->dual();
-                const Foam::point& b = c2->dual();
-
-                // Only if the dual edge cuts the boundary of this processor is
-                // it going to be counted.
-                pointIndexHit info = decomposition_().findLineAny(a, b);
-
-                if (info.hit())
-                {
-                    dE0.append(a);
-                    dE1.append(b);
-
-                    testFacetIntersection[fIOuter] = true;
-                }
-            }
-        }
-
-        fIOuter++;
-    }
-
-    reduce(fIOuter, sumOp<label>());
-
-    timeCheck
-    (
-        "End of actual intersection search over "
-      + name(fIOuter)
-      + " faces."
-    );
-
-    // Preform intersections in both directions, as there is no sense
-    // associated with the Dual edge
-    List<List<pointIndexHit> > intersectionForward(intersectsProc(dE0, dE1));
-    List<List<pointIndexHit> > intersectionReverse(intersectsProc(dE1, dE0));
-
-    timeCheck("End of find processor intersection");
-
-    // Reset counter
-    fIOuter = 0;
-
-    // Relying on the order of iteration of facets being the same as before
-    for
-    (
-        Delaunay::Finite_facets_iterator fit = finite_facets_begin();
-        fit != finite_facets_end();
-        ++fit
-    )
-    {
-        const Cell_handle c1(fit->first);
-        const Cell_handle c2(c1->neighbor(fit->second));
-
-        // Pre-tested facet intersection potential
-        if (testFacetIntersection[fIOuter])
-        {
-            const Foam::point a = dE0[fIInner];
-            const Foam::point b = dE1[fIInner];
-
-            scalar hitDistSqr = GREAT;
-            label closestHitProc = -1;
-            scalar closestHitDistSqr = GREAT;
-
-            // Find the closest intersection with the other background meshes
-            // of the other processors in each direction, finding the closest.
-            forAll(intersectionForward[fIInner], iFI)
-            {
-                const pointIndexHit& info = intersectionForward[fIInner][iFI];
-
-                if (info.hit())
-                {
-                    // Line was a -> hit
-                    hitDistSqr = magSqr(a - info.hitPoint());
-                }
-
-                if (hitDistSqr < closestHitDistSqr)
-                {
-                    closestHitProc = info.index();
-                    closestHitDistSqr = hitDistSqr;
-                }
-            }
-
-            forAll(intersectionReverse[fIInner], iRI)
-            {
-                const pointIndexHit& info = intersectionReverse[fIInner][iRI];
-
-                if (info.hit())
-                {
-                    // Line was b -> hit
-                    hitDistSqr = magSqr(b - info.hitPoint());
-                }
-
-                if (hitDistSqr < closestHitDistSqr)
-                {
-                    closestHitProc = info.index();
-                    closestHitDistSqr = hitDistSqr;
-                }
-            }
-
-            if (closestHitProc >= 0)
-            {
-                // This dual edge pierces a processor, refer all vertices from
-                // both Delaunauy cells to it.
-
-                for (int i = 0; i < 4; i++)
-                {
-                    Vertex_handle v = c1->vertex(i);
-
-                    label vIndex = v->index();
-
-                    if (v->farPoint() || v->referred())
-                    {
-                        continue;
-                    }
-
-                    // Using the hashSet to ensure that each vertex is only
-                    // referred once to each processor
-                    if (!referralVertices[closestHitProc].found(vIndex))
-                    {
-                        referralVertices[closestHitProc].insert(vIndex);
-
-                        parallelIntersectionPoints.append(topoint(v->point()));
-
-                        targetProcessor.append(closestHitProc);
-
-                        if (v->internalOrBoundaryPoint())
-                        {
-                            parallelIntersectionIndices.append(vIndex);
-                        }
-                        else
-                        {
-                            parallelIntersectionIndices.append(-vIndex);
-                        }
-
-                        // Pout<< "Refer "
-                        //     << parallelIntersectionPoints.last()
-                        //     << " " << parallelIntersectionIndices.last()
-                        //     << " " << closestHitProc
-                        //     << endl;
-                    }
-                }
-
-                for (int i = 0; i < 4; i++)
-                {
-                    Vertex_handle v = c2->vertex(i);
-
-                    label vIndex = v->index();
-
-                    if (v->farPoint() || v->referred())
-                    {
-                        continue;
-                    }
-
-                    // Using the hashSet to ensure that each vertex is only
-                    // referred once to each processor
-                    if (!referralVertices[closestHitProc].found(vIndex))
-                    {
-                        referralVertices[closestHitProc].insert(vIndex);
-
-                        parallelIntersectionPoints.append(topoint(v->point()));
-
-                        targetProcessor.append(closestHitProc);
-
-                        if (v->internalOrBoundaryPoint())
-                        {
-                            parallelIntersectionIndices.append(vIndex);
-                        }
-                        else
-                        {
-                            parallelIntersectionIndices.append(-vIndex);
-                        }
-
-                        // Pout<< "Refer "
-                        //     << parallelIntersectionPoints.last()
-                        //     << " " << parallelIntersectionIndices.last()
-                        //     << " " << closestHitProc
-                        //     << endl;
-                    }
-                }
-            }
-
-            fIInner++;
-        }
-
-        fIOuter++;
-    }
-
-    referVertices
-    (
-        targetProcessor,
-        parallelIntersectionPoints,
-        parallelIntersectionIndices,
-        receivedVertices,
-        "intersection",
-        outputName
-    );
-}
-
-
-void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence
-(
-    List<labelHashSet>& referralVertices,
-    List<labelHashSet>& receivedVertices,
-    const word& outputName
-)
-{
-    DynamicList<Foam::point> parallelInfluencePoints;
-    DynamicList<label> targetProcessor;
-    DynamicList<label> parallelInfluenceIndices;
-
-    // Some of these values will not be used, i.e. for non-real cells
-    DynamicList<Foam::point> circumcentre;
-    DynamicList<scalar> circumradiusSqr;
-
-
-    // Index outer (all) Delaunauy cells for whether they are potential
-    // overlaps, index (inner) the list of tests an results.
-    label cIInner = 0;
-    label cIOuter = 0;
-
-    seedProcessorBoundarySurfaces(true);
-
-    label cellIndexCount = 0;
-    for
-    (
-        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-        cit != finite_cells_end();
-        ++cit
-    )
-    {
-        cit->cellIndex() = cellIndexCount++;
-    }
-
-
-    timeCheck("End of cell Indexing");
-
-    labelList testCellInfluence(number_of_cells(), 0);
-
-    label nQuickRejections = 0;
-
-    for
-    (
-        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-        cit != finite_cells_end();
-        ++cit
-    )
-    {
-        const Foam::point& cc = cit->dual();
-
-        const scalar crSqr = magSqr(cc - topoint(cit->vertex(0)->point()));
-
-        if
-        (
-            decomposition_().tree().quickCircumsphereRejection
-            (
-                cc,
-                crSqr,
-                decomposition_().octreeNearestDistances()
-            )
-        )
-        {
-            nQuickRejections++;
-            //testCellInfluence[cit->cellIndex()] = -1;
-        }
-    }
-
-    timeCheck("End of octreeNearestDistances calculation");
-
-    for
-    (
-        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-        cit != finite_cells_end();
-        ++cit
-    )
-    {
-        // Assess the influence of the circumsphere of each Delaunay cell with
-        // the defining volumes for all processors.  Any processor touched by
-        // the circumsphere requires all points of the cell to be referred to
-        // it.
-
-        // The Delaunay cells to assess have to be real, i.e. all vertices form
-        // part of the internal or any part of the boundary definition
-        if
-        (
-            (testCellInfluence[cit->cellIndex()] == 0)
-         && (cit->real() || cit->hasFarPoint())
-        )
-        {
-            const Foam::point& cc = cit->dual();
-
-            const scalar crSqr = magSqr(cc - topoint(cit->vertex(0)->point()));
-
-            // Only if the circumsphere overlaps the boundary of this processor
-            // is there a chance of it overlapping others
-            if (decomposition_().overlapsThisProcessor(cc, sqr(1.01)*crSqr))
-            {
-                circumcentre.append(cc);
-                circumradiusSqr.append(crSqr);
-
-                testCellInfluence[cit->cellIndex()] = 1;
-            }
-        }
-
-        cIOuter++;
-    }
-
-    timeCheck("End of testing cell influence");
-
-//    Pout<< "Number of quick rejections = " << nQuickRejections << endl;
-    Pout<< "Number of influences = " << circumcentre.size() << endl;
-
-    // Increasing the circumspheres to increase the overlaps and compensate for
-    // floating point errors missing some referrals
-    labelListList circumsphereOverlaps
-        = decomposition_().overlapsProcessors
-          (
-              circumcentre,
-              sqr(1.01)*circumradiusSqr,
-              false
-          );
-
-    timeCheck("End of increasing overlaps");
-
-    // Reset counters
-    cIOuter = 0;
-
-    // Relying on the order of iteration of cells being the same as before
-    for
-    (
-        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-        cit != finite_cells_end();
-        ++cit
-    )
-    {
-        // Pre-tested circumsphere potential influence
-        if (testCellInfluence[cit->cellIndex()] == 1)
-        {
-            const labelList& citOverlaps = circumsphereOverlaps[cIInner];
-
-            forAll(citOverlaps, cOI)
-            {
-                label procI = citOverlaps[cOI];
-
-                for (int i = 0; i < 4; i++)
-                {
-                    Vertex_handle v = cit->vertex(i);
-
-                    label vIndex = v->index();
-
-                    if (v->farPoint() || v->referred())
-                    {
-                        continue;
-                    }
-
-                    // Using the hashSet to ensure that each vertex is only
-                    // referred once to each processor
-                    if (!referralVertices[procI].found(vIndex))
-                    {
-                        referralVertices[procI].insert(vIndex);
-
-                        parallelInfluencePoints.append(topoint(v->point()));
-
-                        targetProcessor.append(procI);
-
-                        if (v->internalOrBoundaryPoint())
-                        {
-                            parallelInfluenceIndices.append(vIndex);
-                        }
-                        else
-                        {
-                            parallelInfluenceIndices.append(-vIndex);
-                        }
-                    }
-                }
-            }
-
-            cIInner++;
-        }
-
-        cIOuter++;
-    }
-
-    label nFarPoints = removeProcessorBoundarySeeds(true);
-
-    reduce(nFarPoints, sumOp<label>());
-
-    Info<< "    Removed " << nFarPoints
-        << " far points from the mesh." << endl;
-
-
-//    seedProcessorBoundarySurfaces(false);
-
-//    cIInner = 0;
-//    cIOuter = 0;
-
-
-    // Relying on the order of iteration of cells being the same as before
-//    for
-//    (
-//        Delaunay::Finite_cells_iterator cit = finite_cells_begin();
-//        cit != finite_cells_end();
-//        ++cit
-//    )
-//    {
-//        // Pre-tested circumsphere potential influence
-//        if (testCellInfluence[cIOuter])
-//        {
-//            const labelList& citOverlaps = circumsphereOverlaps[cIInner];
-//
-//            forAll(citOverlaps, cOI)
-//            {
-//                label procI = citOverlaps[cOI];
-//
-//                recursiveCircumsphereSearch
-//                (
-//                    cit,
-//                    procI,
-//                    referralVertices,
-//                    checkedCells,
-//                    parallelInfluencePoints,
-//                    parallelInfluenceIndices,
-//                    targetProcessor
-//                );
-//            }
-//
-//            cIInner++;
-//        }
-//
-//        cIOuter++;
-//    }
-
-//    for
-//    (
-//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-//        vit != finite_vertices_end();
-//        ++vit
-//    )
-//    {
-//        if (vit->referred())
-//        {
-//            //Pout << "REMOVE: " << topoint(vit->point()) << endl;
-//            remove(vit);
-//        }
-//    }
-
-    referVertices
-    (
-        targetProcessor,
-        parallelInfluencePoints,
-        parallelInfluenceIndices,
-        receivedVertices,
-        "influence",
-        outputName
-    );
-}
-
-
-void Foam::conformalVoronoiMesh::referVertices
-(
-    const DynamicList<label>& targetProcessor,
-    DynamicList<Foam::point>& parallelPoints,
-    DynamicList<label>& parallelIndices,
-    List<labelHashSet>& receivedVertices,
-    const word& stageName,
-    const word& outputName
-)
-{
-    timeCheck("Start of referVertices " + stageName);
-
-    if (cvMeshControls().objOutput())
-    {
-        writePoints
-        (
-            "parallel_" + stageName +"_pointsToSend_" + outputName + ".obj",
-            parallelPoints
-        );
-    }
-
-    mapDistribute pointMap = backgroundMeshDecomposition::buildMap
-    (
-        targetProcessor
-    );
-
-    label totalVertices = parallelPoints.size();
+    return flagIntersection;
+}
 
-    reduce(totalVertices, sumOp<label>());
 
-    pointMap.distribute(parallelPoints);
+bool Foam::conformalVoronoiMesh::clipLineToProc
+(
+    const Foam::point& pt,
+    Foam::point& a,
+    Foam::point& b
+) const
+{
+    bool inProc = false;
 
-    pointMap.distribute(parallelIndices);
+    pointIndexHit findAnyIntersection = decomposition_().findLine(a, b);
 
-    if (cvMeshControls().objOutput())
+    if (!findAnyIntersection.hit())
     {
-        writePoints
-        (
-            "parallel_" + stageName +"_pointsReceived_" + outputName + ".obj",
-            parallelPoints
-        );
-    }
-
-    timeCheck("Start of referVertices " + stageName + " insertion.");
-
-    label inserted = 0;
+        pointIndexHit info = decomposition_().findLine(a, pt);
 
-    for (label procI = 0; procI < Pstream::nProcs(); procI++)
+        if (!info.hit())
+        {
+            inProc = true;
+        }
+        else
+        {
+            inProc = false;
+        }
+    }
+    else
     {
-        const labelList& constructMap = pointMap.constructMap()[procI];
+        pointIndexHit info = decomposition_().findLine(a, pt);
 
-        if (constructMap.size())
+        if (!info.hit())
         {
-            forAll(constructMap, i)
-            {
-                label origIndex = parallelIndices[constructMap[i]];
-
-                if (!receivedVertices[procI].found(origIndex))
-                {
-                    // For the initial referred vertices, the original
-                    // processor is the one that is sending it.
-                    label encodedProcI = Vb::encodeProcIndex(procI);
-
-                    // Pout<< "Insert "
-                    //     << parallelPoints[constructMap[i]]
-                    //     << " " << origIndex
-                    //     << " " << procI
-                    //     << endl;
-
-                    insertPoint
-                    (
-                        parallelPoints[constructMap[i]],
-                        origIndex,
-                        encodedProcI
-                    );
-
-                    inserted++;
-
-                    receivedVertices[procI].insert(origIndex);
-                }
-            }
+            inProc = true;
+            b = findAnyIntersection.hitPoint();
+        }
+        else
+        {
+            inProc = true;
+            a = findAnyIntersection.hitPoint();
         }
     }
 
-    reduce(inserted, sumOp<label>());
-
-    Info<< "    Inserted " << stageName << " vertices " << inserted << endl;
-
-    Info<< "    Total " << stageName << " vertices " << totalVertices << endl;
-
-    timeCheck("End of referVertices " + stageName);
+    return inProc;
 }
 
 
@@ -1821,7 +1114,7 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion
     std::list<Facet> facets;
     finite_incident_facets(vit, std::back_inserter(facets));
 
-    const Foam::point vert = topoint(vit->point());
+    pointFromPoint vert = topoint(vit->point());
 
     scalar maxProtrusionDistance = maxSurfaceProtrusion(vert);
 
@@ -1832,12 +1125,20 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion
         ++fit
     )
     {
-        const Foam::point edgeMid =
-            0.5
-           *(
-                fit->first->dual()
-              + fit->first->neighbor(fit->second)->dual()
-            );
+        Cell_handle c1 = fit->first;
+        Cell_handle c2 = fit->first->neighbor(fit->second);
+
+        if
+        (
+            is_infinite(c1) || is_infinite(c2)
+         || !c1->hasInternalPoint() || !c2->hasInternalPoint()
+         || !c1->real() || !c2->real()
+        )
+        {
+            continue;
+        }
+
+        Foam::point edgeMid = 0.5*(c1->dual() + c2->dual());
 
         pointIndexHit surfHit;
         label hitSurface;
@@ -1906,7 +1207,7 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion
     std::list<Facet> facets;
     finite_incident_facets(vit, std::back_inserter(facets));
 
-    const Foam::point vert = topoint(vit->point());
+    pointFromPoint vert = topoint(vit->point());
 
     scalar minIncursionDistance = -maxSurfaceProtrusion(vert);
 
@@ -1917,12 +1218,20 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion
         ++fit
     )
     {
-        const Foam::point edgeMid =
-            0.5
-           *(
-                fit->first->dual()
-              + fit->first->neighbor(fit->second)->dual()
-            );
+        Cell_handle c1 = fit->first;
+        Cell_handle c2 = fit->first->neighbor(fit->second);
+
+        if
+        (
+            is_infinite(c1) || is_infinite(c2)
+         || !c1->hasInternalPoint() || !c2->hasInternalPoint()
+         || !c1->real() || !c2->real()
+        )
+        {
+            continue;
+        }
+
+        Foam::point edgeMid = 0.5*(c1->dual() + c2->dual());
 
         pointIndexHit surfHit;
         label hitSurface;
@@ -2003,111 +1312,110 @@ void Foam::conformalVoronoiMesh::reportProcessorOccupancy()
 }
 
 
-void Foam::conformalVoronoiMesh::reportSurfaceConformationQuality()
-{
-    Info<< nl << "Check surface conformation quality" << endl;
-
-    for
-    (
-        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-        vit != finite_vertices_end();
-        vit++
-    )
-    {
-        if (vit->internalOrBoundaryPoint())
-        {
-            Foam::point vert(topoint(vit->point()));
-            pointIndexHit surfHit;
-            label hitSurface;
-
-            dualCellLargestSurfaceProtrusion(vit, surfHit, hitSurface);
-
-            if (surfHit.hit())
-            {
-                Pout<< nl << "Residual penetration: " << nl
-                    << vit->index() << nl
-                    << vit->type() << nl
-                    << vit->ppMaster() << nl
-                    << "nearFeaturePt "
-                    << nearFeaturePt(surfHit.hitPoint()) << nl
-                    << vert << nl
-                    << surfHit.hitPoint()
-                    << endl;
-            }
-        }
-    }
-
-    {
-        // Assess close surface points
-
-        setVertexSizeAndAlignment();
-
-        for
-        (
-            Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
-            vit != finite_vertices_end();
-            vit++
-        )
-        {
-            if (vit->ppMaster())
-            {
-                std::list<Vertex_handle> adjacentVertices;
-
-                adjacent_vertices(vit, std::back_inserter(adjacentVertices));
-
-                Foam::point pt = topoint(vit->point());
-
-                // Pout<< nl << "vit: " << vit->index() << " "
-                //     << topoint(vit->point())
-                //     << endl;
-
-                // Pout<< adjacentVertices.size() << endl;
-
-                for
-                (
-                    std::list<Vertex_handle>::iterator
-                    avit = adjacentVertices.begin();
-                    avit != adjacentVertices.end();
-                    ++avit
-                )
-                {
-                    Vertex_handle avh = *avit;
-
-                    // The lower indexed vertex will perform the assessment
-                    if
-                    (
-                        avh->ppMaster()
-                     && vit->index() < avh->index()
-                     && vit->type() != avh->type()
-                    )
-                    {
-                        scalar targetSize = 0.2*averageAnyCellSize(vit, avh);
-
-                        // Pout<< "diff " << mag(pt - topoint(avh->point()))
-                        //     << " " << targetSize << endl;
-
-                        if
-                        (
-                            magSqr(pt - topoint(avh->point()))
-                          < sqr(targetSize)
-                        )
-                        {
-                            Pout<< nl << "vit: " << vit->index() << " "
-                                << topoint(vit->point())
-                                << endl;
-
-                            Pout<< "    adjacent too close: "
-                                << avh->index() << " "
-                                << topoint(avh->point())
-                                << endl;
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
+//void Foam::conformalVoronoiMesh::reportSurfaceConformationQuality()
+//{
+//    Info<< nl << "Check surface conformation quality" << endl;
+//
+//    for
+//    (
+//        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+//        vit != finite_vertices_end();
+//        vit++
+//    )
+//    {
+//        if (vit->internalOrBoundaryPoint())
+//        {
+//            Foam::point vert(topoint(vit->point()));
+//            pointIndexHit surfHit;
+//            label hitSurface;
+//
+//            dualCellLargestSurfaceProtrusion(vit, surfHit, hitSurface);
+//
+//            if (surfHit.hit())
+//            {
+//                Pout<< nl << "Residual penetration: " << nl
+//                    << vit->index() << nl
+//                    << vit->type() << nl
+//                    << vit->ppMaster() << nl
+//                    << "nearFeaturePt "
+//                    << nearFeaturePt(surfHit.hitPoint()) << nl
+//                    << vert << nl
+//                    << surfHit.hitPoint()
+//                    << endl;
+//            }
+//        }
+//    }
+//
+//    {
+//        // Assess close surface points
+//
+//        setVertexSizeAndAlignment();
+//
+//        for
+//        (
+//            Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+//            vit != finite_vertices_end();
+//            vit++
+//        )
+//        {
+//            if (vit->ppMaster())
+//            {
+//                std::list<Vertex_handle> adjacentVertices;
+//
+//                adjacent_vertices(vit, std::back_inserter(adjacentVertices));
+//
+//                Foam::point pt = topoint(vit->point());
+//
+//                // Pout<< nl << "vit: " << vit->index() << " "
+//                //     << topoint(vit->point())
+//                //     << endl;
+//
+//                // Pout<< adjacentVertices.size() << endl;
+//
+//                for
+//                (
+//                    std::list<Vertex_handle>::iterator
+//                    avit = adjacentVertices.begin();
+//                    avit != adjacentVertices.end();
+//                    ++avit
+//                )
+//                {
+//                    Vertex_handle avh = *avit;
+//
+//                    // The lower indexed vertex will perform the assessment
+//                    if
+//                    (
+//                        avh->ppMaster()
+//                     && vit->index() < avh->index()
+//                     && vit->type() != avh->type()
+//                    )
+//                    {
+//                        scalar targetSize = 0.2*averageAnyCellSize(vit, avh);
+//
+//                        // Pout<< "diff " << mag(pt - topoint(avh->point()))
+//                        //     << " " << targetSize << endl;
+//
+//                        if
+//                        (
+//                            magSqr(pt - topoint(avh->point()))
+//                          < sqr(targetSize)
+//                        )
+//                        {
+//                            Pout<< nl << "vit: " << vit->index() << " "
+//                                << topoint(vit->point())
+//                                << endl;
+//
+//                            Pout<< "    adjacent too close: "
+//                                << avh->index() << " "
+//                                << topoint(avh->point())
+//                                << endl;
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//    }
+//}
 
 void Foam::conformalVoronoiMesh::limitDisplacement
 (
@@ -2124,7 +1432,7 @@ void Foam::conformalVoronoiMesh::limitDisplacement
         return;
     }
 
-    Foam::point pt = topoint(vit->point());
+    pointFromPoint pt = topoint(vit->point());
     Foam::point dispPt = pt + displacement;
 
     bool limit = false;
@@ -2205,6 +1513,11 @@ Foam::scalar Foam::conformalVoronoiMesh::angleBetweenSurfacePoints
         pAsurfaceHit
     );
 
+    if (!pAhit.hit())
+    {
+        return constant::mathematical::pi;
+    }
+
     vectorField norm(1);
 
     allGeometry_[pAsurfaceHit].getNormal
@@ -2226,6 +1539,11 @@ Foam::scalar Foam::conformalVoronoiMesh::angleBetweenSurfacePoints
         pBsurfaceHit
     );
 
+    if (!pBhit.hit())
+    {
+        return constant::mathematical::pi;
+    }
+
     allGeometry_[pBsurfaceHit].getNormal
     (
         List<pointIndexHit>(1, pBhit),
@@ -2240,84 +1558,81 @@ Foam::scalar Foam::conformalVoronoiMesh::angleBetweenSurfacePoints
 
 bool Foam::conformalVoronoiMesh::nearSurfacePoint
 (
-    pointIndexHit& pHit,
-    label& surfaceHit,
-    DynamicList<Foam::point>& existingSurfacePtLocations
+    pointIndexHitAndFeature& pHit
 ) const
 {
-    const Foam::point& pt = pHit.hitPoint();
+    const Foam::point& pt = pHit.first().hitPoint();
 
     pointIndexHit closePoint;
 
     const bool closeToSurfacePt = pointIsNearSurfaceLocation(pt, closePoint);
 
-    if (closeToSurfacePt)
-    {
-        const scalar cosAngle
-            = angleBetweenSurfacePoints(pt, closePoint.hitPoint());
-
-        // @todo make this tolerance run-time selectable?
-        if (cosAngle < searchAngleOppositeSurface)
-        {
-            pointIndexHit pCloseHit;
-            label pCloseSurfaceHit = -1;
-
-            const scalar searchDist = targetCellSize(closePoint.hitPoint());
-
-            geometryToConformTo_.findSurfaceNearest
-            (
-                closePoint.hitPoint(),
-                searchDist,
-                pCloseHit,
-                pCloseSurfaceHit
-            );
-
-            vectorField norm(1);
-
-            allGeometry_[pCloseSurfaceHit].getNormal
-            (
-                List<pointIndexHit>(1, pCloseHit),
-                norm
-            );
-
-            const vector nA = norm[0];
-
-            pointIndexHit oppositeHit;
-            label oppositeSurfaceHit = -1;
-
-            geometryToConformTo_.findSurfaceNearestIntersection
-            (
-                closePoint.hitPoint() + SMALL*nA,
-                closePoint.hitPoint() + mag(pt - closePoint.hitPoint())*nA,
-                oppositeHit,
-                oppositeSurfaceHit
-            );
-
-            if (oppositeHit.hit())
-            {
-                // Replace point
-                pHit = oppositeHit;
-                surfaceHit = oppositeSurfaceHit;
-
-                Foam::point newPt = oppositeHit.hitPoint();
-
-                appendToSurfacePtTree(newPt, existingSurfacePtLocations);
-
-                return !closeToSurfacePt;
-
-                if (debug)
-                {
-                    Info<< "Point " << pt
-                        << " is close to " << closePoint.hitPoint()
-                        << " so will be moved to " << oppositeHit.hitPoint()
-                        << endl;
-                }
-            }
-        }
-    }
-    else
+//    if
+//    (
+//        closeToSurfacePt
+//     && mag(pt - closePoint.hitPoint()) > pointPairDistance(pt)
+//    )
+//    {
+//        const scalar cosAngle
+//            = angleBetweenSurfacePoints(pt, closePoint.hitPoint());
+//
+//        // @todo make this tolerance run-time selectable?
+//        if (cosAngle < searchAngleOppositeSurface)
+//        {
+//            pointIndexHit pCloseHit;
+//            label pCloseSurfaceHit = -1;
+//
+//            const scalar searchDist = targetCellSize(closePoint.hitPoint());
+//
+//            if (searchDist < SMALL)
+//            {
+//                Pout<< "WARNING: SMALL CELL SIZE" << endl;
+//            }
+//
+//            geometryToConformTo_.findSurfaceNearest
+//            (
+//                closePoint.hitPoint(),
+//                searchDist,
+//                pCloseHit,
+//                pCloseSurfaceHit
+//            );
+//
+//            vectorField norm(1);
+//
+//            allGeometry_[pCloseSurfaceHit].getNormal
+//            (
+//                List<pointIndexHit>(1, pCloseHit),
+//                norm
+//            );
+//
+//            const vector nA = norm[0];
+//
+//            pointIndexHit oppositeHit;
+//            label oppositeSurfaceHit = -1;
+//
+//            geometryToConformTo_.findSurfaceNearestIntersection
+//            (
+//                closePoint.hitPoint() + SMALL*nA,
+//                closePoint.hitPoint() + mag(pt - closePoint.hitPoint())*nA,
+//                oppositeHit,
+//                oppositeSurfaceHit
+//            );
+//
+//            if (oppositeHit.hit())
+//            {
+//                // Replace point
+//                pHit.first() = oppositeHit;
+//                pHit.second() = oppositeSurfaceHit;
+//
+//                appendToSurfacePtTree(pHit.first().hitPoint());
+//
+//                return !closeToSurfacePt;
+//            }
+//        }
+//    }
+//    else
     {
-        appendToSurfacePtTree(pt, existingSurfacePtLocations);
+        appendToSurfacePtTree(pt);
     }
 
     return closeToSurfacePt;
@@ -2326,15 +1641,14 @@ bool Foam::conformalVoronoiMesh::nearSurfacePoint
 
 bool Foam::conformalVoronoiMesh::appendToSurfacePtTree
 (
-    const Foam::point& pt,
-    DynamicList<Foam::point>& existingSurfacePtLocations
+    const Foam::point& pt
 ) const
 {
-   label startIndex = existingSurfacePtLocations.size();
+   label startIndex = existingSurfacePtLocations_.size();
 
-   existingSurfacePtLocations.append(pt);
+   existingSurfacePtLocations_.append(pt);
 
-   label endIndex = existingSurfacePtLocations.size();
+   label endIndex = existingSurfacePtLocations_.size();
 
    return surfacePtLocationTreePtr_().insert(startIndex, endIndex);
 }
@@ -2342,15 +1656,14 @@ bool Foam::conformalVoronoiMesh::appendToSurfacePtTree
 
 bool Foam::conformalVoronoiMesh::appendToEdgeLocationTree
 (
-    const Foam::point& pt,
-    DynamicList<Foam::point>& existingEdgeLocations
+    const Foam::point& pt
 ) const
 {
-   label startIndex = existingEdgeLocations.size();
+   label startIndex = existingEdgeLocations_.size();
 
-   existingEdgeLocations.append(pt);
+   existingEdgeLocations_.append(pt);
 
-   label endIndex = existingEdgeLocations.size();
+   label endIndex = existingEdgeLocations_.size();
 
    return edgeLocationTreePtr_().insert(startIndex, endIndex);
 }
@@ -2442,8 +1755,7 @@ bool Foam::conformalVoronoiMesh::pointIsNearSurfaceLocation
 
 bool Foam::conformalVoronoiMesh::nearFeatureEdgeLocation
 (
-    pointIndexHit& pHit,
-    DynamicList<Foam::point>& existingEdgeLocations
+    pointIndexHit& pHit
 ) const
 {
     Foam::point pt = pHit.hitPoint();
@@ -2513,7 +1825,7 @@ bool Foam::conformalVoronoiMesh::nearFeatureEdgeLocation
 
     if (!closeToFeatureEdge)
     {
-        appendToEdgeLocationTree(pt, existingEdgeLocations);
+        appendToEdgeLocationTree(pt);
     }
 
     return closeToFeatureEdge;
@@ -2609,57 +1921,34 @@ void Foam::conformalVoronoiMesh::buildSizeAndAlignmentTree() const
 void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
 (
     const Delaunay::Finite_vertices_iterator& vit,
-    const Foam::point& vert,
-    const DynamicList<pointIndexHit>& surfHit,
-    const DynamicList<label>& hitSurface,
+    const pointIndexHitAndFeatureDynList& surfaceIntersections,
     scalar surfacePtReplaceDistCoeffSqr,
     scalar edgeSearchDistCoeffSqr,
-    DynamicList<pointIndexHit>& surfaceHits,
-    DynamicList<label>& hitSurfaces,
-    DynamicList<pointIndexHit>& featureEdgeHits,
-    DynamicList<label>& featureEdgeFeaturesHit,
-    DynamicList<Foam::point>& newEdgeLocations,
-    DynamicList<Foam::point>& existingEdgeLocations,
-    DynamicList<Foam::point>& existingSurfacePtLocations
+    pointIndexHitAndFeatureDynList& surfaceHits,
+    pointIndexHitAndFeatureDynList& featureEdgeHits
 ) const
 {
-    const scalar cellSize = targetCellSize(vert);
+    const scalar cellSize = targetCellSize(topoint(vit->point()));
     const scalar cellSizeSqr = sqr(cellSize);
 
-    forAll(surfHit, sI)
+    forAll(surfaceIntersections, sI)
     {
-        bool keepSurfacePoint = true;
+        pointIndexHitAndFeature surfHitI = surfaceIntersections[sI];
 
-        pointIndexHit surfHitI = surfHit[sI];
-        label hitSurfaceI = hitSurface[sI];
+        bool keepSurfacePoint = true;
 
-        if (!surfHitI.hit())
+        if (!surfHitI.first().hit())
         {
             continue;
         }
 
-        bool isNearFeaturePt = nearFeaturePt(surfHitI.hitPoint());
+        bool isNearFeaturePt = nearFeaturePt(surfHitI.first().hitPoint());
 
-        bool isNearSurfacePt = nearSurfacePoint
-        (
-            surfHitI,
-            hitSurfaceI,
-            existingSurfacePtLocations
-        );
+        bool isNearSurfacePt = nearSurfacePoint(surfHitI);
 
         if (isNearFeaturePt || isNearSurfacePt)
         {
             keepSurfacePoint = false;
-
-            // If the triggering Vertex is part of a feature point, allow it to
-            // conform to the surface.
-            // @todo Is this needed?! Shouldn't be any feature points here...
-            if (vit->index() < startOfInternalPoints_)
-            {
-                surfaceHits.append(surfHitI);
-
-                hitSurfaces.append(hitSurfaceI);
-            }
         }
 
         List<List<pointIndexHit> > edHitsByFeature;
@@ -2670,7 +1959,7 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
 
         geometryToConformTo_.findAllNearestEdges
         (
-            surfHitI.hitPoint(),
+            surfHitI.first().hitPoint(),
             searchRadiusSqr,
             edHitsByFeature,
             featuresHit
@@ -2688,11 +1977,13 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
 
                 if (edHit.hit())
                 {
-                    if (!nearFeaturePt(edHit.hitPoint()))
+                    const Foam::point& edPt = edHit.hitPoint();
+
+                    if (!nearFeaturePt(edPt))
                     {
                         if
                         (
-                            magSqr(edHit.hitPoint() - surfHitI.hitPoint())
+                            magSqr(edPt - surfHitI.first().hitPoint())
                           < surfacePtReplaceDistCoeffSqr*cellSizeSqr
                         )
                         {
@@ -2703,25 +1994,26 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
                             keepSurfacePoint = false;
 
                             // NEED TO REMOVE FROM THE SURFACE TREE...
-                            surfacePtLocationTreePtr_().remove
-                            (
-                                existingSurfacePtLocations.size() - 1
-                            );
+//                            surfacePtLocationTreePtr_().remove
+//                            (
+//                                existingSurfacePtLocations_.size() - 1
+//                            );
                         }
 
                         if
                         (
                             !nearFeatureEdgeLocation
                             (
-                                edHit,
-                                existingEdgeLocations
+                                edHit
                             )
                         )
                         {
                             // Do not place edge control points too close to a
                             // feature point or existing edge control points
-                            featureEdgeHits.append(edHit);
-                            featureEdgeFeaturesHit.append(featureHit);
+                            featureEdgeHits.append
+                            (
+                                pointIndexHitAndFeature(edHit, featureHit)
+                            );
                         }
                     }
                 }
@@ -2731,7 +2023,6 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
         if (keepSurfacePoint)
         {
             surfaceHits.append(surfHitI);
-            hitSurfaces.append(hitSurfaceI);
         }
     }
 }
@@ -2758,8 +2049,8 @@ void Foam::conformalVoronoiMesh::storeSurfaceConformation()
         if
         (
             !vit->referred()
-         && vit->pairPoint()
-         && vit->index() >= startOfInternalPoints_
+         && vit->boundaryPoint()
+         && !vit->featurePoint()
         )
         {
             tempSurfaceVertices.append
@@ -2767,8 +2058,7 @@ void Foam::conformalVoronoiMesh::storeSurfaceConformation()
                 Vb
                 (
                     vit->point(),
-                    0,                          // index, reset to zero
-                    vit->type() - vit->index()  // type, relative to index
+                    vit->type()
                 )
             );
         }
@@ -2784,7 +2074,7 @@ void Foam::conformalVoronoiMesh::storeSurfaceConformation()
             label(surfaceConformationVertices_.size()),
             sumOp<label>()
         )
-        << " vertices" << endl;
+        << " vertices" << nl << endl;
 }
 
 
@@ -2792,35 +2082,24 @@ void Foam::conformalVoronoiMesh::reinsertSurfaceConformation()
 {
     Info<< nl << "Reinserting stored surface conformation" << endl;
 
-    label preReinsertionSize(number_of_vertices());
+    const label preReinsertionSize(number_of_vertices());
 
     // It is assumed that the stored surface conformation is on the correct
     // processor and does not need distributed
-
-    for
+    rangeInsertWithInfo
     (
-        List<Vb>::iterator vit=surfaceConformationVertices_.begin();
-        vit != surfaceConformationVertices_.end();
-        ++vit
-    )
-    {
-        // Assuming that all of the reinsertions are pair points, and that the
-        // index and type are relative, i.e. index 0 and type relative to it.
-        insertPoint
-        (
-            vit->point(),
-            vit->index() + number_of_vertices(),
-            vit->type() + number_of_vertices()
-        );
-    }
+        surfaceConformationVertices_.begin(),
+        surfaceConformationVertices_.end(),
+        true
+    );
 
-    Info<< "    Reinserted "
-        << returnReduce
-        (
-            label(number_of_vertices()) - preReinsertionSize,
-            sumOp<label>()
-        )
-        << " vertices" << endl;
+    const label nInserted = label(number_of_vertices()) - preReinsertionSize;
+    const label nFailed = surfaceConformationVertices_.size() - nInserted;
+
+    Info<< "    " << returnReduce(nInserted, sumOp<label>())
+        << " points reinserted, failed to insert "
+        << returnReduce(nFailed, sumOp<label>())
+        << endl;
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePointSpecialisations.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePointSpecialisations.C
index 2882be0c6ff55a98741a1b996b69c86caeeb7ffd..2f7579cbbff95339c341b32c9857ec82dcc100b0 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePointSpecialisations.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePointSpecialisations.C
@@ -48,39 +48,7 @@ Foam::conformalVoronoiMesh::calcPointFeatureEdgesTypes
 
         eS = feMesh.getEdgeStatus(edgeI);
 
-        switch (eS)
-        {
-            case extendedFeatureEdgeMesh::EXTERNAL:
-            {
-                pFEdgeTypes.nExternal++;
-                break;
-            }
-            case extendedFeatureEdgeMesh::INTERNAL:
-            {
-                pFEdgeTypes.nInternal++;
-                break;
-            }
-            case extendedFeatureEdgeMesh::FLAT:
-            {
-                pFEdgeTypes.nFlat++;
-                break;
-            }
-            case extendedFeatureEdgeMesh::OPEN:
-            {
-                pFEdgeTypes.nOpen++;
-                break;
-            }
-            case extendedFeatureEdgeMesh::MULTIPLE:
-            {
-                pFEdgeTypes.nMultiple++;
-                break;
-            }
-            case extendedFeatureEdgeMesh::NONE:
-            {
-                pFEdgeTypes.nNonFeature++;
-                break;
-            }
-        }
+        pFEdgeTypes(eS)++;
     }
 
     if (debug)
@@ -99,15 +67,22 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
     const pointFeatureEdgesTypes& pFEdgesTypes,
     const List<extendedFeatureEdgeMesh::edgeStatus>& allEdStat,
     const label ptI,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     if
     (
-        pFEdgesTypes.nExternal == 2
-     && pFEdgesTypes.nInternal == 1
+        !pFEdgesTypes.found(extendedFeatureEdgeMesh::EXTERNAL)
+     || !pFEdgesTypes.found(extendedFeatureEdgeMesh::INTERNAL)
+    )
+    {
+        return false;
+    }
+
+    if
+    (
+        pFEdgesTypes[extendedFeatureEdgeMesh::EXTERNAL] == 2
+     && pFEdgesTypes[extendedFeatureEdgeMesh::INTERNAL] == 1
      && pEds.size() == 3
     )
     {
@@ -120,6 +95,8 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
             return false;
         }
 
+        label nVert = number_of_vertices();
+
         const label initialNumOfPoints = pts.size();
 
         const scalar ppDist = pointPairDistance(featPt);
@@ -212,18 +189,20 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
           - 2.0*planeA.distance(concaveEdgeExternalPt)
             *concaveEdgePlaneANormal;
 
-        pts.append(internalPtA);
-        indices.append(0);
-        types.append(4);
+        pts.append
+        (
+            Vb(internalPtA, Vb::vtInternalFeaturePoint)
+        );
 
         const Foam::point internalPtB =
             concaveEdgeExternalPt
           - 2.0*planeB.distance(concaveEdgeExternalPt)
             *concaveEdgePlaneBNormal;
 
-        pts.append(internalPtB);
-        indices.append(0);
-        types.append(3);
+        pts.append
+        (
+            Vb(internalPtB, Vb::vtInternalFeaturePoint)
+        );
 
         // Add the external points
 
@@ -295,8 +274,7 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
                 for (label i = 0; i < 2; ++i)
                 {
                     pts.remove();
-                    indices.remove();
-                    types.remove();
+                    nVert--;
                 }
 
                 return false;
@@ -325,9 +303,10 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
                           + 2.0*planeC.distance(internalPtA)
                            *convexEdgePlaneCNormal;
 
-                        pts.append(externalPtD);
-                        indices.append(0);
-                        types.append(-2);
+                        pts.append
+                        (
+                            Vb(externalPtD, Vb::vtExternalFeaturePoint)
+                        );
                     }
                 }
             }
@@ -355,17 +334,19 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
                           + 2.0*planeD.distance(internalPtB)
                            *convexEdgePlaneDNormal;
 
-                        pts.append(externalPtE);
-                        indices.append(0);
-                        types.append(-2);
+                        pts.append
+                        (
+                            Vb(externalPtE, Vb::vtExternalFeaturePoint)
+                        );
                     }
                 }
             }
         }
 
-        pts.append(concaveEdgeExternalPt);
-        indices.append(0);
-        types.append(-4);
+        pts.append
+        (
+            Vb(concaveEdgeExternalPt, Vb::vtExternalFeaturePoint)
+        );
 
         const scalar totalAngle = radToDeg
         (
@@ -375,12 +356,13 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
 
         if (totalAngle > cvMeshControls().maxQuadAngle())
         {
-            // Add additional mitering points
+            // Add additional mitreing points
             //scalar angleSign = 1.0;
 
 
             vector convexEdgesPlaneNormal =
                 0.5*(convexEdgePlaneCNormal + convexEdgePlaneDNormal);
+
             plane planeM(featPt, convexEdgesPlaneNormal);
 
 //            if
@@ -410,17 +392,19 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
             //+ (2.0 + guard)*(concaveEdgeLocalFeatPt - concaveEdgeExternalPt);
               + 2.0*(concaveEdgeLocalFeatPt - concaveEdgeExternalPt);
 
-            pts.append(internalPtF);
-            indices.append(0);
-            types.append(1);
+            pts.append
+            (
+                Vb(internalPtF, Vb::vtInternalFeaturePoint)
+            );
 
             const Foam::point externalPtG =
                 internalPtF
               + 2.0*planeM.distance(internalPtF)*convexEdgesPlaneNormal;
 
-            pts.append(externalPtG);
-            indices.append(0);
-            types.append(-1);
+            pts.append
+            (
+                Vb(externalPtG, Vb::vtExternalFeaturePoint)
+            );
         }
 
         if (debug)
@@ -428,13 +412,17 @@ bool Foam::conformalVoronoiMesh::createSpecialisedFeaturePoint
             for (label ptI = initialNumOfPoints; ptI < pts.size(); ++ptI)
             {
                 Info<< "Point " << ptI << " : ";
-                meshTools::writeOBJ(Info, pts[ptI]);
+                meshTools::writeOBJ(Info, topoint(pts[ptI].point()));
             }
         }
 
         return true;
     }
-    else if (pFEdgesTypes.nExternal == 1 && pFEdgesTypes.nInternal == 2)
+    else if
+    (
+        pFEdgesTypes[extendedFeatureEdgeMesh::EXTERNAL] == 1
+     && pFEdgesTypes[extendedFeatureEdgeMesh::INTERNAL] == 2
+    )
     {
         // Info<< "nExternal == 1 && nInternal == 2" << endl;
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePoints.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePoints.C
index 407de61b3988746ec85d797ea8651d0fdb6e2b19..028dd5a0df09cf18f6e1a55b3fd3e6be08fbc1ad 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePoints.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshFeaturePoints.C
@@ -25,40 +25,19 @@ License
 
 #include "conformalVoronoiMesh.H"
 #include "vectorTools.H"
+#include "triangle.H"
+#include "tetrahedron.H"
+#include "const_circulator.H"
 
 using namespace Foam::vectorTools;
 
 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
 
-void Foam::conformalVoronoiMesh::insertBoundingPoints()
-{
-    pointField farPts(geometryToConformTo_.globalBounds().points());
-
-    // Shift corners of bounds relative to origin
-    farPts -= geometryToConformTo_.globalBounds().midpoint();
-
-    // Scale the box up
-    farPts *= 10.0;
-
-    // Shift corners of bounds back to be relative to midpoint
-    farPts += geometryToConformTo_.globalBounds().midpoint();
-
-    limitBounds_ = treeBoundBox(farPts);
-
-    forAll(farPts, fPI)
-    {
-        insertPoint(farPts[fPI], Vb::vtFar);
-    }
-}
-
-
 void Foam::conformalVoronoiMesh::createEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     label edgeI = edHit.index();
@@ -69,27 +48,27 @@ void Foam::conformalVoronoiMesh::createEdgePointGroup
     {
         case extendedFeatureEdgeMesh::EXTERNAL:
         {
-            createExternalEdgePointGroup(feMesh, edHit, pts, indices, types);
+            createExternalEdgePointGroup(feMesh, edHit, pts);
             break;
         }
         case extendedFeatureEdgeMesh::INTERNAL:
         {
-            createInternalEdgePointGroup(feMesh, edHit, pts, indices, types);
+            createInternalEdgePointGroup(feMesh, edHit, pts);
             break;
         }
         case extendedFeatureEdgeMesh::FLAT:
         {
-            createFlatEdgePointGroup(feMesh, edHit, pts, indices, types);
+            createFlatEdgePointGroup(feMesh, edHit, pts);
             break;
         }
         case extendedFeatureEdgeMesh::OPEN:
         {
-            //createOpenEdgePointGroup(feMesh, edHit, pts, indices, types);
+            createOpenEdgePointGroup(feMesh, edHit, pts);
             break;
         }
         case extendedFeatureEdgeMesh::MULTIPLE:
         {
-            //createMultipleEdgePointGroup(feMesh, edHit, pts, indices, types);
+            createMultipleEdgePointGroup(feMesh, edHit, pts);
             break;
         }
         case extendedFeatureEdgeMesh::NONE:
@@ -104,9 +83,7 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     const Foam::point& edgePt = edHit.hitPoint();
@@ -158,22 +135,30 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
 
     // Insert the master point pairing the the first slave
 
-    pts.append(refPt);
-    indices.append(0);
-    types.append(1);
+    if (!geometryToConformTo_.inside(refPt))
+    {
+        return;
+    }
+
+    pts.append
+    (
+        Vb(refPt, Vb::vtInternalFeatureEdge)
+    );
 
     // Insert the slave points by reflecting refPt in both faces.
     // with each slave refering to the master
 
     Foam::point reflectedA = refPt + 2*ppDist*nA;
-    pts.append(reflectedA);
-    indices.append(0);
-    types.append(-1);
+    pts.append
+    (
+        Vb(reflectedA, Vb::vtExternalFeatureEdge)
+    );
 
     Foam::point reflectedB = refPt + 2*ppDist*nB;
-    pts.append(reflectedB);
-    indices.append(0);
-    types.append(-2);
+    pts.append
+    (
+        Vb(reflectedB, Vb::vtExternalFeatureEdge)
+    );
 }
 
 
@@ -181,9 +166,7 @@ void Foam::conformalVoronoiMesh::createInternalEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     const Foam::point& edgePt = edHit.hitPoint();
@@ -245,9 +228,6 @@ void Foam::conformalVoronoiMesh::createInternalEdgePointGroup
     // required number of quadrants.
     int nAddPoints = min(max(nQuads - 2, 0), 2);
 
-    // index of reflMaster
-    label reflectedMaster = 2 + nAddPoints;
-
     // Add number_of_vertices() at insertion of first vertex to all numbers:
     // Result for nAddPoints 1 when the points are eventually inserted
     // pt           index type
@@ -270,41 +250,56 @@ void Foam::conformalVoronoiMesh::createInternalEdgePointGroup
     // reflectedBb  3     4
     // reflMasterPt 4     0
 
+    if
+    (
+        !geometryToConformTo_.inside(reflectedA)
+     || !geometryToConformTo_.inside(reflectedB)
+    )
+    {
+        return;
+    }
+
     // Master A is inside.
-    pts.append(reflectedA);
-    indices.append(0);
-    types.append(reflectedMaster--);
+    pts.append
+    (
+        Vb(reflectedA, Vb::vtInternalFeatureEdge)
+    );
 
     // Master B is inside.
-    pts.append(reflectedB);
-    indices.append(0);
-    types.append(reflectedMaster--);
+    pts.append
+    (
+        Vb(reflectedB, Vb::vtInternalFeatureEdge)
+    );
 
     if (nAddPoints == 1)
     {
         // One additinal point is the reflection of the slave point,
         // i.e. the original reference point
-        pts.append(refPt);
-        indices.append(0);
-        types.append(reflectedMaster--);
+        pts.append
+        (
+            Vb(refPt, Vb::vtInternalFeatureEdge)
+        );
     }
     else if (nAddPoints == 2)
     {
         Foam::point reflectedAa = refPt + ppDist*nB;
-        pts.append(reflectedAa);
-        indices.append(0);
-        types.append(reflectedMaster--);
+        pts.append
+        (
+            Vb(reflectedAa, Vb::vtInternalFeatureEdge)
+        );
 
         Foam::point reflectedBb = refPt + ppDist*nA;
-        pts.append(reflectedBb);
-        indices.append(0);
-        types.append(reflectedMaster--);
+        pts.append
+        (
+            Vb(reflectedBb, Vb::vtInternalFeatureEdge)
+        );
     }
 
     // Slave is outside.
-    pts.append(reflMasterPt);
-    indices.append(0);
-    types.append(-(nAddPoints + 2));
+    pts.append
+    (
+        Vb(reflMasterPt, Vb::vtExternalFeatureEdge)
+    );
 }
 
 
@@ -312,9 +307,7 @@ void Foam::conformalVoronoiMesh::createFlatEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     const Foam::point& edgePt = edHit.hitPoint();
@@ -337,8 +330,8 @@ void Foam::conformalVoronoiMesh::createFlatEdgePointGroup
     // is a flat edge
     vector s = ppDist*(feMesh.edgeDirections()[edHit.index()] ^ n);
 
-    createPointPair(ppDist, edgePt + s, n, pts, indices, types);
-    createPointPair(ppDist, edgePt - s, n, pts, indices, types);
+    createPointPair(ppDist, edgePt + s, n, pts);
+    createPointPair(ppDist, edgePt - s, n, pts);
 }
 
 
@@ -346,11 +339,33 @@ void Foam::conformalVoronoiMesh::createOpenEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
+//    // Assume it is a baffle and insert flat edge point pairs
+//    const Foam::point& edgePt = edHit.hitPoint();
+//
+//    const scalar ppDist = pointPairDistance(edgePt);
+//
+//    const vectorField& feNormals = feMesh.normals();
+//    const labelList& edNormalIs = feMesh.edgeNormals()[edHit.index()];
+//
+//    // As this is a flat edge, there are two normals by definition
+//    const vector& nA = feNormals[edNormalIs[0]];
+//    const vector& nB = feNormals[edNormalIs[1]];
+//
+//    // Average normal to remove any bias to one side, although as this
+//    // is a flat edge, the normals should be essentially the same
+//    const vector n = 0.5*(nA + nB);
+//
+//    // Direction along the surface to the control point, sense of edge
+//    // direction not important, as +s and -s can be used because this
+//    // is a flat edge
+//    vector s = ppDist*(feMesh.edgeDirections()[edHit.index()] ^ n);
+//
+//    createBafflePointPair(ppDist, edgePt + s, n, pts);
+//    createBafflePointPair(ppDist, edgePt - s, n, pts);
+
     Info<< "NOT INSERTING OPEN EDGE POINT GROUP, NOT IMPLEMENTED" << endl;
 }
 
@@ -359,279 +374,34 @@ void Foam::conformalVoronoiMesh::createMultipleEdgePointGroup
 (
     const extendedFeatureEdgeMesh& feMesh,
     const pointIndexHit& edHit,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     Info<< "NOT INSERTING MULTIPLE EDGE POINT GROUP, NOT IMPLEMENTED" << endl;
 }
 
 
-void Foam::conformalVoronoiMesh::reinsertBoundingPoints()
-{
-    tmp<pointField> farPts = limitBounds_.points();
-
-    forAll(farPts(), fPI)
-    {
-        insertPoint(farPts()[fPI], Vb::vtFar);
-    }
-}
-
-
 void Foam::conformalVoronoiMesh::reinsertFeaturePoints(bool distribute)
 {
     Info<< nl << "Reinserting stored feature points" << endl;
 
     label preReinsertionSize(number_of_vertices());
 
-    if (distribute)
-    {
-        DynamicList<Foam::point> pointsToInsert;
-        DynamicList<label> indices;
-        DynamicList<label> types;
-
-        for
-        (
-            List<Vb>::iterator vit=featureVertices_.begin();
-            vit != featureVertices_.end();
-            ++vit
-        )
-        {
-            pointsToInsert.append(topoint(vit->point()));
-            indices.append(vit->index());
-            types.append(vit->type());
-        }
-
-        // Insert distributed points
-        insertPoints(pointsToInsert, indices, types, true);
-
-        // Save points in new distribution
-        featureVertices_.clear();
-        featureVertices_.setSize(pointsToInsert.size());
-
-        forAll(pointsToInsert, pI)
-        {
-            featureVertices_[pI] =
-                Vb(toPoint(pointsToInsert[pI]), indices[pI], types[pI]);
-        }
-    }
-    else
-    {
-        for
-        (
-            List<Vb>::iterator vit=featureVertices_.begin();
-            vit != featureVertices_.end();
-            ++vit
-        )
-        {
-            // Assuming that all of the reinsertions are pair points, and that
-            // the index and type are relative, i.e. index 0 and type relative
-            // to it.
-            insertPoint
-            (
-                vit->point(),
-                vit->index() + number_of_vertices(),
-                vit->type() + number_of_vertices()
-            );
-        }
-    }
-
-    Info<< "    Reinserted "
-        << returnReduce
-        (
-            label(number_of_vertices()) - preReinsertionSize,
-            sumOp<label>()
-        )
-        << " vertices" << endl;
-}
-
-
-bool Foam::conformalVoronoiMesh::edgesShareNormal
-(
-    const label e1,
-    const label e2
-) const
-{
-    const PtrList<extendedFeatureEdgeMesh>& feMeshes
-    (
-        geometryToConformTo_.features()
-    );
-
-    forAll(feMeshes, i)
-    {
-        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
-
-        const vectorField& e1normals = feMesh.edgeNormals(e1);
-        const vectorField& e2normals = feMesh.edgeNormals(e2);
-
-        forAll(e1normals, nI1)
-        {
-            forAll(e2normals, nI2)
-            {
-                if (degAngleBetween(e1normals[nI1], e2normals[nI2]) < 1)
-                {
-                    return true;
-                }
-            }
-        }
-    }
-
-    return false;
-}
-
-
-void Foam::conformalVoronoiMesh::createConvexFeaturePoints
-(
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
-)
-{
-    const PtrList<extendedFeatureEdgeMesh>& feMeshes
-    (
-        geometryToConformTo_.features()
-    );
-
-    forAll(feMeshes, i)
-    {
-        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
-
-        for
-        (
-            label ptI = feMesh.convexStart();
-            ptI < feMesh.concaveStart();
-            ptI++
-        )
-        {
-            const Foam::point& featPt = feMesh.points()[ptI];
-
-            if (!positionOnThisProc(featPt))
-            {
-                continue;
-            }
-
-            const vectorField& featPtNormals = feMesh.featurePointNormals(ptI);
-
-            const scalar ppDist = - pointPairDistance(featPt);
-
-            vector cornerNormal = sum(featPtNormals);
-            cornerNormal /= mag(cornerNormal);
-
-            Foam::point internalPt = featPt + ppDist*cornerNormal;
-
-            // Result when the points are eventually inserted (example n = 4)
-            // Add number_of_vertices() at insertion of first vertex to all
-            // numbers:
-            // pt           index type
-            // internalPt   0     1
-            // externalPt0  1     0
-            // externalPt1  2     0
-            // externalPt2  3     0
-            // externalPt3  4     0
+    insertPoints(featureVertices_, distribute);
 
-            pts.append(internalPt);
-            indices.append(0);
-            types.append(1);
-
-            label internalPtIndex = -1;
-
-            forAll(featPtNormals, nI)
-            {
-                const vector& n = featPtNormals[nI];
-
-                plane planeN = plane(featPt, n);
-
-                Foam::point externalPt =
-                    internalPt + 2.0 * planeN.distance(internalPt) * n;
-
-                pts.append(externalPt);
-                indices.append(0);
-                types.append(internalPtIndex--);
-            }
-        }
-    }
-}
-
-
-void Foam::conformalVoronoiMesh::createConcaveFeaturePoints
-(
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
-)
-{
-    const PtrList<extendedFeatureEdgeMesh>& feMeshes
+    const label nReinserted = returnReduce
     (
-        geometryToConformTo_.features()
+        label(number_of_vertices()) - preReinsertionSize,
+        sumOp<label>()
     );
 
-    forAll(feMeshes, i)
-    {
-        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
-
-        for
-        (
-            label ptI = feMesh.concaveStart();
-            ptI < feMesh.mixedStart();
-            ptI++
-        )
-        {
-            const Foam::point& featPt = feMesh.points()[ptI];
-
-            if (!positionOnThisProc(featPt))
-            {
-                continue;
-            }
-
-            const vectorField& featPtNormals = feMesh.featurePointNormals(ptI);
-            const scalar ppDist = pointPairDistance(featPt);
-
-            vector cornerNormal = sum(featPtNormals);
-            cornerNormal /= mag(cornerNormal);
-
-            Foam::point externalPt = featPt + ppDist*cornerNormal;
-
-            label externalPtIndex = featPtNormals.size();
-
-            // Result when the points are eventually inserted (example n = 5)
-            // Add number_of_vertices() at insertion of first vertex to all
-            // numbers:
-            // pt           index type
-            // internalPt0  0     5
-            // internalPt1  1     5
-            // internalPt2  2     5
-            // internalPt3  3     5
-            // internalPt4  4     5
-            // externalPt   5     4
-
-            forAll(featPtNormals, nI)
-            {
-                const vector& n = featPtNormals[nI];
-
-                const plane planeN = plane(featPt, n);
-
-                const Foam::point internalPt =
-                    externalPt - 2.0 * planeN.distance(externalPt) * n;
-
-                pts.append(internalPt);
-                indices.append(0);
-                types.append(externalPtIndex--);
-            }
-
-            pts.append(externalPt);
-            indices.append(0);
-            types.append(-1);
-        }
-    }
+    Info<< "    Reinserted " << nReinserted << " vertices" << endl;
 }
 
 
 void Foam::conformalVoronoiMesh::createMixedFeaturePoints
 (
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     if (cvMeshControls().mixedFeaturePointPPDistanceCoeff() < 0)
@@ -659,6 +429,13 @@ void Foam::conformalVoronoiMesh::createMixedFeaturePoints
             ptI++
         )
         {
+            const Foam::point& featPt = points[ptI];
+
+            if (!positionOnThisProc(featPt))
+            {
+                continue;
+            }
+
             const labelList& pEds = pointsEdges[ptI];
 
             pointFeatureEdgesTypes pFEdgeTypes(ptI);
@@ -672,8 +449,7 @@ void Foam::conformalVoronoiMesh::createMixedFeaturePoints
             {
                 specialisedSuccess = createSpecialisedFeaturePoint
                 (
-                    feMesh, pEds, pFEdgeTypes, allEdStat, ptI,
-                    pts, indices, types
+                    feMesh, pEds, pFEdgeTypes, allEdStat, ptI, pts
                 );
             }
 
@@ -715,12 +491,9 @@ void Foam::conformalVoronoiMesh::createMixedFeaturePoints
                     continue;
                 }
 
-                const Foam::point& pt = points[ptI];
+//                createFeaturePoints(feMesh, ptI, pts, types);
 
-                if (!positionOnThisProc(pt))
-                {
-                    continue;
-                }
+                const Foam::point pt = points[ptI];
 
                 const scalar edgeGroupDistance = mixedFeaturePointDistance(pt);
 
@@ -733,13 +506,13 @@ void Foam::conformalVoronoiMesh::createMixedFeaturePoints
 
                     const pointIndexHit edgeHit(true, edgePt, edgeI);
 
-                    createEdgePointGroup(feMesh, edgeHit, pts, indices, types);
+                    createEdgePointGroup(feMesh, edgeHit, pts);
                 }
             }
         }
     }
 }
-
+//
 //
 //void Foam::conformalVoronoiMesh::createFeaturePoints
 //(
@@ -787,7 +560,7 @@ void Foam::conformalVoronoiMesh::createMixedFeaturePoints
 //                    surfaceConformationVertices_[indices[pI]];
 //            }
 //
-//            forAll()
+//            forAll(feMesh.)
 //
 //            // Now find the nearest points within the edge cones.
 //
@@ -803,22 +576,36 @@ void Foam::conformalVoronoiMesh::insertFeaturePoints()
 {
     Info<< nl << "Conforming to feature points" << endl;
 
-    DynamicList<Foam::point> pts;
-    DynamicList<label> indices;
-    DynamicList<label> types;
+    DynamicList<Vb> pts;
 
     const label preFeaturePointSize = number_of_vertices();
 
-    createConvexFeaturePoints(pts, indices, types);
+    createFeaturePoints(pts);
 
-    createConcaveFeaturePoints(pts, indices, types);
+    createMixedFeaturePoints(pts);
 
-//    createFeaturePoints(pts, indices, types);
+    // Points added using the createEdgePointGroup function will be labelled as
+    // internal/external feature edges. Relabel them as feature points,
+    // otherwise they are inserted as both feature points and surface points.
+    forAll(pts, pI)
+    {
+        Vb& pt = pts[pI];
 
-    createMixedFeaturePoints(pts, indices, types);
+        if (pt.featureEdgePoint())
+        {
+            if (pt.internalBoundaryPoint())
+            {
+                pt.type() = Vb::vtInternalFeaturePoint;
+            }
+            else if (pt.externalBoundaryPoint())
+            {
+                pt.type() = Vb::vtExternalFeaturePoint;
+            }
+        }
+    }
 
     // Insert the created points, distributing to the appropriate processor
-    insertPoints(pts, indices, types, true);
+    insertPoints(pts, true);
 
     if (cvMeshControls().objOutput())
     {
@@ -843,7 +630,7 @@ void Foam::conformalVoronoiMesh::insertFeaturePoints()
 
     forAll(pts, pI)
     {
-        featureVertices_[pI] = Vb(toPoint(pts[pI]), indices[pI], types[pI]);
+        featureVertices_[pI] = pts[pI];
     }
 
     constructFeaturePointLocations();
@@ -924,3 +711,525 @@ Foam::conformalVoronoiMesh::findSurfacePtLocationsNearFeaturePoint
 
     return dynPointList.shrink();
 }
+
+
+void Foam::conformalVoronoiMesh::addMasterAndSlavePoints
+(
+    const DynamicList<Foam::point>& masterPoints,
+    const DynamicList<Foam::indexedVertexEnum::vertexType>& masterPointsTypes,
+    const Map<DynamicList<autoPtr<plane> > >& masterPointReflections,
+    DynamicList<Vb>& pts,
+    const label ptI
+) const
+{
+    typedef DynamicList<autoPtr<plane> >        planeDynList;
+    typedef Foam::indexedVertexEnum::vertexType vertexType;
+
+    forAll(masterPoints, pI)
+    {
+        // Append master to the list of points
+
+//        OFstream strMasters("fpm_" + name(ptI) + ".obj");
+//        OFstream strSlaves("fps_" + name(ptI) + ".obj");
+
+        const Foam::point& masterPt = masterPoints[pI];
+        const vertexType masterType = masterPointsTypes[pI];
+
+        pts.append
+        (
+            Vb
+            (
+                masterPt,
+                masterType
+            )
+        );
+
+//        meshTools::writeOBJ(strMasters, masterPt);
+
+        const planeDynList& masterPointPlanes = masterPointReflections[pI];
+
+        forAll(masterPointPlanes, planeI)
+        {
+            // Reflect master points in the planes and insert the slave points
+
+            const plane& reflPlane = masterPointPlanes[planeI]();
+
+            const Foam::point slavePt =
+                reflectPointInPlane(masterPt, reflPlane);
+
+            const vertexType slaveType =
+            (
+                masterType == Vb::vtInternalFeaturePoint
+              ? Vb::vtExternalFeaturePoint // true
+              : Vb::vtInternalFeaturePoint // false
+            );
+
+            pts.append
+            (
+                Vb
+                (
+                    slavePt,
+                    slaveType
+                )
+            );
+
+//            meshTools::writeOBJ(strSlaves, slavePt);
+        }
+    }
+}
+
+
+Foam::label Foam::conformalVoronoiMesh::getSign
+(
+    const extendedFeatureEdgeMesh::edgeStatus eStatus
+) const
+{
+    if (eStatus == extendedFeatureEdgeMesh::EXTERNAL)
+    {
+        return -1;
+    }
+    else if (eStatus == extendedFeatureEdgeMesh::INTERNAL)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void Foam::conformalVoronoiMesh::createMasterAndSlavePoints
+(
+    const extendedFeatureEdgeMesh& feMesh,
+    const label ptI,
+    DynamicList<Vb>& pts
+) const
+{
+    typedef DynamicList<autoPtr<plane> >                planeDynList;
+    typedef Foam::indexedVertexEnum::vertexType         vertexType;
+    typedef Foam::extendedFeatureEdgeMesh::edgeStatus   edgeStatus;
+
+    const Foam::point& featPt = feMesh.points()[ptI];
+
+    if (!positionOnThisProc(featPt))
+    {
+        return;
+    }
+
+    const scalar ppDist = pointPairDistance(featPt);
+
+    // Maintain a list of master points and the planes to relect them in
+    DynamicList<Foam::point> masterPoints;
+    DynamicList<vertexType> masterPointsTypes;
+    Map<planeDynList> masterPointReflections;
+
+    const labelList& featPtEdges = feMesh.featurePointEdges()[ptI];
+
+    const_circulator<labelList> circ(featPtEdges);
+
+//    Info<< "Point = " << ptI << endl;
+
+    // Loop around the edges of the feature point
+    if (circ.size()) do
+    {
+//        const edgeStatus eStatusPrev = feMesh.getEdgeStatus(circ.prev());
+        const edgeStatus eStatusCurr = feMesh.getEdgeStatus(circ());
+//        const edgeStatus eStatusNext = feMesh.getEdgeStatus(circ.next());
+
+//        Info<< "Prev = "
+//            << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusPrev]
+//            << " Curr = "
+//            << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusCurr]
+////            << " Next = "
+////            << extendedFeatureEdgeMesh::edgeStatusNames_[eStatusNext]
+//            << endl;
+
+        // Get the direction in which to move the point in relation to the
+        // feature point
+        label sign = getSign(eStatusCurr);
+
+        const vector n = sharedFaceNormal(feMesh, circ(), circ.next());
+
+        const vector pointMotionDirection = sign*0.5*ppDist*n;
+
+        if (masterPoints.empty())
+        {
+            // Initialise with the first master point
+
+            Foam::point pt = featPt + pointMotionDirection;
+
+            planeDynList firstPlane;
+            firstPlane.append(autoPtr<plane>(new plane(featPt, n)));
+
+            masterPoints.append(pt);
+
+            masterPointsTypes.append
+            (
+                sign == 1
+              ? Vb::vtExternalFeaturePoint // true
+              : Vb::vtInternalFeaturePoint // false
+            );
+
+            if
+            (
+                masterPointsTypes.last() == Vb::vtInternalFeaturePoint
+             && !geometryToConformTo_.inside(masterPoints.last())
+            )
+            {
+                return;
+            }
+
+            const Foam::point reflectedPoint = reflectPointInPlane
+            (
+                masterPoints.last(),
+                firstPlane.last()()
+            );
+
+            if
+            (
+                masterPointsTypes.last() == Vb::vtExternalFeaturePoint
+             && !geometryToConformTo_.inside(reflectedPoint)
+            )
+            {
+                return;
+            }
+
+            masterPointReflections.insert
+            (
+                masterPoints.size() - 1,
+                firstPlane
+            );
+        }
+//        else if
+//        (
+//            eStatusPrev == extendedFeatureEdgeMesh::INTERNAL
+//         && eStatusCurr == extendedFeatureEdgeMesh::EXTERNAL
+//        )
+//        {
+//            // Insert a new master point.
+//            Foam::point pt = featPt + pointMotionDirection;
+//
+//            planeDynList firstPlane;
+//            firstPlane.append(autoPtr<plane>(new plane(featPt, n)));
+//
+//            masterPoints.append(pt);
+//
+//            masterPointsTypes.append
+//            (
+//                sign == 1
+//              ? Vb::vtExternalFeaturePoint // true
+//              : Vb::vtInternalFeaturePoint // false
+//            );
+//
+//            masterPointReflections.insert
+//            (
+//                masterPoints.size() - 1,
+//                firstPlane
+//            );
+//        }
+//        else if
+//        (
+//            eStatusPrev == extendedFeatureEdgeMesh::EXTERNAL
+//         && eStatusCurr == extendedFeatureEdgeMesh::INTERNAL
+//        )
+//        {
+//
+//        }
+        else
+        {
+            // Just add this face contribution to the latest master point
+
+            masterPoints.last() += pointMotionDirection;
+
+            masterPointReflections[masterPoints.size() - 1].append
+            (
+                autoPtr<plane>(new plane(featPt, n))
+            );
+        }
+
+    } while (circ.circulate(CirculatorBase::CLOCKWISE));
+
+    addMasterAndSlavePoints
+    (
+        masterPoints,
+        masterPointsTypes,
+        masterPointReflections,
+        pts,
+        ptI
+    );
+}
+
+
+void Foam::conformalVoronoiMesh::createFeaturePoints(DynamicList<Vb>& pts)
+{
+    const PtrList<extendedFeatureEdgeMesh>& feMeshes
+    (
+        geometryToConformTo_.features()
+    );
+
+    forAll(feMeshes, i)
+    {
+        Info<< indent << "Edge mesh = " << feMeshes[i].name() << nl << endl;
+
+        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
+
+        for
+        (
+            label ptI = feMesh.convexStart();
+            ptI < feMesh.mixedStart();
+            ptI++
+        )
+        {
+            createMasterAndSlavePoints(feMesh, ptI, pts);
+        }
+    }
+}
+
+
+//Foam::scalar Foam::conformalVoronoiMesh::pyramidVolume
+//(
+//    const Foam::point& apex,
+//    const Foam::point& a,
+//    const Foam::point& b,
+//    const Foam::point& c,
+//    const bool printInfo
+//) const
+//{
+//    triPointRef tri(a, b, c);
+//
+//    tetPointRef tet(tri.a(), tri.b(), tri.c(), apex);
+//
+//    scalar volume = tet.mag();
+//
+////    scalar volume = (1.0/3.0)*constant::mathematical::pi;
+////
+////    K::Circle_3 circle(toPoint(a), toPoint(b), toPoint(c));
+////
+////    scalar height = mag(topoint(circle.center()) - apex);
+////
+////    volume *= circle.squared_radius()*height;
+//
+//    if (printInfo)
+//    {
+//        Info<< "Calculating volume of pyramid..." << nl
+//            << "    Apex      : " << apex << nl
+//            << "    Point a   : " << a << nl
+//            << "    Point b   : " << b << nl
+//            << "    Point c   : " << c << nl
+//            << "        Center  : " << tri.centre() << nl
+//            << "        Volume  : " << volume << endl;
+//    }
+//
+//    return volume;
+//}
+
+
+//void Foam::conformalVoronoiMesh::createPyramidMasterPoint
+//(
+//    const Foam::point& apex,
+//    const vectorField& edgeDirections,
+//    Foam::point& masterPoint,
+//    vectorField& norms
+//) const
+//{
+//    pointField basePoints(edgeDirections.size() + 1);
+//
+//    forAll(edgeDirections, eI)
+//    {
+//        basePoints[eI] = edgeDirections[eI] + apex;
+//    }
+//
+//    basePoints[edgeDirections.size() + 1] = apex;
+//
+//    face f(identity(edgeDirections.size()));
+//
+//    pyramidPointFaceRef p(f, apex);
+//
+//    const scalar ppDist = pointPairDistance(apex);
+//
+//
+//    vector unitDir = f.centre();
+//    unitDir /= mag(unitDir);
+//
+//    masterPoint = apex + ppDist*unitDir;
+//
+//    norms.setSize(edgeDirections.size());
+//
+//    forAll(norms, nI)
+//    {
+//        norms[nI] =
+//    }
+//}
+
+
+//void Foam::conformalVoronoiMesh::createConvexConcaveFeaturePoints
+//(
+//    DynamicList<Foam::point>& pts,
+//    DynamicList<label>& indices,
+//    DynamicList<label>& types
+//)
+//{
+//    const PtrList<extendedFeatureEdgeMesh>& feMeshes
+//    (
+//        geometryToConformTo_.features()
+//    );
+//
+//    forAll(feMeshes, i)
+//    {
+//        const extendedFeatureEdgeMesh& feMesh(feMeshes[i]);
+//
+//        for
+//        (
+//            label ptI = feMesh.convexStart();
+//            ptI < feMesh.mixedStart();
+//            ptI++
+//        )
+//        {
+//            const Foam::point& apex = feMesh.points()[ptI];
+//
+//            if (!positionOnThisProc(apex))
+//            {
+//                continue;
+//            }
+//
+//            const vectorField& featPtEdgeDirections
+//                = feMesh.featurePointEdgeDirections(ptI);
+//
+//            Foam::point masterPoint;
+//            vectorField tetNorms;
+//
+//            createPyramidMasterPoint
+//            (
+//                apex,
+//                featPtEdgeDirections,
+//                masterPoint,
+//                tetNorms
+//            );
+//
+//
+//
+//            // Result when the points are eventually inserted (example n = 4)
+//            // Add number_of_vertices() at insertion of first vertex to all
+//            // numbers:
+//            // pt           index type
+//            // internalPt   0     1
+//            // externalPt0  1     0
+//            // externalPt1  2     0
+//            // externalPt2  3     0
+//            // externalPt3  4     0
+//
+//            // Result when the points are eventually inserted (example n = 5)
+//            // Add number_of_vertices() at insertion of first vertex to all
+//            // numbers:
+//            // pt           index type
+//            // internalPt0  0     5
+//            // internalPt1  1     5
+//            // internalPt2  2     5
+//            // internalPt3  3     5
+//            // internalPt4  4     5
+//            // externalPt   5     4
+//
+//            if (geometryToConformTo_.inside(masterPoint))
+//            {
+//
+//            }
+//            else
+//            {
+//
+//            }
+//
+//            pts.append(masterPoint);
+//            indices.append(0);
+//            types.append(1);
+//
+//            label internalPtIndex = -1;
+//
+//            forAll(tetNorms, nI)
+//            {
+//                const vector& n = tetNorms[nI];
+//
+//                Foam::point reflectedPoint
+//                    = reflectPoint(featPt, masterPoint, n);
+//
+//                pts.append(reflectedPoint);
+//                indices.append(0);
+//                types.append(internalPtIndex--);
+//            }
+//        }
+//    }
+//}
+
+
+Foam::vector Foam::conformalVoronoiMesh::sharedFaceNormal
+(
+    const extendedFeatureEdgeMesh& feMesh,
+    const label edgeI,
+    const label nextEdgeI
+) const
+{
+    const labelList& edgeInormals = feMesh.edgeNormals()[edgeI];
+    const labelList& nextEdgeInormals = feMesh.edgeNormals()[nextEdgeI];
+
+    const vector& A1 = feMesh.normals()[edgeInormals[0]];
+    const vector& A2 = feMesh.normals()[edgeInormals[1]];
+
+    const vector& B1 = feMesh.normals()[nextEdgeInormals[0]];
+    const vector& B2 = feMesh.normals()[nextEdgeInormals[1]];
+
+    const scalar A1B1 = mag(A1 ^ B1);
+    const scalar A1B2 = mag(A1 ^ B2);
+    const scalar A2B1 = mag(A2 ^ B1);
+    const scalar A2B2 = mag(A2 ^ B2);
+
+    if (A1B1 < A1B2 && A1B1 < A2B1 && A1B1 < A2B2)
+    {
+        return 0.5*(A1 + B1);
+    }
+    else if (A1B2 < A1B1 && A1B2 < A2B1 && A1B2 < A2B2)
+    {
+        return 0.5*(A1 + B2);
+    }
+    else if (A2B1 < A1B1 && A2B1 < A1B2 && A2B1 < A2B2)
+    {
+        return 0.5*(A2 + B1);
+    }
+    else
+    {
+        return 0.5*(A2 + B2);
+    }
+}
+
+
+Foam::List<Foam::point> Foam::conformalVoronoiMesh::reflectPointInPlanes
+(
+    const Foam::point p,
+    const DynamicList<autoPtr<plane> >& planes
+) const
+{
+    List<Foam::point> reflectedPoints(planes.size());
+
+    forAll(planes, planeI)
+    {
+        reflectedPoints[planeI] = reflectPointInPlane(p, planes[planeI]());
+    }
+
+    return reflectedPoints;
+}
+
+
+Foam::point Foam::conformalVoronoiMesh::reflectPointInPlane
+(
+    const Foam::point p,
+    const plane& planeN
+) const
+{
+    const vector reflectedPtDir = p - planeN.nearestPoint(p);
+
+    if ((planeN.normal() & reflectedPtDir) > 0)
+    {
+        return p - 2.0*planeN.distance(p)*planeN.normal();
+    }
+    else
+    {
+        return p + 2.0*planeN.distance(p)*planeN.normal();
+    }
+}
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshI.H
index 43d8c077fc785724ad83b37ac8e48a7a76f77ba9..7d664407dcb357815ebba50111fe17677e374573 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshI.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshI.H
@@ -21,21 +21,28 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 \*---------------------------------------------------------------------------*/
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+inline Foam::scalar Foam::conformalVoronoiMesh::defaultCellSize() const
+{
+    return readScalar
+    (
+        cvMeshControls().cvMeshDict().subDict("motionControl").lookup
+        (
+            "defaultCellSize"
+        )
+    );
+}
+
+
 inline Foam::scalar Foam::conformalVoronoiMesh::targetCellSize
 (
     const Foam::point& pt
 ) const
 {
-    return cellSizeControl().cellSize(pt);
+    return cellShapeControls().cellSize(pt);
 }
 
 
@@ -66,8 +73,8 @@ inline Foam::scalar Foam::conformalVoronoiMesh::averageAnyCellSize
 {
     if
     (
-        !vA->internalOrBoundaryPoint()
-     && !vB->internalOrBoundaryPoint()
+        (!vA->internalOrBoundaryPoint() || vA->referred())
+     && (!vB->internalOrBoundaryPoint() || vB->referred())
     )
     {
         // There are no internalOrBoundaryPoints available, determine
@@ -80,11 +87,11 @@ inline Foam::scalar Foam::conformalVoronoiMesh::averageAnyCellSize
            *targetCellSize(topoint(vB->point()))
         );
     }
-    else if (!vB->internalOrBoundaryPoint())
+    else if (!vB->internalOrBoundaryPoint() || vB->referred())
     {
         return vA->targetCellSize();
     }
-    else if (!vA->internalOrBoundaryPoint())
+    else if (!vA->internalOrBoundaryPoint() || vA->referred())
     {
         return vB->targetCellSize();
     }
@@ -98,9 +105,10 @@ inline Foam::scalar Foam::conformalVoronoiMesh::averageAnyCellSize
     const Delaunay::Finite_facets_iterator& fit
 ) const
 {
-    // Geometric mean
+    // Arithmetic mean
+
+    scalar sizeSum = 0;
 
-    scalar sizeProduct = 1;
     label nProducts = 0;
 
     const Cell_handle c(fit->first);
@@ -110,10 +118,10 @@ inline Foam::scalar Foam::conformalVoronoiMesh::averageAnyCellSize
     {
         Vertex_handle v = c->vertex(vertex_triple_index(oppositeVertex, i));
 
-        if (v->internalOrBoundaryPoint())
+        if (v->internalOrBoundaryPoint() && !v->referred())
         {
 
-            sizeProduct *= v->targetCellSize();
+            sizeSum += v->targetCellSize();
 
             nProducts++;
         }
@@ -128,13 +136,22 @@ inline Foam::scalar Foam::conformalVoronoiMesh::averageAnyCellSize
         {
             Vertex_handle v = c->vertex(vertex_triple_index(oppositeVertex, i));
 
-            sizeProduct *= targetCellSize(topoint(v->point()));
+            sizeSum += targetCellSize(topoint(v->point()));
         }
 
         nProducts = 3;
     }
 
-    return pow(sizeProduct, (1.0/nProducts));
+    if (sizeSum < 0)
+    {
+        WarningIn("averageAnyCellSize(const Delaunay::Finite_facets_iterator&)")
+            << "sizeSum = " << sizeSum
+            << endl;
+
+        return 0;
+    }
+
+    return pow(sizeSum, (1.0/nProducts));
 }
 
 
@@ -219,125 +236,155 @@ inline Foam::scalar Foam::conformalVoronoiMesh::maxSurfaceProtrusion
 }
 
 
-inline Foam::label Foam::conformalVoronoiMesh::insertPoint
+inline bool Foam::conformalVoronoiMesh::insertPoint
 (
     const Foam::point& p,
-    const label type
+    const indexedVertexEnum::vertexType type
 )
 {
-    return insertPoint(toPoint(p), type);
+    return insertPoint(toPoint<Point>(p), type);
 }
 
 
-inline Foam::label Foam::conformalVoronoiMesh::insertPoint
+inline bool Foam::conformalVoronoiMesh::insertPoint
 (
     const Point& P,
-    const label type
+    const indexedVertexEnum::vertexType type
 )
 {
     uint nVert = number_of_vertices();
 
     Vertex_handle vh = insert(P);
 
+    bool pointInserted = true;
+
     if (nVert == number_of_vertices())
     {
-        Pout << "Failed to insert point " << topoint(P) << endl;
+        Pout<< "Failed to insert point : " << topoint(P)
+            << " of type " << type << endl;
+        pointInserted = false;
     }
     else
     {
-        vh->index() = nVert;
+        vh->index() = getNewVertexIndex();
         vh->type() = type;
     }
 
-    return vh->index();
+    return pointInserted;
 }
 
 
-inline void Foam::conformalVoronoiMesh::insertPoint
+inline bool Foam::conformalVoronoiMesh::insertReferredPoint(const Vb& P)
+{
+    return insertReferredPoint(P.point(), P.index(), P.type(), P.procIndex());
+}
+
+
+inline bool Foam::conformalVoronoiMesh::insertReferredPoint
 (
     const Foam::point& p,
     const label index,
-    const label type
+    const indexedVertexEnum::vertexType type,
+    const label processor
 )
 {
-    insertPoint(toPoint(p), index, type);
+    return insertReferredPoint(toPoint<Point>(p), index, type, processor);
 }
 
 
-inline void Foam::conformalVoronoiMesh::insertPoint
+inline bool Foam::conformalVoronoiMesh::insertReferredPoint
 (
     const Point& P,
     const label index,
-    const label type
+    const indexedVertexEnum::vertexType type,
+    const label processor
 )
 {
     uint nVert = number_of_vertices();
 
     Vertex_handle vh = insert(P);
 
+    bool pointInserted = true;
+
     if (nVert == number_of_vertices())
     {
-        Pout << "Failed to insert point " << topoint(P) << endl;
+        Pout<< "Failed to insert point " << topoint(P)
+            << " type: " << type << " index: " << index
+            << " proc: " << processor << endl;
+        pointInserted = false;
     }
     else
     {
         vh->index() = index;
         vh->type() = type;
+        vh->procIndex() = processor;
     }
+
+    return pointInserted;
 }
 
 
-inline void Foam::conformalVoronoiMesh::insertPointPair
+inline void Foam::conformalVoronoiMesh::createPointPair
 (
     const scalar ppDist,
     const Foam::point& surfPt,
-    const vector& n
+    const vector& n,
+    DynamicList<Vb>& pts
 )
 {
-    Pout<< "insertPointPair is depricated, "
-        << " it does not check parallel insertion." << endl;
-
     vector ppDistn = ppDist*n;
 
-    label master = insertPoint
+    pts.append
     (
-        surfPt - ppDistn,
-        number_of_vertices() + 1
+        Vb(surfPt - ppDistn, Vb::vtInternalSurface)
     );
 
-    insertPoint(surfPt + ppDistn, master);
+    pts.append
+    (
+        Vb(surfPt + ppDistn, Vb::vtExternalSurface)
+    );
 }
 
 
-inline void Foam::conformalVoronoiMesh::createPointPair
+inline Foam::point Foam::conformalVoronoiMesh::perturbPoint
+(
+    const Foam::point& pt
+) const
+{
+    Foam::point perturbedPt(pt);
+
+//    vector delta(xR/ni, yR/nj, zR/nk);
+//    scalar pert = randomPerturbationCoeff*cmptMin(delta);
+
+    scalar pert = 1e-12*defaultCellSize();
+
+    perturbedPt.x() += pert*(rndGen_.scalar01() - 0.5);
+    perturbedPt.y() += pert*(rndGen_.scalar01() - 0.5);
+    perturbedPt.z() += pert*(rndGen_.scalar01() - 0.5);
+
+    return perturbedPt;
+}
+
+
+inline void Foam::conformalVoronoiMesh::createBafflePointPair
 (
     const scalar ppDist,
     const Foam::point& surfPt,
     const vector& n,
-    DynamicList<Foam::point>& pts,
-    DynamicList<label>& indices,
-    DynamicList<label>& types
+    DynamicList<Vb>& pts
 )
 {
     vector ppDistn = ppDist*n;
 
-    // Result when the points are eventually inserted.
-    // Add number_of_vertices() at insertion of first vertex to all numbers:
-    // pt               index type
-    // surfPt - ppDistn 0     1
-    // surfPt + ppDistn 1     0
-
-    // Master, index = number_of_vertices(), type = number_of_vertices() + 1
-    pts.append(surfPt - ppDistn);
-    indices.append(0);
-    types.append(1);
+    pts.append
+    (
+        Vb(surfPt - ppDistn, Vb::vtInternalSurface)
+    );
 
-    // Slave, index = number_of_vertices()(new) + 1, type = index of master.
-    // This will be inserted after the master, so number_of_vertices() will
-    // have increased
-    pts.append(surfPt + ppDistn);
-    indices.append(0);
-    types.append(-1);
+    pts.append
+    (
+        Vb(surfPt + ppDistn, Vb::vtInternalSurface)
+    );
 }
 
 
@@ -350,13 +397,30 @@ inline bool Foam::conformalVoronoiMesh::isBoundaryDualFace
     Vertex_handle vA = c->vertex(eit->second);
     Vertex_handle vB = c->vertex(eit->third);
 
+//    if (vA->internalBoundaryPoint() && vB->externalBoundaryPoint())
+//    {
+//        if (vA->index() == vB->index() - 1)
+//        {
+//            return true;
+//        }
+//    }
+//    else if (vA->externalBoundaryPoint() && vB->internalBoundaryPoint())
+//    {
+//        if (vA->index() == vB->index() + 1)
+//        {
+//            return true;
+//        }
+//    }
+//
+//    return false;
+
     // A dual face on the boundary will result from one Dv inside and
     // one outside
     return
     (
         (
-            vA->internalOrBoundaryPoint()
-         || vB->internalOrBoundaryPoint()
+            (vA->internalOrBoundaryPoint() && !vA->referred())
+         || (vB->internalOrBoundaryPoint() && !vB->referred())
         )
      && (
             !vA->internalOrBoundaryPoint()
@@ -458,58 +522,35 @@ inline bool Foam::conformalVoronoiMesh::isParallelDualEdge
 }
 
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-#ifdef CGAL_INEXACT
-
-inline Foam::conformalVoronoiMesh::pointFromPoint
-Foam::conformalVoronoiMesh::topoint
+inline bool Foam::conformalVoronoiMesh::isProcBoundaryEdge
 (
-    const Point& P
-) const
-{
-    return reinterpret_cast<pointFromPoint>(P);
-}
-
-
-inline Foam::conformalVoronoiMesh::PointFrompoint
-Foam::conformalVoronoiMesh::toPoint
-(
-    const Foam::point& p
+    const Delaunay::Finite_edges_iterator& eit
 ) const
 {
-    return reinterpret_cast<PointFrompoint>(p);
-}
-
-#else
+    bool isProcBoundaryEdge = false;
 
+    Cell_handle c = eit->first;
+    Vertex_handle vA = c->vertex(eit->second);
+    Vertex_handle vB = c->vertex(eit->third);
 
-inline Foam::conformalVoronoiMesh::pointFromPoint
-Foam::conformalVoronoiMesh::topoint
-(
-    const Point& P
-) const
-{
-    return Foam::point
+    if
     (
-        CGAL::to_double(P.x()),
-        CGAL::to_double(P.y()),
-        CGAL::to_double(P.z())
-    );
-}
-
+        (
+            (vA->referred() && !vB->referred())
+         || (vB->referred() && !vA->referred())
+        )
+     && vA->internalOrBoundaryPoint()
+     && vB->internalOrBoundaryPoint()
+    )
+    {
+        isProcBoundaryEdge = true;
+    }
 
-inline Foam::conformalVoronoiMesh::PointFrompoint
-Foam::conformalVoronoiMesh::toPoint
-(
-    const Foam::point& p
-) const
-{
-    return Point(p.x(), p.y(), p.z());
+    return isProcBoundaryEdge;
 }
 
-#endif
 
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 inline Foam::conformalVoronoiMesh::CGALVector
 Foam::conformalVoronoiMesh::toCGALVector(const Foam::vector& v) const
@@ -562,10 +603,10 @@ Foam::conformalVoronoiMesh::decomposition() const
 }
 
 
-inline const Foam::cellSizeControlSurfaces&
-Foam::conformalVoronoiMesh::cellSizeControl() const
+inline const Foam::cellShapeControl&
+Foam::conformalVoronoiMesh::cellShapeControls() const
 {
-    return cellSizeControl_;
+    return cellShapeControl_;
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C
index 68f98e8a9d3e01cf1238bd3817f403b6109fbe84..f21ef34adc64652c5576b99dd48691dd20ab3083 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C
@@ -28,6 +28,11 @@ License
 #include "OFstream.H"
 #include "pointMesh.H"
 #include "pointFields.H"
+#include "ListOps.H"
+#include "polyMeshFilter.H"
+#include "polyTopoChange.H"
+#include "PrintTable.H"
+#include "pointMesh.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
@@ -57,61 +62,185 @@ void Foam::conformalVoronoiMesh::timeCheck
 
         if (m.valid())
         {
-            label mSize = m.size();
-            label mPeak = m.peak();
-            label mRss = m.rss();
+            PrintTable<word, label> memoryTable("Memory Usage (kB)");
+
+            memoryTable.add("mSize", m.size());
+            memoryTable.add("mPeak", m.peak());
+            memoryTable.add("mRss", m.rss());
+
+            Info<< incrIndent;
+            memoryTable.print(Info);
+            Info<< decrIndent;
+        }
+    }
+}
 
-            if (Pstream::parRun())
+
+void Foam::conformalVoronoiMesh::printVertexInfo() const
+{
+    label nInternal = 0;
+    label nInternalRef = 0;
+    label nUnassigned = 0;
+    label nUnassignedRef = 0;
+    label nInternalNearBoundary = 0;
+    label nInternalNearBoundaryRef = 0;
+    label nInternalSurface = 0;
+    label nInternalSurfaceRef = 0;
+    label nInternalFeatureEdge = 0;
+    label nInternalFeatureEdgeRef = 0;
+    label nInternalFeaturePoint = 0;
+    label nInternalFeaturePointRef = 0;
+    label nExternalSurface = 0;
+    label nExternalSurfaceRef = 0;
+    label nExternalFeatureEdge = 0;
+    label nExternalFeatureEdgeRef = 0;
+    label nExternalFeaturePoint = 0;
+    label nExternalFeaturePointRef = 0;
+    label nFar = 0;
+    label nReferred = 0;
+
+    for
+    (
+        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
+        vit != finite_vertices_end();
+        ++vit
+    )
+    {
+        if (vit->type() == Vb::vtInternal)
+        {
+            if (vit->referred())
             {
-                labelList allMSize(Pstream::nProcs());
-                labelList allMPeak(Pstream::nProcs());
-                labelList allMRss(Pstream::nProcs());
-
-                allMSize[Pstream::myProcNo()] = mSize;
-                allMPeak[Pstream::myProcNo()] = mPeak;
-                allMRss[Pstream::myProcNo()] = mRss;
-
-                Pstream::gatherList(allMSize);
-                Pstream::gatherList(allMPeak);
-                Pstream::gatherList(allMRss);
-
-                Info<< "--- [ "
-                    << "mem (kB) " << tab
-                    << "size" << tab
-                    << "peak" << tab
-                    << "rss"
-                    << " ] --- " << endl;
-
-                forAll(allMSize, procI)
-                {
-                    Info<< "--- [ "
-                        << procI << " " << tab
-                        << allMSize[procI] << tab
-                        << allMPeak[procI] << tab
-                        << allMRss[procI]
-                        << " ] --- " << endl;
-                }
+                nReferred++;
+                nInternalRef++;
+            }
+
+            nInternal++;
+        }
+        else if (vit->type() == Vb::vtUnassigned)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nUnassignedRef++;
+            }
+
+            nUnassigned++;
+        }
+        else if (vit->type() == Vb::vtInternalNearBoundary)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nInternalNearBoundaryRef++;
+            }
+
+            nInternalNearBoundary++;
+        }
+        else if (vit->type() == Vb::vtInternalSurface)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nInternalSurfaceRef++;
+            }
+
+            nInternalSurface++;
+        }
+        else if (vit->type() == Vb::vtInternalFeatureEdge)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nInternalFeatureEdgeRef++;
+            }
+
+            nInternalFeatureEdge++;
+        }
+        else if (vit->type() == Vb::vtInternalFeaturePoint)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nInternalFeaturePointRef++;
+            }
 
-                Info<< "--- [ "
-                    << "sum " << tab
-                    << sum(allMSize) << tab
-                    << sum(allMPeak) << tab
-                    << sum(allMRss)
-                    << " ] --- " << endl;
+            nInternalFeaturePoint++;
+        }
+        else if (vit->type() == Vb::vtExternalSurface)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nExternalSurfaceRef++;
+            }
 
+            nExternalSurface++;
+        }
+        else if (vit->type() == Vb::vtExternalFeatureEdge)
+        {
+            if (vit->referred())
+            {
+                nReferred++;
+                nExternalFeatureEdgeRef++;
             }
-            else
+
+            nExternalFeatureEdge++;
+        }
+        else if (vit->type() == Vb::vtExternalFeaturePoint)
+        {
+            if (vit->referred())
             {
-                Info<< "--- [ "
-                    << "mem size " << mSize << " kB, "
-                    << "mem peak " << mPeak << " kB, "
-                    << "mem rss " << mRss << " kB"
-                    << " ] --- " << endl;
+                nReferred++;
+                nExternalFeaturePointRef++;
             }
+
+            nExternalFeaturePoint++;
+        }
+        else if (vit->type() == Vb::vtFar)
+        {
+            nFar++;
         }
     }
+
+    label nTotalVertices
+        = nUnassigned
+        + nInternal
+        + nInternalNearBoundary
+        + nInternalSurface
+        + nInternalFeatureEdge
+        + nInternalFeaturePoint
+        + nExternalSurface
+        + nExternalFeatureEdge
+        + nExternalFeaturePoint
+        + nFar;
+
+    if (nTotalVertices != label(number_of_vertices()))
+    {
+        WarningIn("Foam::conformalVoronoiMesh::printVertexInfo()")
+            << nTotalVertices << " does not equal " << number_of_vertices()
+            << endl;
+    }
+
+    PrintTable<word, label> vertexTable("Vertex Type Information");
+
+    vertexTable.add("Total", nTotalVertices);
+    vertexTable.add("Unassigned", nUnassigned);
+    vertexTable.add("nInternal", nInternal);
+    vertexTable.add("nInternalNearBoundary", nInternalNearBoundary);
+    vertexTable.add("nInternalSurface", nInternalSurface);
+    vertexTable.add("nInternalFeatureEdge", nInternalFeatureEdge);
+    vertexTable.add("nInternalFeaturePoint", nInternalFeaturePoint);
+    vertexTable.add("nExternalSurface", nExternalSurface);
+    vertexTable.add("nExternalFeatureEdge", nExternalFeatureEdge);
+    vertexTable.add("nExternalFeaturePoint", nExternalFeaturePoint);
+    vertexTable.add("nFar", nFar);
+    vertexTable.add("nReferred", nReferred);
+
+    Info<< endl;
+    vertexTable.print(Info);
 }
 
+
 void Foam::conformalVoronoiMesh::drawDelaunayCell
 (
     Ostream& os,
@@ -120,7 +249,7 @@ void Foam::conformalVoronoiMesh::drawDelaunayCell
 ) const
 {
     // Supply offset as tet number
-    offset *= 5;
+    offset *= 4;
 
     os  << "# cell index: " << label(c->cellIndex()) << endl;
 
@@ -130,9 +259,10 @@ void Foam::conformalVoronoiMesh::drawDelaunayCell
 
     for (int i = 0; i < 4; i++)
     {
-        os  << "# index type: "
+        os  << "# index / type / procIndex: "
             << label(c->vertex(i)->index()) << " "
-            << label(c->vertex(i)->type()) << endl;
+            << label(c->vertex(i)->type()) << " "
+            << label(c->vertex(i)->procIndex()) << endl;
 
         meshTools::writeOBJ(os, topoint(c->vertex(i)->point()));
     }
@@ -142,23 +272,39 @@ void Foam::conformalVoronoiMesh::drawDelaunayCell
         << "f " << 1 + offset << " " << 4 + offset << " " << 3 + offset << nl
         << "f " << 1 + offset << " " << 2 + offset << " " << 4 + offset << endl;
 
-    os  << "# cicumcentre " << endl;
+//    os  << "# cicumcentre " << endl;
 
-    meshTools::writeOBJ(os, c->dual());
+//    meshTools::writeOBJ(os, c->dual());
 
-    os  << "l " << 1 + offset << " " << 5 + offset << endl;
+//    os  << "l " << 1 + offset << " " << 5 + offset << endl;
 }
 
 
 void Foam::conformalVoronoiMesh::writePoints
 (
     const fileName& fName,
-    bool internalOnly
+    const Foam::indexedVertexEnum::vertexType startPointType,
+    const Foam::indexedVertexEnum::vertexType endPointType
 ) const
 {
     OFstream str(runTime_.path()/fName);
 
-    Pout<< nl << "Writing points to " << str.name() << endl;
+    Pout<< nl << "Writing points of types:" << nl;
+
+    forAllConstIter
+    (
+        HashTable<int>,
+        Foam::indexedVertexEnum::vertexTypeNames_,
+        iter
+    )
+    {
+        if (iter() >= startPointType && iter() <= endPointType)
+        {
+            Pout<< "    " << iter.key() << nl;
+        }
+    }
+
+    Pout<< "to " << str.name() << endl;
 
     for
     (
@@ -167,7 +313,7 @@ void Foam::conformalVoronoiMesh::writePoints
         ++vit
     )
     {
-        if (!internalOnly || vit->internalPoint())
+        if (vit->type() >= startPointType && vit->type() <= endPointType)
         {
             meshTools::writeOBJ(str, topoint(vit->point()));
         }
@@ -175,6 +321,16 @@ void Foam::conformalVoronoiMesh::writePoints
 }
 
 
+void Foam::conformalVoronoiMesh::writePoints
+(
+    const fileName& fName,
+    const Foam::indexedVertexEnum::vertexType pointType
+) const
+{
+    writePoints(fName, pointType, pointType);
+}
+
+
 void Foam::conformalVoronoiMesh::writeBoundaryPoints
 (
     const fileName& fName
@@ -220,6 +376,27 @@ void Foam::conformalVoronoiMesh::writePoints
 }
 
 
+void Foam::conformalVoronoiMesh::writePoints
+(
+    const fileName& fName,
+    const List<Vb>& points
+) const
+{
+    if (points.size())
+    {
+        OFstream str(runTime_.path()/fName);
+
+        Pout<< nl << "Writing " << points.size() << " points from pointList to "
+            << str.name() << endl;
+
+        forAll(points, p)
+        {
+            meshTools::writeOBJ(str, topoint(points[p].point()));
+        }
+    }
+}
+
+
 void Foam::conformalVoronoiMesh::writeProcessorInterface
 (
     const fileName& fName,
@@ -228,9 +405,7 @@ void Foam::conformalVoronoiMesh::writeProcessorInterface
 {
     OFstream str(runTime_.path()/fName);
 
-    Pout<< "Writing processor interface" << endl;
-
-    pointField points(number_of_cells(), point::max);
+    pointField points(number_of_finite_cells(), point::max);
 
     for
     (
@@ -239,15 +414,13 @@ void Foam::conformalVoronoiMesh::writeProcessorInterface
         ++cit
     )
     {
-        if (!cit->farCell())
+        if (!cit->hasFarPoint())
         {
             points[cit->cellIndex()] = cit->dual();
         }
     }
 
     meshTools::writeOBJ(str, faces, points);
-
-    Pout<< "Written processor interface" << endl;
 }
 
 
@@ -297,11 +470,7 @@ void Foam::conformalVoronoiMesh::writeInternalDelaunayVertices
 }
 
 
-void Foam::conformalVoronoiMesh::writeMesh
-(
-    const fileName& instance,
-    bool filterFaces
-)
+void Foam::conformalVoronoiMesh::writeMesh(const fileName& instance)
 {
     writeInternalDelaunayVertices(instance);
 
@@ -314,6 +483,7 @@ void Foam::conformalVoronoiMesh::writeMesh
 
     {
         pointField points;
+        labelList boundaryPts(number_of_finite_cells(), -1);
         faceList faces;
         labelList owner;
         labelList neighbour;
@@ -323,9 +493,12 @@ void Foam::conformalVoronoiMesh::writeMesh
         labelList procNeighbours;
         pointField cellCentres;
 
+        PackedBoolList boundaryFacesToRemove;
+
         calcDualMesh
         (
             points,
+            boundaryPts,
             faces,
             owner,
             neighbour,
@@ -337,7 +510,7 @@ void Foam::conformalVoronoiMesh::writeMesh
             cellCentres,
             cellToDelaunayVertex,
             patchToDelaunayVertex,
-            filterFaces
+            boundaryFacesToRemove
         );
 
         Info<< nl << "Writing polyMesh to " << instance << endl;
@@ -347,6 +520,7 @@ void Foam::conformalVoronoiMesh::writeMesh
             Foam::polyMesh::defaultRegion,
             instance,
             points,
+            boundaryPts,
             faces,
             owner,
             neighbour,
@@ -355,12 +529,11 @@ void Foam::conformalVoronoiMesh::writeMesh
             patchSizes,
             dualPatchStarts,
             procNeighbours,
-            cellCentres
+            cellCentres,
+            boundaryFacesToRemove
         );
     }
 
-
-
     if (cvMeshControls().writeTetDualMesh())
     {
         // Determine map from Delaunay vertex to Dual mesh
@@ -389,6 +562,7 @@ void Foam::conformalVoronoiMesh::writeMesh
         forAll(patchToDelaunayVertex, patchI)
         {
             const labelList& patchVertices = patchToDelaunayVertex[patchI];
+
             forAll(patchVertices, i)
             {
                 label vertI = patchVertices[i];
@@ -416,6 +590,7 @@ void Foam::conformalVoronoiMesh::writeMesh
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
         pointField points;
+        labelList boundaryPts(number_of_finite_cells(), -1);
         // From tet point back to Delaunay vertex index
         labelList pointToDelaunayVertex;
         faceList faces;
@@ -541,23 +716,24 @@ void Foam::conformalVoronoiMesh::writeMesh
 
         labelList procNeighbours(patchNames.size(), -1);
 
-        Info<< nl << "Writing tetDualMesh to " << instance << endl;
-
-        writeMesh
-        (
-            "tetDualMesh",
-            instance,
-            points,
-            faces,
-            owner,
-            neighbour,
-            patchTypes,
-            patchNames,
-            patchSizes,
-            patchStarts,
-            procNeighbours,
-            cellCentres
-        );
+//        Info<< nl << "Writing tetDualMesh to " << instance << endl;
+
+//        writeMesh
+//        (
+//            "tetDualMesh",
+//            instance,
+//            points,
+//            boundaryPts,
+//            faces,
+//            owner,
+//            neighbour,
+//            patchTypes,
+//            patchNames,
+//            patchSizes,
+//            patchStarts,
+//            procNeighbours,
+//            cellCentres
+//        );
     }
 }
 
@@ -598,7 +774,8 @@ Foam::autoPtr<Foam::fvMesh> Foam::conformalVoronoiMesh::createDummyMesh
                 patchI,
                 mesh.boundaryMesh(),
                 Pstream::myProcNo(),
-                procNeighbours[patchI]
+                procNeighbours[patchI],
+                coupledPolyPatch::COINCIDENTFULLMATCH
             );
         }
         else
@@ -620,6 +797,122 @@ Foam::autoPtr<Foam::fvMesh> Foam::conformalVoronoiMesh::createDummyMesh
 }
 
 
+void Foam::conformalVoronoiMesh::checkProcessorPatchesMatch
+(
+    const wordList& patchTypes,
+    const labelList& patchSizes,
+    const labelList& procNeighbours
+) const
+{
+    // Check patch sizes
+    labelListList procPatchSizes
+    (
+        Pstream::nProcs(),
+        labelList(Pstream::nProcs(), -1)
+    );
+
+    forAll(patchTypes, patchI)
+    {
+        if (patchTypes[patchI] == processorPolyPatch::typeName)
+        {
+            procPatchSizes[Pstream::myProcNo()][procNeighbours[patchI]]
+                = patchSizes[patchI];
+        }
+    }
+
+    Pstream::gatherList(procPatchSizes);
+
+    if (Pstream::master())
+    {
+        bool allMatch = true;
+
+        forAll(procPatchSizes, procI)
+        {
+            const labelList& patchSizes = procPatchSizes[procI];
+
+            forAll(patchSizes, patchI)
+            {
+                if (patchSizes[patchI] != procPatchSizes[patchI][procI])
+                {
+                    allMatch = false;
+
+                    Info<< indent << "Patches " << procI << " and " << patchI
+                        << " have different sizes: " << patchSizes[patchI]
+                        << " and " << procPatchSizes[patchI][procI] << endl;
+                }
+            }
+        }
+
+        if (allMatch)
+        {
+            Info<< indent << "All processor patches have matching numbers of "
+                << "faces" << endl;
+        }
+    }
+}
+
+
+void Foam::conformalVoronoiMesh::reorderPoints
+(
+    pointField& points,
+    labelList& boundaryPts,
+    faceList& faces,
+    const label nInternalFaces
+) const
+{
+    Info<< incrIndent << indent << "Reordering points into internal/external"
+        << endl;
+
+    labelList oldToNew(points.size(), 0);
+
+    // Find points that are internal
+    for (label fI = nInternalFaces; fI < faces.size(); ++fI)
+    {
+        const face& f = faces[fI];
+
+        forAll(f, fpI)
+        {
+            oldToNew[f[fpI]] = 1;
+        }
+    }
+
+    const label nInternalPoints = points.size() - sum(oldToNew);
+
+    label countInternal = 0;
+    label countExternal = nInternalPoints;
+
+    forAll(points, pI)
+    {
+        if (oldToNew[pI] == 0)
+        {
+            oldToNew[pI] = countInternal++;
+        }
+        else
+        {
+            oldToNew[pI] = countExternal++;
+        }
+    }
+
+    Info<< indent
+        << "Number of internal points: " << countInternal << nl
+        << indent << "Number of external points: " << countExternal
+        << decrIndent << endl;
+
+    inplaceReorder(oldToNew, points);
+    inplaceReorder(oldToNew, boundaryPts);
+
+    forAll(faces, fI)
+    {
+        face& f = faces[fI];
+
+        forAll(f, fpI)
+        {
+            f[fpI] = oldToNew[f[fpI]];
+        }
+    }
+}
+
+
 void Foam::conformalVoronoiMesh::reorderProcessorPatches
 (
     const word& meshName,
@@ -633,6 +926,11 @@ void Foam::conformalVoronoiMesh::reorderProcessorPatches
     const labelList& procNeighbours
 ) const
 {
+    Info<< incrIndent << indent << "Reordering processor patches" << endl;
+
+    Info<< incrIndent;
+    checkProcessorPatchesMatch(patchTypes, patchSizes, procNeighbours);
+
     // Create dummy mesh with correct proc boundaries to do sorting
     autoPtr<fvMesh> sortMeshPtr
     (
@@ -656,8 +954,26 @@ void Foam::conformalVoronoiMesh::reorderProcessorPatches
     );
     const fvMesh& sortMesh = sortMeshPtr();
 
+    // Change the transform type on processors to coincident full match.
+//    forAll(sortMesh.boundaryMesh(), patchI)
+//    {
+//        const polyPatch& patch = sortMesh.boundaryMesh()[patchI];
+//
+//        if (isA<processorPolyPatch>(patch))
+//        {
+//            const processorPolyPatch& cpPatch
+//                = refCast<const processorPolyPatch>(patch);
+//
+//            processorPolyPatch& pPatch
+//                = const_cast<processorPolyPatch&>(cpPatch);
+//
+//            pPatch.transform() = coupledPolyPatch::COINCIDENTFULLMATCH;
+//        }
+//    }
+
     // Rotation on new faces.
-    labelList rotation(faces.size(), 0);
+    labelList rotation(faces.size(), -1);
+    labelList faceMap(faces.size(), -1);
 
     PstreamBuffers pBufs(Pstream::nonBlocking);
 
@@ -699,23 +1015,22 @@ void Foam::conformalVoronoiMesh::reorderProcessorPatches
             labelList patchFaceMap(patchSizes[patchI], -1);
             labelList patchFaceRotation(patchSizes[patchI], 0);
 
-            bool changed =
-                refCast<const processorPolyPatch>(pp).order
+            bool changed = refCast<const processorPolyPatch>(pp).order
+            (
+                pBufs,
+                primitivePatch
                 (
-                    pBufs,
-                    primitivePatch
+                    SubList<face>
                     (
-                        SubList<face>
-                        (
-                            faces,
-                            patchSizes[patchI],
-                            patchStarts[patchI]
-                        ),
-                        points
+                        faces,
+                        patchSizes[patchI],
+                        patchStarts[patchI]
                     ),
-                    patchFaceMap,
-                    patchFaceRotation
-                );
+                    points
+                ),
+                patchFaceMap,
+                patchFaceRotation
+            );
 
             if (changed)
             {
@@ -724,8 +1039,17 @@ void Foam::conformalVoronoiMesh::reorderProcessorPatches
 
                 forAll(patchFaceRotation, patchFaceI)
                 {
-                    rotation[patchFaceI + start] =
-                        patchFaceRotation[patchFaceI];
+                    rotation[patchFaceI + start]
+                        = patchFaceRotation[patchFaceI];
+                }
+
+                forAll(patchFaceMap, patchFaceI)
+                {
+                    if (patchFaceMap[patchFaceI] != patchFaceI)
+                    {
+                        faceMap[patchFaceI + start]
+                            = patchFaceMap[patchFaceI] + start;
+                    }
                 }
 
                 anyChanged = true;
@@ -738,13 +1062,26 @@ void Foam::conformalVoronoiMesh::reorderProcessorPatches
     if (anyChanged)
     {
         // Rotate faces (rotation is already in new face indices).
+        label nRotated = 0;
+
         forAll(rotation, faceI)
         {
+            if (rotation[faceI] == -1)
+            {
+                continue;
+            }
+
             if (rotation[faceI] != 0)
             {
-                faces[faceI] = faces[faceI].rotateFace(rotation[faceI]);
+                inplaceRotateList<List, label>(faces[faceI], rotation[faceI]);
+                nRotated++;
             }
         }
+
+        inplaceReorder(faceMap, faces);
+
+        Info<< indent << returnReduce(nRotated, sumOp<label>())
+            << " faces have been rotated" << decrIndent << decrIndent << endl;
     }
 }
 
@@ -754,6 +1091,7 @@ void Foam::conformalVoronoiMesh::writeMesh
     const word& meshName,
     const fileName& instance,
     pointField& points,
+    labelList& boundaryPts,
     faceList& faces,
     labelList& owner,
     labelList& neighbour,
@@ -762,7 +1100,8 @@ void Foam::conformalVoronoiMesh::writeMesh
     const labelList& patchSizes,
     const labelList& patchStarts,
     const labelList& procNeighbours,
-    const pointField& cellCentres
+    const pointField& cellCentres,
+    const PackedBoolList& boundaryFacesToRemove
 ) const
 {
     if (cvMeshControls().objOutput())
@@ -770,6 +1109,8 @@ void Foam::conformalVoronoiMesh::writeMesh
         writeObjMesh(points, faces, word(meshName + ".obj"));
     }
 
+    reorderPoints(points, boundaryPts, faces, patchStarts[0]);
+
     if (Pstream::parRun())
     {
         reorderProcessorPatches
@@ -786,6 +1127,10 @@ void Foam::conformalVoronoiMesh::writeMesh
         );
     }
 
+    Info<< "    Constructing mesh" << endl;
+
+    timeCheck("Before fvMesh construction");
+
     fvMesh mesh
     (
         IOobject
@@ -802,6 +1147,8 @@ void Foam::conformalVoronoiMesh::writeMesh
         xferMove(neighbour)
     );
 
+    Info<< "    Adding patches to mesh" << endl;
+
     List<polyPatch*> patches(patchStarts.size());
 
     label nValidPatches = 0;
@@ -811,7 +1158,6 @@ void Foam::conformalVoronoiMesh::writeMesh
         if (patchTypes[p] == processorPolyPatch::typeName)
         {
             // Do not create empty processor patches
-
             if (patchSizes[p] > 0)
             {
                 patches[nValidPatches] = new processorPolyPatch
@@ -822,7 +1168,8 @@ void Foam::conformalVoronoiMesh::writeMesh
                     nValidPatches,
                     mesh.boundaryMesh(),
                     Pstream::myProcNo(),
-                    procNeighbours[p]
+                    procNeighbours[p],
+                    coupledPolyPatch::NOORDERING
                 );
 
                 nValidPatches++;
@@ -848,18 +1195,224 @@ void Foam::conformalVoronoiMesh::writeMesh
 
     mesh.addFvPatches(patches);
 
+    timeCheck("Before fvMesh filtering");
+
+    autoPtr<polyMeshFilter> meshFilter;
+
+    label nInitialBadFaces = 0;
+
+    if (cvMeshControls().filterEdges())
+    {
+        Info<< nl << "Filtering edges on polyMesh" << nl << endl;
+
+        meshFilter.reset(new polyMeshFilter(mesh));
+
+        // Filter small edges only. This reduces the number of faces so that
+        // the face filtering is sped up.
+        nInitialBadFaces = meshFilter().filterEdges(0);
+        {
+            const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
+
+            polyTopoChange meshMod(newMesh);
+
+            meshMod.changeMesh(mesh, false);
+        }
+    }
+
+    if (cvMeshControls().filterFaces())
+    {
+        Info<< nl << "Filtering faces on polyMesh" << nl << endl;
+
+        meshFilter.reset(new polyMeshFilter(mesh));
+
+        meshFilter().filter(nInitialBadFaces);
+        {
+            const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
+
+            polyTopoChange meshMod(newMesh);
+
+            meshMod.changeMesh(mesh, false);
+        }
+    }
+
+    timeCheck("After fvMesh filtering");
+
+    mesh.setInstance(instance);
+
     if (!mesh.write())
     {
         FatalErrorIn("Foam::conformalVoronoiMesh::writeMesh(..)")
             << "Failed writing polyMesh."
             << exit(FatalError);
     }
+    else
+    {
+        Info<< nl << "Written filtered mesh to "
+            << mesh.polyMesh::instance() << nl
+            << endl;
+    }
 
-    writeCellSizes(mesh);
 
-    writeCellCentres(mesh);
+    volTensorField alignments
+    (
+        IOobject
+        (
+            "alignmentsField",
+            runTime_.timeName(),
+            runTime_,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        mesh,
+        tensor::zero
+    );
 
-    findRemainingProtrusionSet(mesh);
+    forAll(mesh.cellCentres(), pI)
+    {
+        Vertex_handle nearV =
+            nearest_vertex
+            (
+                toPoint<Point>(mesh.cellCentres()[pI])
+            );
+        alignments[pI] = nearV->alignment();
+    }
+    alignments.write();
+
+    {
+        volVectorField alignmentx
+        (
+            IOobject
+            (
+                "alignmentsx",
+                runTime_.timeName(),
+                runTime_,
+                IOobject::NO_READ,
+                IOobject::AUTO_WRITE
+            ),
+            mesh,
+            vector::zero
+        );
+        forAll(alignmentx, aI)
+        {
+            alignmentx[aI] = alignments[aI].x();
+        }
+        alignmentx.write();
+    }
+    {
+        volVectorField alignmenty
+        (
+            IOobject
+            (
+                "alignmentsy",
+                runTime_.timeName(),
+                runTime_,
+                IOobject::NO_READ,
+                IOobject::AUTO_WRITE
+            ),
+            mesh,
+            vector::zero
+        );
+        forAll(alignmenty, aI)
+        {
+            alignmenty[aI] = alignments[aI].y();
+        }
+        alignmenty.write();
+    }
+    {
+        volVectorField alignmentz
+        (
+            IOobject
+            (
+                "alignmentsz",
+                runTime_.timeName(),
+                runTime_,
+                IOobject::NO_READ,
+                IOobject::AUTO_WRITE
+            ),
+            mesh,
+            vector::zero
+        );
+        forAll(alignmentz, aI)
+        {
+            alignmentz[aI] = alignments[aI].z();
+        }
+        alignmentz.write();
+    }
+    labelIOList boundaryIOPts
+    (
+        IOobject
+        (
+            "boundaryPoints",
+            instance,
+            runTime_,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        boundaryPts
+    );
+
+
+
+
+    // Dump list of boundary points
+    forAll(mesh.boundaryMesh(), patchI)
+    {
+        const polyPatch& pp = mesh.boundaryMesh()[patchI];
+
+        if (!isA<coupledPolyPatch>(pp))
+        {
+            forAll(pp, fI)
+            {
+                const face& boundaryFace = pp[fI];
+
+                forAll(boundaryFace, pI)
+                {
+                    const label boundaryPointI = boundaryFace[pI];
+
+                    boundaryIOPts[boundaryPointI] = boundaryPts[boundaryPointI];
+                }
+            }
+        }
+    }
+
+    boundaryIOPts.write();
+
+//    forAllConstIter(labelHashSet, pointsInPatch, pI)
+//    {
+//        const Foam::point& ptMaster = mesh.points()[pI.key()];
+//
+//        forAllConstIter(labelHashSet, pointsInPatch, ptI)
+//        {
+//            if (ptI.key() != pI.key())
+//            {
+//                const Foam::point& ptSlave = mesh.points()[ptI.key()];
+//
+//                const scalar dist = mag(ptMaster - ptSlave);
+//                if (ptMaster == ptSlave)
+//                {
+//                    Pout<< "Point(" << pI.key() << ") " << ptMaster
+//                        << " == "
+//                        << "(" << ptI.key() << ") " << ptSlave
+//                        << endl;
+//                }
+//                else if (dist == 0)
+//                {
+//                    Pout<< "Point(" << pI.key() << ") " << ptMaster
+//                        << " ~= "
+//                        << "(" << ptI.key() << ") " << ptSlave
+//                        << endl;
+//                }
+//            }
+//        }
+//    }
+
+//    writeCellSizes(mesh);
+
+//    writeCellAlignments(mesh);
+
+//    writeCellCentres(mesh);
+
+//    findRemainingProtrusionSet(mesh);
 }
 
 
@@ -926,7 +1479,7 @@ void Foam::conformalVoronoiMesh::writeCellSizes
 
         forAll(cellSize, i)
         {
-            cellSize[i] = cellSizeControl().cellSize(C[i]);
+            cellSize[i] = cellShapeControls().cellSize(C[i]);
         }
 
         // Info<< nl << "Create targetCellVolume volScalarField" << endl;
@@ -1036,7 +1589,7 @@ void Foam::conformalVoronoiMesh::writeCellSizes
 
     //     forAll(cellSize, i)
     //     {
-    //         cellSize[i] = cellSizeControl().cellSize(P[i]);
+    //         cellSize[i] = cellShapeControls().cellSize(P[i]);
     //     }
 
     //     ptTargetCellSize.write();
@@ -1044,6 +1597,61 @@ void Foam::conformalVoronoiMesh::writeCellSizes
 }
 
 
+void Foam::conformalVoronoiMesh::writeCellAlignments
+(
+    const fvMesh& mesh
+) const
+{
+//    Info<< nl << "Create cellAlignments volTensorField" << endl;
+//
+//    volTensorField cellAlignments
+//    (
+//        IOobject
+//        (
+//            "cellAlignments",
+//            mesh.polyMesh::instance(),
+//            mesh,
+//            IOobject::NO_READ,
+//            IOobject::AUTO_WRITE
+//        ),
+//        mesh,
+//        tensor::I,
+//        zeroGradientFvPatchTensorField::typeName
+//    );
+//
+//    tensorField& cellAlignment = cellAlignments.internalField();
+//
+//    const vectorField& C = mesh.cellCentres();
+//
+//    vectorField xDir(cellAlignment.size());
+//    vectorField yDir(cellAlignment.size());
+//    vectorField zDir(cellAlignment.size());
+//
+//    forAll(cellAlignment, i)
+//    {
+//        cellAlignment[i] = cellShapeControls().cellAlignment(C[i]);
+//        xDir[i] = cellAlignment[i] & vector(1, 0, 0);
+//        yDir[i] = cellAlignment[i] & vector(0, 1, 0);
+//        zDir[i] = cellAlignment[i] & vector(0, 0, 1);
+//    }
+//
+//    OFstream xStr("xDir.obj");
+//    OFstream yStr("yDir.obj");
+//    OFstream zStr("zDir.obj");
+//
+//    forAll(xDir, i)
+//    {
+//        meshTools::writeOBJ(xStr, C[i], C[i] + xDir[i]);
+//        meshTools::writeOBJ(yStr, C[i], C[i] + yDir[i]);
+//        meshTools::writeOBJ(zStr, C[i], C[i] + zDir[i]);
+//    }
+//
+//    cellAlignments.correctBoundaryConditions();
+//
+//    cellAlignments.write();
+}
+
+
 void Foam::conformalVoronoiMesh::writeCellCentres
 (
     const fvMesh& mesh
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.C
similarity index 67%
rename from applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.C
rename to applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.C
index 06b2c4d400890eeaf97fda4e60110090ec18a4f7..bd4973b32b91f5e81e317fbf6b5d88376a246315 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.C
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 \*---------------------------------------------------------------------------*/
 
 #include "indexedCell.H"
@@ -41,8 +36,47 @@ Foam::Ostream& Foam::operator<<
 {
     const CGAL::indexedCell<Gt, Cb>& iv = p.t_;
 
-    os  << "Cell : index:" << iv.index_ << " filterCount:" << iv.filterCount_
-        << nl;
+    os  << "Cell: ";
+
+    if (iv.index_ == CGAL::indexedCell<Gt, Cb>::ctFar)
+    {
+        os  << "far";
+    }
+    else if (iv.index_ >= 0)
+    {
+        os  << iv.index_;
+    }
+    else if (iv.index_ == CGAL::indexedCell<Gt, Cb>::ctInternal)
+    {
+        os  << "internal";
+    }
+    else if (iv.index_ == CGAL::indexedCell<Gt, Cb>::ctSurface)
+    {
+        os  << "surface";
+    }
+    else if (iv.index_ == CGAL::indexedCell<Gt, Cb>::ctFeatureEdge)
+    {
+        os  << "featureEdge";
+    }
+    else if (iv.index_ == CGAL::indexedCell<Gt, Cb>::ctFeaturePoint)
+    {
+        os  << "featurePoint";
+    }
+    else
+    {
+        os  << "unassigned";
+    }
+
+    if (iv.parallelDualVertex())
+    {
+        os  << " (processor)";
+    }
+    else
+    {
+        os  << " (local)";
+    }
+
+    os  << " filterCount: " << iv.filterCount_ << nl;
     os  << "    " << iv.vertex(0)->info();
     os  << "    " << iv.vertex(1)->info();
     os  << "    " << iv.vertex(2)->info();
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H
similarity index 84%
rename from applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H
rename to applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H
index eab096819aedc3669652182f349712344c0a23b6..4669110b6e9edbb95dd1e0a9ea240576f95a49fd 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCell.H
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Class
     indexedCell
 
@@ -52,6 +47,8 @@ SourceFiles
 #include "InfoProxy.H"
 #include "tetCell.H"
 #include "typeInfo.H"
+#include "vectorTools.H"
+#include "indexedCellEnum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -85,6 +82,7 @@ template
 >
 class indexedCell
 :
+    public Foam::indexedCellEnum,
     public Cb
 {
     // Private data
@@ -98,6 +96,7 @@ class indexedCell
         //           not on a processor face
         //  < 0 && > ctFar : the (global) index of a dual point on a processor
         //                   face
+
         int index_;
 
         //- The number of times that this Delaunay cell has been limited
@@ -105,14 +104,17 @@ class indexedCell
         int filterCount_;
 
 
-public:
+    // Private member functions
 
-    enum cellTypes
-    {
-        ctFar = INT_MIN
-    };
+        //- Same as globallyOrderedCellVertices but without sorting
+        Foam::tetCell unsortedVertexGlobalIndices
+        (
+            const Foam::globalIndex& globalDelaunayVertexIndices
+        ) const;
 
 
+public:
+
     typedef typename Cb::Vertex_handle                   Vertex_handle;
     typedef typename Cb::Cell_handle                     Cell_handle;
 
@@ -155,9 +157,13 @@ public:
 
         inline int cellIndex() const;
 
+#ifdef CGAL_INEXACT
         inline const Foam::point& dual();
+#else
+        inline const Foam::point dual();
+#endif
 
-        inline bool farCell() const;
+        inline bool unassigned() const;
 
         inline int& filterCount();
 
@@ -169,6 +175,12 @@ public:
         //- Does the Delaunay cell have a far point
         inline bool hasFarPoint() const;
 
+        //- Does the Delaunay cell have a feature point
+        inline bool hasFeaturePoint() const;
+
+        //- Does the Delaunay cell have a seed point
+        inline bool hasSeedPoint() const;
+
         inline bool hasInternalPoint() const;
 
         //- Does the Dual vertex form part of a processor patch
@@ -186,6 +198,13 @@ public:
             const Foam::globalIndex& globalDelaunayVertexIndices
         ) const;
 
+        //- Using the globalIndex object, return a list of four vertices with
+        //  so that the cell has a consistent orientation in parallel.
+        inline Foam::FixedList<Foam::label, 4> globallyOrderedCellVertices
+        (
+            const Foam::globalIndex& globalDelaunayVertexIndices
+        ) const;
+
         //- Is the Delaunay cell part of the final dual mesh, i.e. any vertex
         //  form part of the internal or boundary definition
         inline bool internalOrBoundaryDualVertex() const;
@@ -198,8 +217,13 @@ public:
         //  least one Delaunay vertex outside and at least one inside
         inline bool boundaryDualVertex() const;
 
+        //- A dual vertex on a feature edge will result from this Delaunay cell
+        inline bool featureEdgeDualVertex() const;
+
         inline bool nearProcBoundary() const;
 
+        inline bool potentialCoplanarCell() const;
+
 
     // Info
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.C
new file mode 100644
index 0000000000000000000000000000000000000000..7213739844d2035931f2177751a37ac76311ea1a
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.C
@@ -0,0 +1,128 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "plane.H"
+#include "tetrahedron.H"
+#include "pointConversion.H"
+#include "CGALTriangulation3DKernel.H"
+
+
+template <typename Cell>
+Foam::scalar Foam::cvMeshChecks::coplanarTet
+(
+    Cell& c,
+    const scalar tol
+)
+{
+    tetPointRef tet
+    (
+        topoint(c->vertex(0)->point()),
+        topoint(c->vertex(1)->point()),
+        topoint(c->vertex(2)->point()),
+        topoint(c->vertex(3)->point())
+    );
+
+    const scalar quality = tet.quality();
+
+    if (quality < tol)
+    {
+        return quality;
+    }
+
+    return 0;
+
+//    plane triPlane
+//    (
+//        topoint(c->vertex(0)->point()),
+//        topoint(c->vertex(1)->point()),
+//        topoint(c->vertex(2)->point())
+//    );
+//
+//    const scalar distance = triPlane.distance(topoint(c->vertex(3)->point()));
+//
+//    // Check if the four points are roughly coplanar. If they are then we
+//    // cannot calculate the circumcentre. Better test might be the volume
+//    // of the tet.
+//    if (distance < tol)
+//    {
+//        return 0;
+//    }
+//
+//    return distance;
+}
+
+
+template <typename Cell>
+bool Foam::cvMeshChecks::closePoints
+(
+    Cell& c,
+    const scalar tol
+)
+{
+    for (label v = 0; v < 4; ++v)
+    {
+        for (label vA = v + 1; vA < 4; ++vA)
+        {
+            if
+            (
+                mag
+                (
+                    topoint(c->vertex(v)->point())
+                  - topoint(c->vertex(vA)->point())
+                )
+              < tol
+            )
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
+template <typename Cell>
+bool Foam::cvMeshChecks::smallVolume
+(
+    Cell& c,
+    const scalar tol
+)
+{
+    CGAL::Tetrahedron_3<baseK> tet
+    (
+        c->vertex(0)->point(),
+        c->vertex(1)->point(),
+        c->vertex(2)->point(),
+        c->vertex(3)->point()
+    );
+
+    if (tet.volume() < tol)
+    {
+        return true;
+    }
+
+    return false;
+}
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.H
new file mode 100644
index 0000000000000000000000000000000000000000..c040eafab67c1b07447377de165db13fb32b7dce
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellChecks.H
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef indexedCellChecks_H
+#define indexedCellChecks_H
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+namespace cvMeshChecks
+{
+
+    template <typename Cell>
+    scalar coplanarTet
+    (
+        Cell& c,
+        const scalar tol = 1e-12
+    );
+
+    template <typename Cell>
+    bool closePoints
+    (
+        Cell& c,
+        const scalar tol = 1e-12
+    );
+
+    template <typename Cell>
+    bool smallVolume
+    (
+        Cell& c,
+        const scalar tol = 0.0
+    );
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace cvMeshChecks
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "indexedCellChecks.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.C
new file mode 100644
index 0000000000000000000000000000000000000000..5d7d953948bb73934c550843bb1371d068a3b249
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.C
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "indexedCellEnum.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+template<>
+const char*
+Foam::NamedEnum<Foam::indexedCellEnum::cellTypes, 6>::names[] =
+{
+    "Unassigned",
+    "Internal",
+    "Surface",
+    "FeatureEdge",
+    "FeaturePoint",
+    "Far"
+};
+
+const Foam::NamedEnum<Foam::indexedCellEnum::cellTypes, 6>
+cellTypesNames_;
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.H
new file mode 100644
index 0000000000000000000000000000000000000000..5ccef621e74d1bf80816da1fd6380a77779fac15
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellEnum.H
@@ -0,0 +1,80 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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
+    indexedCellEnum
+
+Description
+
+SourceFiles
+    indexedCellEnum.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef indexedCellEnum_H
+#define indexedCellEnum_H
+
+#include "NamedEnum.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+class indexedCellEnum
+{
+public:
+
+
+    enum cellTypes
+    {
+        ctUnassigned    = INT_MIN,
+        ctFar           = INT_MIN + 1,
+        ctInternal      = INT_MIN + 2,
+        ctSurface       = INT_MIN + 3,
+        ctFeatureEdge   = INT_MIN + 4,
+        ctFeaturePoint  = INT_MIN + 5
+    };
+
+    static const Foam::NamedEnum<cellTypes, 6> cellTypesNames_;
+};
+
+
+template<>
+inline bool contiguous<indexedCellEnum>()
+{
+    return true;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H
similarity index 51%
rename from applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H
rename to applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H
index eb5e0b44bd15d4ac01fb83e6b44d0528be489986..83434ba2f12712085d2ca796067708d195eddc8a 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell/indexedCellI.H
@@ -21,20 +21,41 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 \*---------------------------------------------------------------------------*/
 
+//#include "indexedCellChecks.H"
+
+template<class Gt, class Cb>
+Foam::tetCell CGAL::indexedCell<Gt, Cb>::unsortedVertexGlobalIndices
+(
+    const Foam::globalIndex& globalDelaunayVertexIndices
+) const
+{
+    Foam::tetCell tVGI;
+
+    for (int i = 0; i < 4; i++)
+    {
+        Vertex_handle v = this->vertex(i);
+
+        // Finding the global index of each Delaunay vertex
+        tVGI[i] = globalDelaunayVertexIndices.toGlobal
+        (
+            Foam::Pstream::myProcNo(),
+            v->index()
+        );
+    }
+
+    return tVGI;
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Gt, class Cb>
 CGAL::indexedCell<Gt, Cb>::indexedCell()
 :
     Cb(),
-    index_(ctFar),
+    index_(ctUnassigned),
     filterCount_(0)
 {}
 
@@ -46,7 +67,7 @@ CGAL::indexedCell<Gt, Cb>::indexedCell
 )
 :
     Cb(v0, v1, v2, v3),
-    index_(ctFar),
+    index_(ctUnassigned),
     filterCount_(0)
 {}
 
@@ -65,7 +86,7 @@ CGAL::indexedCell<Gt, Cb>::indexedCell
 )
 :
     Cb(v0, v1, v2, v3, n0, n1, n2, n3),
-    index_(ctFar),
+    index_(ctUnassigned),
     filterCount_(0)
 {}
 
@@ -86,28 +107,37 @@ int CGAL::indexedCell<Gt, Cb>::cellIndex() const
 }
 
 
-template<class Gt, class Cb>
-const Foam::point& CGAL::indexedCell<Gt, Cb>::dual()
-{
 #ifdef CGAL_INEXACT
-    return reinterpret_cast<const Foam::point&>(this->circumcenter());
+    template<class Gt, class Cb>
+    const Foam::point& CGAL::indexedCell<Gt, Cb>::dual()
+    {
+    //    if (Foam::cvMeshChecks::coplanarTet(*this, 1e-20) == 0)
+    //    {
+            // Do exact calc
+    //    }
+
+        return reinterpret_cast<const Foam::point&>(this->circumcenter());
+    }
 #else
-    const typename Gt::Point_3& P = this->circumcenter();
+    template<class Gt, class Cb>
+    const Foam::point CGAL::indexedCell<Gt, Cb>::dual()
+    {
+        const typename Gt::Point_3& P = this->circumcenter();
 
-    return
-    (
-        CGAL::to_double(P.x()),
-        CGAL::to_double(P.y()),
-        CGAL::to_double(P.z())
-    );
+        return Foam::point
+        (
+            CGAL::to_double(P.x()),
+            CGAL::to_double(P.y()),
+            CGAL::to_double(P.z())
+        );
+    }
 #endif
-}
 
 
 template<class Gt, class Cb>
-inline bool CGAL::indexedCell<Gt, Cb>::farCell() const
+inline bool CGAL::indexedCell<Gt, Cb>::unassigned() const
 {
-    return index_ == ctFar;
+    return index_ == ctUnassigned;
 }
 
 
@@ -160,6 +190,32 @@ inline bool CGAL::indexedCell<Gt, Cb>::hasFarPoint() const
 }
 
 
+template<class Gt, class Cb>
+inline bool CGAL::indexedCell<Gt, Cb>::hasFeaturePoint() const
+{
+    return
+    (
+        this->vertex(0)->featurePoint()
+     || this->vertex(1)->featurePoint()
+     || this->vertex(2)->featurePoint()
+     || this->vertex(3)->featurePoint()
+    );
+}
+
+
+template<class Gt, class Cb>
+inline bool CGAL::indexedCell<Gt, Cb>::hasSeedPoint() const
+{
+    return
+    (
+        this->vertex(0)->seedPoint()
+     || this->vertex(1)->seedPoint()
+     || this->vertex(2)->seedPoint()
+     || this->vertex(3)->seedPoint()
+    );
+}
+
+
 template<class Gt, class Cb>
 inline bool CGAL::indexedCell<Gt, Cb>::hasInternalPoint() const
 {
@@ -178,10 +234,21 @@ inline bool CGAL::indexedCell<Gt, Cb>::parallelDualVertex() const
 {
     return
     (
-        this->vertex(0)->referred()
-     || this->vertex(1)->referred()
-     || this->vertex(2)->referred()
-     || this->vertex(3)->referred()
+        !this->hasFarPoint()
+    &&
+        (
+            this->vertex(0)->referred()
+         || this->vertex(1)->referred()
+         || this->vertex(2)->referred()
+         || this->vertex(3)->referred()
+        )
+    &&
+        (
+            this->vertex(0)->real()
+         || this->vertex(1)->real()
+         || this->vertex(2)->real()
+         || this->vertex(3)->real()
+        )
     );
 }
 
@@ -247,34 +314,38 @@ inline Foam::tetCell CGAL::indexedCell<Gt, Cb>::vertexGlobalIndices
 ) const
 {
     // tetVertexGlobalIndices
-    Foam::tetCell tVGI;
+    Foam::tetCell tVGI
+        = unsortedVertexGlobalIndices(globalDelaunayVertexIndices);
 
-    for (int i = 0; i < 4; i++)
+    // bubble sort
+    for (int i = 0; i < tVGI.size(); i++)
     {
-        Vertex_handle v = this->vertex(i);
-
-        // Finding the global index of each Delaunay vertex
-
-        if (v->referred())
-        {
-            // Referred vertices may have negative indices
-
-            tVGI[i] = globalDelaunayVertexIndices.toGlobal
-            (
-                v->procIndex(),
-                Foam::mag(v->index())
-            );
-        }
-        else
+        for (int j = tVGI.size() - 1 ; j > i; j--)
         {
-            tVGI[i] = globalDelaunayVertexIndices.toGlobal
-            (
-                Foam::Pstream::myProcNo(),
-                v->index()
-            );
+            if (tVGI[j - 1] > tVGI[j])
+            {
+                Foam::Swap(tVGI[j - 1], tVGI[j]);
+            }
         }
     }
 
+    return tVGI;
+}
+
+
+template<class Gt, class Cb>
+inline Foam::FixedList<Foam::label, 4>
+CGAL::indexedCell<Gt, Cb>::globallyOrderedCellVertices
+(
+    const Foam::globalIndex& globalDelaunayVertexIndices
+) const
+{
+    // tetVertexGlobalIndices
+    Foam::tetCell tVGI
+        = unsortedVertexGlobalIndices(globalDelaunayVertexIndices);
+
+    Foam::FixedList<Foam::label, 4> vertexMap(Foam::identity(4));
+
     // bubble sort
     for (int i = 0; i < tVGI.size(); i++)
     {
@@ -283,10 +354,16 @@ inline Foam::tetCell CGAL::indexedCell<Gt, Cb>::vertexGlobalIndices
             if (tVGI[j - 1] > tVGI[j])
             {
                 Foam::Swap(tVGI[j - 1], tVGI[j]);
+                Foam::Swap(vertexMap[j - 1], vertexMap[j]);
             }
         }
     }
 
+    for (int i = 0; i < 4; i++)
+    {
+        tVGI[i] = vertexMap[i];
+    }
+
     return tVGI;
 }
 
@@ -309,10 +386,14 @@ inline bool CGAL::indexedCell<Gt, Cb>::anyInternalOrBoundaryDualVertex() const
 {
     return
     (
-        this->vertex(0)->anyInternalOrBoundaryPoint()
-     || this->vertex(1)->anyInternalOrBoundaryPoint()
-     || this->vertex(2)->anyInternalOrBoundaryPoint()
-     || this->vertex(3)->anyInternalOrBoundaryPoint()
+        this->vertex(0)->internalOrBoundaryPoint()
+     || this->vertex(0)->externalBoundaryPoint()
+     || this->vertex(1)->internalOrBoundaryPoint()
+     || this->vertex(1)->externalBoundaryPoint()
+     || this->vertex(2)->internalOrBoundaryPoint()
+     || this->vertex(2)->externalBoundaryPoint()
+     || this->vertex(3)->internalOrBoundaryPoint()
+     || this->vertex(3)->externalBoundaryPoint()
     );
 }
 
@@ -323,21 +404,34 @@ inline bool CGAL::indexedCell<Gt, Cb>::boundaryDualVertex() const
     return
     (
         (
-           this->vertex(0)->internalOrBoundaryPoint()
-        || this->vertex(1)->internalOrBoundaryPoint()
-        || this->vertex(2)->internalOrBoundaryPoint()
-        || this->vertex(3)->internalOrBoundaryPoint()
+           this->vertex(0)->internalBoundaryPoint()
+        || this->vertex(1)->internalBoundaryPoint()
+        || this->vertex(2)->internalBoundaryPoint()
+        || this->vertex(3)->internalBoundaryPoint()
         )
      && (
-           !this->vertex(0)->internalOrBoundaryPoint()
-        || !this->vertex(1)->internalOrBoundaryPoint()
-        || !this->vertex(2)->internalOrBoundaryPoint()
-        || !this->vertex(3)->internalOrBoundaryPoint()
+           this->vertex(0)->externalBoundaryPoint()
+        || this->vertex(1)->externalBoundaryPoint()
+        || this->vertex(2)->externalBoundaryPoint()
+        || this->vertex(3)->externalBoundaryPoint()
         )
     );
 }
 
 
+template<class Gt, class Cb>
+inline bool CGAL::indexedCell<Gt, Cb>::featureEdgeDualVertex() const
+{
+    return
+    (
+        this->vertex(0)->featureEdgePoint()
+     && this->vertex(1)->featureEdgePoint()
+     && this->vertex(2)->featureEdgePoint()
+     && this->vertex(3)->featureEdgePoint()
+    );
+}
+
+
 template<class Gt, class Cb>
 inline bool CGAL::indexedCell<Gt, Cb>::nearProcBoundary() const
 {
@@ -351,4 +445,94 @@ inline bool CGAL::indexedCell<Gt, Cb>::nearProcBoundary() const
 }
 
 
+template<class Gt, class Cb>
+inline bool CGAL::indexedCell<Gt, Cb>::potentialCoplanarCell() const
+{
+    Foam::label nMasters = 0;
+    Foam::label nSlaves = 0;
+
+    Vertex_handle vM[2];
+    Vertex_handle vS[2];
+
+    for (Foam::label i = 0; i < 4; ++i)
+    {
+        Vertex_handle v = this->vertex(i);
+
+        if (v->internalBoundaryPoint())
+        {
+            vM[nMasters] = v;
+            nMasters++;
+        }
+
+        if (v->externalBoundaryPoint())
+        {
+            vS[nSlaves] = v;
+            nSlaves++;
+        }
+    }
+
+    Foam::label nPairs = 0;
+
+    if (nMasters == 2 && nSlaves == 2)
+    {
+        Foam::vector vp0(Foam::vector::zero);
+        Foam::vector vp1(Foam::vector::zero);
+
+        if
+        (
+            vM[0]->type() == vS[0]->index()
+         && vM[0]->index() == vS[0]->type()
+        )
+        {
+            vp0 = reinterpret_cast<const Foam::point&>(vM[0]->point())
+                - reinterpret_cast<const Foam::point&>(vS[0]->point());
+            nPairs++;
+        }
+        else if
+        (
+            vM[0]->type() == vS[1]->index()
+         && vM[0]->index() == vS[1]->type()
+        )
+        {
+            vp0 = reinterpret_cast<const Foam::point&>(vM[0]->point())
+                - reinterpret_cast<const Foam::point&>(vS[1]->point());
+            nPairs++;
+        }
+
+        if
+        (
+            vM[1]->type() == vS[0]->index()
+         && vM[1]->index() == vS[0]->type()
+        )
+        {
+            vp1 = reinterpret_cast<const Foam::point&>(vM[1]->point())
+                - reinterpret_cast<const Foam::point&>(vS[0]->point());
+            nPairs++;
+        }
+        else if
+        (
+            vM[1]->type() == vS[1]->index()
+         && vM[1]->index() == vS[1]->type()
+        )
+        {
+            vp1 = reinterpret_cast<const Foam::point&>(vM[1]->point())
+                - reinterpret_cast<const Foam::point&>(vS[1]->point());
+            nPairs++;
+        }
+
+        if (nPairs == 2)
+        {
+            if (Foam::vectorTools::areParallel(vp0, vp1))
+            {
+                Foam::Pout<< "PARALLEL" << Foam::endl;
+
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
 // * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C
deleted file mode 100644
index 2f1fa3c5bbb4b2185b61ea679014140d1eebfcae..0000000000000000000000000000000000000000
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C
+++ /dev/null
@@ -1,115 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 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/>.
-
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
-\*---------------------------------------------------------------------------*/
-
-#include "indexedVertex.H"
-#include "point.H"
-
-// * * * * * * * * * * * * * * * *  IOStream operators * * * * * * * * * * * //
-
-template<class Gt, class Vb>
-Foam::Ostream& Foam::operator<<
-(
-    Ostream& os,
-    const InfoProxy<CGAL::indexedVertex<Gt, Vb> >& p
-)
-{
-    const CGAL::indexedVertex<Gt, Vb>& iv = p.t_;
-
-    if (iv.type_ == CGAL::indexedVertex<Gt, Vb>::vtNearBoundary)
-    {
-        os  << "internal near boundary point" << nl;
-    }
-    else if (iv.type_ == CGAL::indexedVertex<Gt, Vb>::vtInternal)
-    {
-        os  << "internal point" << nl;
-    }
-    else if (iv.type_ == CGAL::indexedVertex<Gt, Vb>::vtFar)
-    {
-        os  << "far point" << nl;
-    }
-    else if (iv.type_ > CGAL::indexedVertex<Gt, Vb>::vtFar && iv.type_ < 0)
-    {
-        if (iv.index_ >= 0)
-        {
-            os  << "referred (master) point from processor " << iv.procIndex()
-                << nl;
-        }
-        else
-        {
-            os  << "referred (slave) point from processor " << iv.procIndex()
-                << nl;
-        }
-    }
-    else if (iv.type_ >= 0)
-    {
-        if (iv.ppMaster())
-        {
-            os  << "master of point pair. paired up with point " << iv.index_
-            << nl;
-        }
-        else if (iv.ppSlave())
-        {
-            os  << "slave of point pair. paired up with point " << iv.index_
-            << nl;
-        }
-        else
-        {
-            FatalErrorIn
-            (
-                "operator<<"
-                "(Ostream&, const InfoProxy<CGAL::indexedVertex<Gt, Vb> >&)"
-            )   << "unhandled type " << iv.type_ << " index " << iv.index_
-                << abort(FatalError);
-        }
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "operator<<"
-            "(Ostream&, const InfoProxy<CGAL::indexedVertex<Gt, Vb> >&)"
-        )   << "unhandled type " << iv.type_ << " index " << iv.index_
-            << abort(FatalError);
-    }
-    const Foam::point pos
-    (
-        CGAL::to_double(iv.point().x()),
-        CGAL::to_double(iv.point().y()),
-        CGAL::to_double(iv.point().z())
-    );
-
-    os  << "    type:" << iv.type_ << " index:" << iv.index_
-        << " at:" << pos << nl;
-
-    return os;
-}
-
-
-// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.C
new file mode 100644
index 0000000000000000000000000000000000000000..5aa39368740d93ff1203ba896c98a6364755e512
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.C
@@ -0,0 +1,185 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "indexedVertex.H"
+#include "point.H"
+#include "Istream.H"
+#include "Ostream.H"
+#include "OStringStream.H"
+#include "IStringStream.H"
+
+// * * * * * * * * * * * * * * * *  IOStream operators * * * * * * * * * * * //
+
+Foam::Istream& Foam::operator>>
+(
+    Istream& is,
+    CGAL::Point_3<baseK>& p
+)
+{
+//    string data(is);
+//
+//    std::istringstream stdIs;
+//
+//    CGAL::set_ascii_mode(stdIs);
+//
+//    stdIs.str(data);
+//
+//    CGAL::Gmpz xNumer, xDenom;
+//    CGAL::Gmpz yNumer, yDenom;
+//    CGAL::Gmpz zNumer, zDenom;
+//
+//    stdIs >> xNumer >> xDenom >> yNumer >> yDenom >> zNumer >> zDenom;
+//
+//    CGAL::Gmpq x(xNumer, xDenom);
+//    CGAL::Gmpq y(yNumer, yDenom);
+//    CGAL::Gmpq z(zNumer, zDenom);
+//
+//    p = CGAL::Point_3<baseK>
+//    (
+//        CGAL::to_double(x),
+//        CGAL::to_double(y),
+//        CGAL::to_double(z)
+//    );
+
+    Foam::point pt;
+
+    is >> pt.x() >> pt.y() >> pt.z();
+
+    p = CGAL::Point_3<baseK>
+    (
+        pt.x(),
+        pt.y(),
+        pt.z()
+    );
+
+    return is;
+}
+
+
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const CGAL::Point_3<baseK>& p
+)
+{
+//    CGAL::Gmpq x(CGAL::to_double(p.x()));
+//    CGAL::Gmpq y(CGAL::to_double(p.y()));
+//    CGAL::Gmpq z(CGAL::to_double(p.z()));
+//
+//    std::ostringstream stdOs;
+//
+//    CGAL::set_ascii_mode(stdOs);
+//
+//    stdOs<< x.numerator() << ' ' << x.denominator() << ' '
+//         << y.numerator() << ' ' << y.denominator() << ' '
+//         << z.numerator() << ' ' << z.denominator();
+//
+//    os << stdOs.str();
+
+    os  << CGAL::to_double(p.x()) << ' '
+        << CGAL::to_double(p.y()) << ' '
+        << CGAL::to_double(p.z());
+
+    return os;
+}
+
+
+template<class Gt, class Vb>
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const CGAL::indexedVertex<Gt, Vb>& p
+)
+{
+    os  << p.point()
+        << p.index()
+        << static_cast<int>(p.type())
+        << p.procIndex()
+        << p.alignment()
+        << p.targetCellSize();
+
+    return os;
+}
+
+
+template<class Gt, class Vb>
+Foam::Istream& Foam::operator>>
+(
+    Istream& is,
+    CGAL::indexedVertex<Gt, Vb>& p
+)
+{
+    is  >> p.point()
+        >> p.index();
+
+    int type;
+    is  >> type;
+
+    p.type() = static_cast<Foam::indexedVertexEnum::vertexType>(type);
+
+    is  >> p.procIndex()
+        >> p.alignment()
+        >> p.targetCellSize();
+
+    return is;
+}
+
+
+template<class Gt, class Vb>
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const InfoProxy<CGAL::indexedVertex<Gt, Vb> >& p
+)
+{
+    const CGAL::indexedVertex<Gt, Vb>& iv = p.t_;
+
+    const Foam::point pt
+    (
+        CGAL::to_double(iv.point().x()),
+        CGAL::to_double(iv.point().y()),
+        CGAL::to_double(iv.point().z())
+    );
+
+    string referred
+    (
+        Pstream::myProcNo() == iv.processor_
+      ? string(" (local)")
+      : string(" (from " + name(iv.processor_) + ")")
+    );
+
+    os  << iv.index_ << " "
+        << CGAL::indexedVertex<Gt, Vb>::vertexTypeNames_[iv.type_]
+        << " at:" << pt
+        << " size:" << iv.targetCellSize_
+        << " alignment:" << iv.alignment_
+        << referred.c_str()
+        << endl;
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H
similarity index 57%
rename from applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H
rename to applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H
index c3d13ab05eb8b6d413c655cb25eeca246726ca85..f39e90761d0666415b2ab03878a65addf72d2744 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertex.H
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Class
     indexedVertex
 
@@ -43,9 +38,11 @@ SourceFiles
 #define indexedVertex_H
 
 #include <CGAL/Triangulation_3.h>
+#include "CGALTriangulation3DKernel.H"
 #include "tensor.H"
 #include "InfoProxy.H"
 #include "point.H"
+#include "indexedVertexEnum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -56,13 +53,41 @@ template<class Gt, class Vb> class indexedVertex;
 
 namespace Foam
 {
+
 class Ostream;
+class Istream;
+
 template<class Gt, class Vb> Ostream& operator<<
 (
     Ostream&,
     const Foam::InfoProxy<CGAL::indexedVertex<Gt, Vb> >&
 );
-}
+
+template<class Gt, class Vb> Ostream& operator<<
+(
+    Ostream&,
+    const CGAL::indexedVertex<Gt, Vb>&
+);
+
+template<class Gt, class Vb> Istream& operator>>
+(
+    Istream&,
+    CGAL::indexedVertex<Gt, Vb>&
+);
+
+inline Istream& operator>>
+(
+    Istream& is,
+    CGAL::Point_3<baseK>& p
+);
+
+inline Ostream& operator<<
+(
+    Ostream& os,
+    const CGAL::Point_3<baseK>& p
+);
+
+} // End namespace Foam
 
 
 namespace CGAL
@@ -72,26 +97,24 @@ namespace CGAL
                          Class indexedVertex Declaration
 \*---------------------------------------------------------------------------*/
 
-template<class Gt, class Vb=CGAL::Triangulation_vertex_base_3<Gt> >
+template<class Gt, class Vb = CGAL::Triangulation_vertex_base_3<Gt> >
 class indexedVertex
 :
+    public Foam::indexedVertexEnum,
     public Vb
 {
     // Private data
 
+        //- Type of pair-point
+        vertexType type_;
+
         //- The index for this Delaunay vertex.  For referred vertices, the
         //  index is negative for vertices that are the outer (slave) of point
         //  pairs
         int index_;
 
-        //- type of pair-point   :
-        //  vtNearBoundary       : internal near boundary point.
-        //  vtInternal           : internal point.
-        //  vtFar                : far-point.
-        //  > vtFar, < 0         : referred point from processor -(type_ + 1)
-        //  >= 0                 : part of point-pair. Index of other point.
-        //                         Lowest numbered is inside one (master).
-        int type_;
+        //- Number of the processor that owns this vertex
+        int processor_;
 
         //- Required alignment of the dual cell of this vertex
         Foam::tensor alignment_;
@@ -100,29 +123,15 @@ class indexedVertex
         Foam::scalar targetCellSize_;
 
         //- Specify whether the vertex is fixed or movable.
-        bool vertexFixed_;
-
-        bool nearProcBoundary_;
+//        bool vertexFixed_;
 
 
 public:
 
-    enum vertexTypes
-    {
-        vtNearBoundary  = INT_MIN,
-        vtInternal      = INT_MIN + 1,
-        vtFar           = INT_MIN + 2
-    };
-
-    enum vertexMotion
-    {
-        fixed   = 0,
-        movable = 1
-    };
-
-    typedef typename Vb::Vertex_handle      Vertex_handle;
-    typedef typename Vb::Cell_handle        Cell_handle;
-    typedef typename Vb::Point              Point;
+    typedef typename Vb::Triangulation_data_structure   Tds;
+    typedef typename Vb::Point                          Point;
+    typedef typename Tds::Vertex_handle                 Vertex_handle;
+    typedef typename Tds::Cell_handle                   Cell_handle;
 
     template<typename TDS2>
     struct Rebind_TDS
@@ -131,14 +140,23 @@ public:
         typedef indexedVertex<Gt,Vb2>                           Other;
     };
 
-
     // Constructors
 
         inline indexedVertex();
 
         inline indexedVertex(const Point& p);
 
-        inline indexedVertex(const Point& p, int index, int type);
+        inline indexedVertex(const Point& p, vertexType type);
+
+        inline indexedVertex(const Foam::point& p, vertexType type);
+
+        inline indexedVertex
+        (
+            const Point& p,
+            int index,
+            vertexType type,
+            int processor
+        );
 
         inline indexedVertex(const Point& p, Cell_handle f);
 
@@ -151,9 +169,9 @@ public:
 
         inline int index() const;
 
-        inline int& type();
+        inline vertexType& type();
 
-        inline int type() const;
+        inline vertexType type() const;
 
         inline Foam::tensor& alignment();
 
@@ -171,26 +189,18 @@ public:
         //- Is point internal, i.e. not on boundary
         inline bool internalPoint() const;
 
-        //- Is point internal, i.e. not on boundary, external query.
-        inline static bool internalPoint(int type);
-
-        // is this a referred vertex
+        //- Is this a referred vertex
         inline bool referred() const;
 
-        // is this a referred internal or boundary vertex
-        inline bool referredInternalOrBoundaryPoint() const;
-
-        // is this a referred external (pair slave) vertex
-        inline bool referredExternal() const;
-
-        // Is this a "real" point on this processor, i.e. is it internal or part
-        // of the boundary description, and not a "far" or "referred" point
+        //- Is this a "real" point on this processor, i.e. is internal or part
+        //  of the boundary description, and not a "far" or "referred" point
         inline bool real() const;
 
         // For referred vertices, what is the original processor index
         inline int procIndex() const;
 
-        inline static int encodeProcIndex(int procI);
+        // For referred vertices, set the original processor index
+        inline int& procIndex();
 
         //- Set the point to be internal
         inline void setInternal();
@@ -208,45 +218,61 @@ public:
         inline void setNearProcBoundary();
 
         //- Either master or slave of pointPair.
-        inline bool pairPoint() const;
-
-        //- Master of a pointPair is the lowest numbered one.
-        inline bool ppMaster() const;
-
-        //- Master of a pointPair is the lowest numbered one, external query.
-        inline static bool ppMaster(int index, int type);
-
-        //- Slave of a pointPair is the highest numbered one.
-        inline bool ppSlave() const;
+        inline bool boundaryPoint() const;
 
         //- Either original internal point or master of pointPair.
         inline bool internalOrBoundaryPoint() const;
 
-        //- Either original internal point or master of pointPair.
-        //  External query.
-        inline static bool internalOrBoundaryPoint(int index, int type);
-
         //- Is point near the boundary or part of the boundary definition
         inline bool nearOrOnBoundary() const;
 
-        //- Either a real or referred internal or boundary point
-        inline bool anyInternalOrBoundaryPoint() const;
+        //- Part of a feature point
+        inline bool featurePoint() const;
 
-        //- Is the vertex fixed or movable
-        inline bool isVertexFixed() const;
+        //- Part of a feature edge
+        inline bool featureEdgePoint() const;
 
-        //- Fix the vertex so that it can't be moved
-        inline void setVertexFixed();
+        //- Part of a surface point pair
+        inline bool surfacePoint() const;
 
-    // inline void operator=(const Delaunay::Finite_vertices_iterator vit)
-    // {
-    //     Vb::operator=indexedVertex(vit->point());
+        inline bool internalBoundaryPoint() const;
 
-    //     this->index_ = vit->index();
+        inline bool externalBoundaryPoint() const;
 
-    //     this->type_ = vit->type();
-    // }
+//        //- Is the vertex fixed or movable
+//        inline bool isVertexFixed() const;
+//
+//        //- Fix the vertex so that it can't be moved
+//        inline void setVertexFixed();
 
+        inline indexedVertex& operator=(const indexedVertex& rhs)
+        {
+            Vb::operator=(rhs);
+
+            this->type_ = rhs.type();
+            this->index_ = rhs.index();
+            this->processor_ = rhs.procIndex();
+            this->alignment_ = rhs.alignment();
+            this->targetCellSize_ = rhs.targetCellSize();
+
+            return *this;
+        }
+
+        inline bool operator==(const indexedVertex& rhs) const
+        {
+            return
+            (
+                //this->point() == rhs.point()
+                this->type_ == rhs.type()
+             && this->index_ == rhs.index()
+             && this->processor_ == rhs.procIndex()
+            );
+        }
+
+        inline bool operator!=(const indexedVertex& rhs) const
+        {
+            return !(*this == rhs);
+        }
 
 
     // Info
@@ -264,6 +290,17 @@ public:
             const Foam::InfoProxy<indexedVertex<Gt, Vb> >&
         );
 
+        friend Foam::Ostream& Foam::operator<< <Gt, Vb>
+        (
+            Foam::Ostream&,
+            const indexedVertex<Gt, Vb>&
+        );
+
+        friend Foam::Istream& Foam::operator>> <Gt, Vb>
+        (
+            Foam::Istream&,
+            indexedVertex<Gt, Vb>&
+        );
 };
 
 
@@ -271,6 +308,37 @@ public:
 
 } // End namespace CGAL
 
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+#ifdef CGAL_INEXACT
+namespace Foam
+{
+    // For inexact representations where the storage type is a double, the data
+    // is contiguous. This may not be true for exact number types.
+    template<>
+    inline bool contiguous
+    <
+        CGAL::indexedVertex
+        <
+            K,
+            CGAL::Triangulation_vertex_base_3<K>
+        >
+    >()
+    {
+        return true;
+    }
+
+
+    template<>
+    inline bool contiguous<CGAL::Triangulation_vertex_base_3<K>::Point>()
+    {
+        return true;
+    }
+
+} // End namespace Foam
+#endif
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #include "indexedVertexI.H"
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C
new file mode 100644
index 0000000000000000000000000000000000000000..ee394b16fa62de04af248b5609c81baa1a2e9295
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.C
@@ -0,0 +1,88 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 "indexedVertexEnum.H"
+#include "Pstream.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+template<>
+const char*
+Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 10>::names[] =
+{
+    "Unassigned",
+    "Internal",
+    "InternalNearBoundary",
+    "InternalSurface",
+    "InternalFeatureEdge",
+    "InternalFeaturePoint",
+    "ExternalSurface",
+    "ExternalFeatureEdge",
+    "ExternalFeaturePoint",
+    "Far"
+};
+
+const Foam::NamedEnum<Foam::indexedVertexEnum::vertexType, 10>
+Foam::indexedVertexEnum::vertexTypeNames_;
+
+
+template<>
+const char*
+Foam::NamedEnum<Foam::indexedVertexEnum::vertexMotion, 2>::names[] =
+{
+    "fixed",
+    "movable"
+};
+
+const Foam::NamedEnum<Foam::indexedVertexEnum::vertexMotion, 2>
+vertexMotionNames_;
+
+
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const Foam::indexedVertexEnum::vertexType& v
+)
+{
+    os  << static_cast<int>(v);
+
+    return os;
+}
+
+Foam::Istream& Foam::operator>>
+(
+    Istream& is,
+    Foam::indexedVertexEnum::vertexType& v
+)
+{
+    int type;
+    is  >> type;
+
+    v = static_cast<Foam::indexedVertexEnum::vertexType>(type);
+
+    return is;
+}
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H
new file mode 100644
index 0000000000000000000000000000000000000000..c597d8a17307cf790fee28c068f857c7c5f68691
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexEnum.H
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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
+    indexedVertexEnum
+
+Description
+
+SourceFiles
+    indexedVertexEnum.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef indexedVertexEnum_H
+#define indexedVertexEnum_H
+
+#include "NamedEnum.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+class indexedVertexEnum
+{
+public:
+
+    enum vertexType
+    {
+        vtUnassigned            = 0,
+        vtInternal              = 1,
+        vtInternalNearBoundary  = 2,
+        vtInternalSurface       = 3,
+        vtInternalFeatureEdge   = 4,
+        vtInternalFeaturePoint  = 5,
+        vtExternalSurface       = 6,
+        vtExternalFeatureEdge   = 7,
+        vtExternalFeaturePoint  = 8,
+        vtFar                   = 9
+    };
+
+    enum vertexMotion
+    {
+        fixed   = 0,
+        movable = 1
+    };
+
+    static const Foam::NamedEnum<vertexType, 10> vertexTypeNames_;
+
+    static const Foam::NamedEnum<vertexMotion, 2> vertexMotionNames_;
+
+    friend Ostream& operator<<(Foam::Ostream&, const vertexType&);
+
+    friend Istream& operator>>(Foam::Istream&, vertexType&);
+};
+
+
+template<>
+inline bool contiguous<indexedVertexEnum>()
+{
+    return true;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H
similarity index 56%
rename from applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H
rename to applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H
index f427316fc544e10a9371d2e1bdce365a9e8dd396..02d37c1b05caa7cd82d4a3d3317cfd5c25121a66 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex/indexedVertexI.H
@@ -21,25 +21,21 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 \*---------------------------------------------------------------------------*/
 
+#include "Pstream.H"
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Gt, class Vb>
 inline CGAL::indexedVertex<Gt, Vb>::indexedVertex()
 :
     Vb(),
-    index_(vtInternal),
-    type_(vtInternal),
-    alignment_(),
-    targetCellSize_(0.0),
-    vertexFixed_(false),
-    nearProcBoundary_(false)
+    type_(vtUnassigned),
+    index_(vtUnassigned),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
 {}
 
 
@@ -47,12 +43,43 @@ template<class Gt, class Vb>
 inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(const Point& p)
 :
     Vb(p),
-    index_(vtInternal),
-    type_(vtInternal),
-    alignment_(),
-    targetCellSize_(0.0),
-    vertexFixed_(false),
-    nearProcBoundary_(false)
+    type_(vtUnassigned),
+    index_(vtUnassigned),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
+{}
+
+
+template<class Gt, class Vb>
+inline CGAL::indexedVertex<Gt, Vb>::indexedVertex
+(
+    const Point& p,
+    vertexType type
+)
+:
+    Vb(p),
+    type_(type),
+    index_(-1),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
+{}
+
+
+template<class Gt, class Vb>
+inline CGAL::indexedVertex<Gt, Vb>::indexedVertex
+(
+    const Foam::point& p,
+    vertexType type
+)
+:
+    Vb(Point(p.x(), p.y(), p.z())),
+    type_(type),
+    index_(-1),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
 {}
 
 
@@ -61,16 +88,16 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex
 (
     const Point& p,
     int index,
-    int type
+    vertexType type,
+    int processor
 )
 :
     Vb(p),
-    index_(index),
     type_(type),
-    alignment_(),
-    targetCellSize_(0.0),
-    vertexFixed_(false),
-    nearProcBoundary_(false)
+    index_(index),
+    processor_(processor),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
 {}
 
 
@@ -78,12 +105,11 @@ template<class Gt, class Vb>
 inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(const Point& p, Cell_handle f)
 :
     Vb(f, p),
-    index_(vtInternal),
-    type_(vtInternal),
-    alignment_(),
-    targetCellSize_(0.0),
-    vertexFixed_(false),
-    nearProcBoundary_(false)
+    type_(vtUnassigned),
+    index_(vtUnassigned),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
 {}
 
 
@@ -91,12 +117,11 @@ template<class Gt, class Vb>
 inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(Cell_handle f)
 :
     Vb(f),
-    index_(vtInternal),
-    type_(vtInternal),
-    alignment_(),
-    targetCellSize_(0.0),
-    vertexFixed_(false),
-    nearProcBoundary_(false)
+    type_(vtUnassigned),
+    index_(vtUnassigned),
+    processor_(Foam::Pstream::myProcNo()),
+    alignment_(Foam::tensor::zero),
+    targetCellSize_(0.0)
 {}
 
 
@@ -117,14 +142,16 @@ inline int CGAL::indexedVertex<Gt, Vb>::index() const
 
 
 template<class Gt, class Vb>
-inline int& CGAL::indexedVertex<Gt, Vb>::type()
+inline typename CGAL::indexedVertex<Gt, Vb>::vertexType&
+CGAL::indexedVertex<Gt, Vb>::type()
 {
     return type_;
 }
 
 
 template<class Gt, class Vb>
-inline int CGAL::indexedVertex<Gt, Vb>::type() const
+inline typename CGAL::indexedVertex<Gt, Vb>::vertexType
+CGAL::indexedVertex<Gt, Vb>::type() const
 {
     return type_;
 }
@@ -161,7 +188,7 @@ inline Foam::scalar CGAL::indexedVertex<Gt, Vb>::targetCellSize() const
 template<class Gt, class Vb>
 inline bool CGAL::indexedVertex<Gt, Vb>::uninitialised() const
 {
-    return type_ == vtInternal && index_ == vtInternal;
+    return type_ == vtUnassigned;
 }
 
 
@@ -175,63 +202,41 @@ inline bool CGAL::indexedVertex<Gt, Vb>::farPoint() const
 template<class Gt, class Vb>
 inline bool CGAL::indexedVertex<Gt, Vb>::internalPoint() const
 {
-    return internalPoint(type_);
-}
-
-
-template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::internalPoint(int type)
-{
-    return type <= vtInternal;
+    return type_ == vtInternal || type_ == vtInternalNearBoundary;
 }
 
 
 template<class Gt, class Vb>
 inline bool CGAL::indexedVertex<Gt, Vb>::referred() const
 {
-    return (type_ < 0 && type_ > vtFar);
-}
-
-
-template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::referredInternalOrBoundaryPoint() const
-{
-    return referred() && index_ >= 0;
-}
-
+    // Can't be zero as the first few points are far points which won't be
+    // referred
+    //return index_ < 0;
 
-template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::referredExternal() const
-{
-    return referred() && index_ < 0;
+    // processor_ will be take the value of the processor that this vertex is
+    // from, so it cannot be on this processor.
+    return processor_ != Foam::Pstream::myProcNo();
 }
 
 
 template<class Gt, class Vb>
 inline bool CGAL::indexedVertex<Gt, Vb>::real() const
 {
-    return internalPoint() || pairPoint();
+    return (internalPoint() || boundaryPoint()) && !referred();
 }
 
 
 template<class Gt, class Vb>
 inline int CGAL::indexedVertex<Gt, Vb>::procIndex() const
 {
-    if (referred())
-    {
-        return -(type_ + 1);
-    }
-    else
-    {
-        return -1;
-    }
+    return processor_;
 }
 
 
 template<class Gt, class Vb>
-inline int CGAL::indexedVertex<Gt, Vb>::encodeProcIndex(int procI)
+inline int& CGAL::indexedVertex<Gt, Vb>::procIndex()
 {
-    return -(procI + 1);
+    return processor_;
 }
 
 
@@ -245,115 +250,85 @@ inline void CGAL::indexedVertex<Gt, Vb>::setInternal()
 template<class Gt, class Vb>
 inline bool CGAL::indexedVertex<Gt, Vb>::nearBoundary() const
 {
-    return type_ == vtNearBoundary;
+    return type_ == vtInternalNearBoundary;
 }
 
 
 template<class Gt, class Vb>
 inline void CGAL::indexedVertex<Gt, Vb>::setNearBoundary()
 {
-    type_ = vtNearBoundary;
-}
-
-
-template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::nearProcBoundary() const
-{
-    return nearProcBoundary_;
-}
-
-
-template<class Gt, class Vb>
-inline void CGAL::indexedVertex<Gt, Vb>::setNearProcBoundary()
-{
-    nearProcBoundary_ = true;
+    type_ = vtInternalNearBoundary;
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::pairPoint() const
+inline bool CGAL::indexedVertex<Gt, Vb>::boundaryPoint() const
 {
-    return type_ >= 0;
+    return type_ >= vtInternalSurface && !farPoint();
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::ppMaster() const
-{
-    return ppMaster(index_, type_);
-}
-
-
-template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::ppMaster(int index, int type)
+inline bool CGAL::indexedVertex<Gt, Vb>::internalOrBoundaryPoint() const
 {
-    if (index >= 0 && type > index)
-    {
-        return true;
-    }
-
-    return false;
+    return internalPoint() || internalBoundaryPoint();
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::ppSlave() const
+inline bool CGAL::indexedVertex<Gt, Vb>::nearOrOnBoundary() const
 {
-    if (type_ >= 0 && type_ < index_)
-    {
-        return true;
-    }
-    else
-    {
-        return false;
-    }
+    return boundaryPoint() || nearBoundary();
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::internalOrBoundaryPoint() const
+inline bool CGAL::indexedVertex<Gt, Vb>::internalBoundaryPoint() const
 {
-    return internalOrBoundaryPoint(index_, type_);
+    return type_ >= vtInternalSurface && type_ <= vtInternalFeaturePoint;
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::internalOrBoundaryPoint
-(
-    int index,
-    int type
-)
+inline bool CGAL::indexedVertex<Gt, Vb>::externalBoundaryPoint() const
 {
-    return internalPoint(type) || ppMaster(index, type);
+    return type_ >= vtExternalSurface && type_ <= vtExternalFeaturePoint;
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::nearOrOnBoundary() const
+inline bool CGAL::indexedVertex<Gt, Vb>::featurePoint() const
 {
-    return pairPoint() || nearBoundary();
+    return type_ == vtInternalFeaturePoint || type_ == vtExternalFeaturePoint;
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::anyInternalOrBoundaryPoint() const
+inline bool CGAL::indexedVertex<Gt, Vb>::featureEdgePoint() const
 {
-    return internalOrBoundaryPoint() || referredInternalOrBoundaryPoint();
+    return type_ == vtInternalFeatureEdge || type_ == vtExternalFeatureEdge;
 }
 
 
 template<class Gt, class Vb>
-inline bool CGAL::indexedVertex<Gt, Vb>::isVertexFixed() const
+inline bool CGAL::indexedVertex<Gt, Vb>::surfacePoint() const
 {
-    return vertexFixed_;
+    return type_ == vtInternalSurface || type_ == vtExternalSurface;
 }
 
 
-template<class Gt, class Vb>
-inline void CGAL::indexedVertex<Gt, Vb>::setVertexFixed()
-{
-    vertexFixed_ = true;
-}
+//template<class Gt, class Vb>
+//inline bool CGAL::indexedVertex<Gt, Vb>::isVertexFixed() const
+//{
+//    return vertexFixed_;
+//}
+//
+//
+//template<class Gt, class Vb>
+//inline void CGAL::indexedVertex<Gt, Vb>::setVertexFixed()
+//{
+//    vertexFixed_ = true;
+//}
 
 
 // * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointConversion.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointConversion.H
new file mode 100644
index 0000000000000000000000000000000000000000..6242a3a6feab4f4ccd89542efe3bca4c29a07a55
--- /dev/null
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointConversion.H
@@ -0,0 +1,99 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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
+    pointConversion
+
+Description
+
+    Conversion functions between point (FOAM::) and Point (CGAL)
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pointConversion_H
+#define pointConversion_H
+
+#include "point.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef CGAL_INEXACT
+
+    // Define Point to be contiguous for inexact (double storage) kernel
+    typedef const Foam::point& pointFromPoint;
+    typedef const CGAL::Triangulation_vertex_base_3<K>::Point& PointFrompoint;
+
+#else
+
+    typedef Foam::point pointFromPoint;
+    typedef CGAL::Triangulation_vertex_base_3<K>::Point PointFrompoint;
+
+#endif
+
+namespace Foam
+{
+
+#ifdef CGAL_INEXACT
+
+    template<typename Point>
+    inline pointFromPoint topoint(const Point& P)
+    {
+        return reinterpret_cast<pointFromPoint>(P);
+    }
+
+    template<typename Point>
+    inline PointFrompoint toPoint(const Foam::point& p)
+    {
+        return reinterpret_cast<PointFrompoint>(p);
+    }
+
+#else
+
+    template<typename Point>
+    inline pointFromPoint topoint(const Point& P)
+    {
+        return Foam::point
+        (
+            CGAL::to_double(P.x()),
+            CGAL::to_double(P.y()),
+            CGAL::to_double(P.z())
+        );
+    }
+
+    template<typename Point>
+    inline Point toPoint(const Foam::point& p)
+    {
+        return Point(p.x(), p.y(), p.z());
+    }
+
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointFeatureEdgesTypes.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointFeatureEdgesTypes.H
index 8838487f1e5dae657ced3fe3fab48b6e7a154b84..5bae06d86f198c3e8bd8ec49cea7bed9c3168cf7 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointFeatureEdgesTypes.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/pointFeatureEdgesTypes.H
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Class
     pointFeatureEdgesTypes
 
@@ -48,28 +43,39 @@ namespace Foam
 \*---------------------------------------------------------------------------*/
 
 //- Hold the types of feature edges attached to the point.
-struct pointFeatureEdgesTypes
+class pointFeatureEdgesTypes
+:
+    public HashTable<label, extendedFeatureEdgeMesh::edgeStatus>
 {
-    label ptI;
-    label nExternal, nInternal;
-    label nFlat, nOpen, nMultiple, nNonFeature;
+    label pointLabel_;
+
+public:
 
     pointFeatureEdgesTypes(const label pointLabel)
-    {
-        ptI = pointLabel;
-        nExternal = nInternal = 0;
-        nFlat = nOpen = nMultiple = nNonFeature = 0;
-    }
+    :
+        HashTable<label, extendedFeatureEdgeMesh::edgeStatus>(),
+        pointLabel_(pointLabel)
+    {}
+
 
     friend Ostream& operator<<(Ostream& os, const pointFeatureEdgesTypes& p)
     {
-        os  << "E " << "I " << "F " << "O " << "M " << "N "
-            << "Pt" << nl
-            << p.nExternal << " " << p.nInternal << " "
-            << p.nFlat << " " << p.nOpen << " "
-            << p.nMultiple << " " << p.nNonFeature << " "
-            << p.ptI
-            << endl;
+        os  << "Point = " << p.pointLabel_ << endl;
+
+        for
+        (
+            HashTable<label, extendedFeatureEdgeMesh::edgeStatus>
+                ::const_iterator iter = p.cbegin();
+            iter != p.cend();
+            ++iter
+        )
+        {
+            os  << "    "
+                << extendedFeatureEdgeMesh::edgeStatusNames_[iter.key()]
+                << " = "
+                << iter()
+                << endl;
+        }
 
         return os;
     }
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
index 50d2384f24c149d8d573363d5469a283065f20bf..64f753fb99d102e5309f06c345f36c4bd996c590 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.C
@@ -117,7 +117,6 @@ Foam::conformationSurfaces::conformationSurfaces
             }
         }
 
-
         word featureMethod = surfaceSubDict.lookup("featureMethod");
 
         if (featureMethod == "extendedFeatureEdgeMesh")
@@ -230,7 +229,12 @@ Foam::conformationSurfaces::conformationSurfaces
 
     // Extend the global bounds to stop the bound box sitting on the surfaces
     // to be conformed to
-    globalBounds_ = globalBounds_.extend(rndGen_, 1e-4);
+    //globalBounds_ = globalBounds_.extend(rndGen_, 1e-4);
+
+    vector newSpan = 1e-4*globalBounds_.span();
+
+    globalBounds_.min() -= newSpan;
+    globalBounds_.max() += newSpan;
 
     // Look at all surfaces at determine whether the locationInMesh point is
     // inside or outside each, to establish a signature for the domain to be
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
index c1bdac76ba2ef772c19fc9dce17e3eadbd3f10fa..3acb10d53a86eefb61b311a240cd89244c82c815 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H
@@ -45,9 +45,6 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declaration of classes
-class conformalVoronoiMesh;
-
 /*---------------------------------------------------------------------------*\
                      Class conformationSurfaces Declaration
 \*---------------------------------------------------------------------------*/
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.C
index 15c82e64c5c9a9fdbb47ec73dc2affedc48bf7be..e65cbea4e9ebbbb7bfc6517418f44311998fd2b4 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.C
@@ -84,126 +84,42 @@ Foam::cvControls::cvControls
 
     // Controls for coarse surface conformation
 
-    const dictionary& coarseDict
+    const dictionary& conformationControlsDict
     (
-        surfDict.subDict("coarseConformationControls")
-    );
-
-    const dictionary& coarseInitialDict
-    (
-        coarseDict.subDict("initial")
-    );
-
-    const dictionary& coarseIterationDict
-    (
-        coarseDict.subDict("iteration")
+        surfDict.subDict("conformationControls")
     );
 
     surfacePtExclusionDistanceCoeff_ = readScalar
     (
-        coarseInitialDict.lookup("surfacePtExclusionDistanceCoeff")
-    );
-
-    edgeSearchDistCoeffSqr_coarse_initial_ = sqr
-    (
-        readScalar
-        (
-            coarseInitialDict.lookup("edgeSearchDistCoeff")
-        )
-    );
-
-    edgeSearchDistCoeffSqr_coarse_iteration_ = sqr
-    (
-        readScalar
-        (
-            coarseIterationDict.lookup("edgeSearchDistCoeff")
-        )
-    );
-
-    surfacePtReplaceDistCoeffSqr_coarse_initial_ = sqr
-    (
-        readScalar
-        (
-            coarseInitialDict.lookup("surfacePtReplaceDistCoeff")
-        )
-    );
-
-    surfacePtReplaceDistCoeffSqr_coarse_iteration_ = sqr
-    (
-        readScalar
-        (
-            coarseIterationDict.lookup("surfacePtReplaceDistCoeff")
-        )
-    );
-
-    maxConformationIterations_coarse_ = readLabel
-    (
-        coarseDict.lookup("maxIterations")
-    );
-
-    iterationToInitialHitRatioLimit_coarse_ = readScalar
-    (
-        coarseDict.lookup("iterationToInitialHitRatioLimit")
-    );
-
-    // Controls for fine surface conformation
-
-    const dictionary& fineDict
-    (
-        surfDict.subDict("fineConformationControls")
-    );
-
-    const dictionary& fineInitialDict
-    (
-        fineDict.subDict("initial")
-    );
-
-    const dictionary& fineIterationDict
-    (
-        fineDict.subDict("iteration")
+        conformationControlsDict.lookup("surfacePtExclusionDistanceCoeff")
     );
 
-    edgeSearchDistCoeffSqr_fine_initial_ = sqr
+    edgeSearchDistCoeffSqr_ = sqr
     (
         readScalar
         (
-            fineInitialDict.lookup("edgeSearchDistCoeff")
+            conformationControlsDict.lookup("edgeSearchDistCoeff")
         )
     );
 
-    edgeSearchDistCoeffSqr_fine_iteration_ = sqr
+    surfacePtReplaceDistCoeffSqr_ = sqr
     (
         readScalar
         (
-            fineIterationDict.lookup("edgeSearchDistCoeff")
+            conformationControlsDict.lookup("surfacePtReplaceDistCoeff")
         )
     );
 
-    surfacePtReplaceDistCoeffSqr_fine_initial_ = sqr
+    maxConformationIterations_ = readLabel
     (
-        readScalar
-        (
-            fineInitialDict.lookup("surfacePtReplaceDistCoeff")
-        )
-    );
-
-    surfacePtReplaceDistCoeffSqr_fine_iteration_ = sqr
-    (
-        readScalar
-        (
-            fineIterationDict.lookup("surfacePtReplaceDistCoeff")
-        )
+        conformationControlsDict.lookup("maxIterations")
     );
 
-    maxConformationIterations_fine_ = readLabel
+    iterationToInitialHitRatioLimit_ = readScalar
     (
-        fineDict.lookup("maxIterations")
+        conformationControlsDict.lookup("iterationToInitialHitRatioLimit")
     );
 
-    iterationToInitialHitRatioLimit_fine_ = readScalar
-    (
-        fineDict.lookup("iterationToInitialHitRatioLimit")
-    );
 
     // Motion control controls
 
@@ -279,248 +195,22 @@ Foam::cvControls::cvControls
 
     const dictionary& filteringDict(cvMeshDict_.subDict("polyMeshFiltering"));
 
-    writeTetDualMesh_ = Switch(filteringDict.lookup("writeTetDualMesh"));
-
-    filterSizeCoeff_ = readScalar
-    (
-        filteringDict.lookup("filterSizeCoeff")
-    );
-
-    mergeClosenessCoeff_ = readScalar
-    (
-        filteringDict.lookup("mergeClosenessCoeff")
-    );
-
-    edgeMergeAngle_ = readScalar
-    (
-        filteringDict.lookup("edgeMergeAngle")
-    );
-
-    continueFilteringOnBadInitialPolyMesh_ = Switch
-    (
-        filteringDict.lookupOrDefault<Switch>
-        (
-            "continueFilteringOnBadInitialPolyMesh",
-            false
-        )
-    );
-
-    filterErrorReductionCoeff_ = readScalar
-    (
-        filteringDict.lookup("filterErrorReductionCoeff")
-    );
-
-    filterCountSkipThreshold_ = readLabel
-    (
-        filteringDict.lookup("filterCountSkipThreshold")
-    );
-
-    maxCollapseIterations_ = readLabel
-    (
-        filteringDict.lookup("maxCollapseIterations")
-    );
-
-    maxConsecutiveEqualFaceSets_ = readLabel
-    (
-        filteringDict.lookup("maxConsecutiveEqualFaceSets")
-    );
-
-    surfaceStepFaceAngle_ = readScalar
-    (
-        filteringDict.lookup("surfaceStepFaceAngle")
-    );
-
-    edgeCollapseGuardFraction_ = readScalar
+    filterEdges_ = Switch
     (
-        filteringDict.lookup("edgeCollapseGuardFraction")
+        filteringDict.lookupOrDefault<Switch>("filterEdges", true)
     );
 
-    maxCollapseFaceToPointSideLengthCoeff_ = readScalar
+    filterFaces_ = Switch
     (
-        filteringDict.lookup("maxCollapseFaceToPointSideLengthCoeff")
+        filteringDict.lookupOrDefault<Switch>("filterFaces", false)
     );
-}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-Foam::scalar Foam::cvControls::edgeSearchDistCoeffSqrInitial
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
-    {
-        return edgeSearchDistCoeffSqr_coarse_initial_;
-    }
-
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return edgeSearchDistCoeffSqr_fine_initial_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::edgeSearchDistCoeffSqrInitial"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
-}
-
-
-Foam::scalar Foam::cvControls::edgeSearchDistCoeffSqrIteration
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
-    {
-        return edgeSearchDistCoeffSqr_coarse_iteration_;
-    }
-
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return edgeSearchDistCoeffSqr_fine_iteration_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::edgeSearchDistCoeffSqrIteration"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
-}
-
-
-Foam::scalar Foam::cvControls::surfacePtReplaceDistCoeffSqrInitial
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
-    {
-        return surfacePtReplaceDistCoeffSqr_coarse_initial_;
-    }
-
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return surfacePtReplaceDistCoeffSqr_fine_initial_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::surfacePtReplaceDistCoeffSqrInitial"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
-}
-
-
-Foam::scalar Foam::cvControls::surfacePtReplaceDistCoeffSqrIteration
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
-    {
-        return surfacePtReplaceDistCoeffSqr_coarse_iteration_;
-    }
-
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return surfacePtReplaceDistCoeffSqr_fine_iteration_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::surfacePtReplaceDistCoeffSqrIteration"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
-}
-
-
-Foam::label Foam::cvControls::maxConformationIterations
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
-    {
-        return maxConformationIterations_coarse_;
-    }
-
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return maxConformationIterations_fine_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::maxConformationIterations"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
-}
 
-
-Foam::scalar Foam::cvControls::iterationToInitialHitRatioLimit
-(
-    int reconfMode
-) const
-{
-    if (reconfMode == conformalVoronoiMesh::rmCoarse)
+    if (filterFaces_)
     {
-        return iterationToInitialHitRatioLimit_coarse_;
+        filterEdges_ = Switch::ON;
     }
 
-    else if (reconfMode == conformalVoronoiMesh::rmFine)
-    {
-        return iterationToInitialHitRatioLimit_fine_;
-    }
-    else
-    {
-        FatalErrorIn
-        (
-            "Foam::cvControls::iterationToInitialHitRatioLimit"
-            "("
-                "int reconfMode"
-            ") const"
-        )   << "Unknown reconformationMode " << reconfMode
-            << exit(FatalError);
-    }
-
-    return 0;
+    writeTetDualMesh_ = Switch(filteringDict.lookup("writeTetDualMesh"));
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.H
index 58dd06fc741ee6b1c88dc14a5d1cd6756de93692..e8184753b0b6af1bf2914e4c8a4b20dae8cd6811 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControls.H
@@ -37,6 +37,7 @@ SourceFiles
 
 #include "dictionary.H"
 #include "Switch.H"
+#include "vector.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -106,74 +107,21 @@ class cvControls
 
                 //- Distance to search for feature edges near to
                 //  surface protrusions - fraction of the local target
-                //  cell size. Coarse conformation, initial protrusion
-                //  tests.
-                scalar edgeSearchDistCoeffSqr_coarse_initial_;
-
-                //- Distance to search for feature edges near to
-                //  surface protrusions - fraction of the local target
-                //  cell size. Coarse conformation, iteration
-                //  protrusion tests.
-                scalar edgeSearchDistCoeffSqr_coarse_iteration_;
-
-                //- Proximity to a feature edge where a surface hit is
-                //  not created, only the edge conformation is created
-                //  - fraction of the local target cell size. Coarse
-                //  conformation, initial protrusion tests.
-                scalar surfacePtReplaceDistCoeffSqr_coarse_initial_;
+                //  cell size.
+                scalar edgeSearchDistCoeffSqr_;
 
                 //- Proximity to a feature edge where a surface hit is
                 //  not created, only the edge conformation is created
-                //  - fraction of the local target cell size. Coarse
-                //  conformation, iteration protrusion tests.
-                scalar surfacePtReplaceDistCoeffSqr_coarse_iteration_;
+                //  - fraction of the local target cell size.
+                scalar surfacePtReplaceDistCoeffSqr_;
 
-                //- Maximum allowed number coarse surface conformation
-                //  iterations.
-                label maxConformationIterations_coarse_;
+                //- Maximum allowed number surface conformation iterations.
+                label maxConformationIterations_;
 
-                //- Termination criterion for coarse surface
-                //  conformation iterations.  When the number of
-                //  surface protrusions drops below this ratio of the
-                //  initial number of protrusions.
-                scalar iterationToInitialHitRatioLimit_coarse_;
-
-
-            // Controls for fine surface conformation
-
-                //- Distance to search for feature edges near to
-                //  surface protrusions - fraction of the local target
-                //  cell size. Fine conformation, initial protrusion
-                //  tests.
-                scalar edgeSearchDistCoeffSqr_fine_initial_;
-
-                //- Distance to search for feature edges near to
-                //  surface protrusions - fraction of the local target
-                //  cell size. Fine conformation, iteration protrusion
-                //  tests.
-                scalar edgeSearchDistCoeffSqr_fine_iteration_;
-
-                //- Proximity to a feature edge where a surface hit is
-                //  not created, only the edge conformation is created
-                //  - fraction of the local target cell size. Fine
-                //  conformation, initial protrusion tests.
-                scalar surfacePtReplaceDistCoeffSqr_fine_initial_;
-
-                //- Proximity to a feature edge where a surface hit is
-                //  not created, only the edge conformation is created
-                //  - fraction of the local target cell size. Fine
-                //  conformation, iteration protrusion tests.
-                scalar surfacePtReplaceDistCoeffSqr_fine_iteration_;
-
-                //- Maximum allowed number fine surface conformation
-                //  iterations.
-                label maxConformationIterations_fine_;
-
-                //- Termination criterion for fine surface conformation
-                //  iterations.  When the number of surface protrusions
-                //  drops below this ratio of the initial number of
-                //  protrusions.
-                scalar iterationToInitialHitRatioLimit_fine_;
+                //- Termination criterion for conformation iterations.
+                //  When the number of surface protrusions drops below this
+                //  ratio of the initial number of protrusions.
+                scalar iterationToInitialHitRatioLimit_;
 
 
     // Motion control controls
@@ -198,6 +146,7 @@ class cvControls
         //- Now often to re-store the size and alignment data
         label sizeAndAlignmentRebuildFrequency_;
 
+
         // Point insertion criteria
 
             //- Length between Delaunay vertices above which a new Dv should be
@@ -223,66 +172,14 @@ class cvControls
 
     // polyMesh filtering controls
 
-        //- Write tet mesh at output time (it always writes the Voronoi)
-        Switch writeTetDualMesh_;
+        //- Activates the mesh edge filtering. On by default.
+        Switch filterEdges_;
 
-        //- Upper limit on the size of faces to be filtered from,
-        //  fraction of the local target cell size
-        scalar filterSizeCoeff_;
-
-        //- Upper limit on how close two dual vertices can be before
-        //  being merged, fraction of the local target cell size
-        scalar mergeClosenessCoeff_;
-
-        //- If the angle between two dual edges that are connected by a single
-        //  point is less than this angle, then the edges will be merged into a
-        //  single edge.
-        scalar edgeMergeAngle_;
-
-        //- If the mesh quality criteria cannot be satisfied, continue
-        //  with filtering anyway?
-        Switch continueFilteringOnBadInitialPolyMesh_;
-
-        //- When a face is "bad", what fraction should the filterSizeCoeff_ be
-        //  reduced by.  Recursive, so for a filterCount value of fC, the
-        //  filterSizeCoeff is reduced by pow(filterErrorReductionCoeff_, fC)
-        scalar filterErrorReductionCoeff_;
-
-        //- Maximum number of filterCount applications before a face
-        //  is not attempted to be filtered
-        label filterCountSkipThreshold_;
-
-        //- Maximum number of permissible iterations of the face collapse
-        //  algorithm.  The value to choose will be related the maximum number
-        //  of points on a face that is to be collapsed and how many faces
-        //  around it need to be collapsed.
-        label maxCollapseIterations_;
-
-        //- Maximum number of times an to allow an equal faceSet to be
-        //  returned from the face quality assessment before stopping iterations
-        //  to break an infinitie loop.
-        label maxConsecutiveEqualFaceSets_;
-
-        //- The maximum allowed angle between a boundary face normal and the
-        //  local surface normal before face will be aggressively collapsed
-        scalar surfaceStepFaceAngle_;
-
-        //- Defining how close to the midpoint (M) of the projected
-        //  vertices line a projected vertex (X) can be before making
-        //  an edge collapse invalid
-        //
-        //  X---X-g----------------M----X-----------g----X--X
-        //
-        //  Only allow a collapse if all projected vertices are
-        //  outwith edgeCollapseGuardFraction (g) of the distance form
-        //  the face centre to the furthest vertex in the considered
-        //  direction
-        scalar edgeCollapseGuardFraction_;
+        //- Activates the mesh face filtering. Off by default.
+        Switch filterFaces_;
 
-        //- The maximum allowed length of the longest edge of a face
-        //  to enable a face to be collapsed to a point, fraction of
-        //  the local target cell size
-        scalar maxCollapseFaceToPointSideLengthCoeff_;
+        //- Write tet mesh at output time (it always writes the Voronoi)
+        Switch writeTetDualMesh_;
 
 
     // Private Member Functions
@@ -346,30 +243,17 @@ public:
             //- Return the surfaceConformationRebuildFrequency
             inline label surfaceConformationRebuildFrequency() const;
 
-            //- Return the edgeSearchDistCoeffSqr for initial
-            //  conformation for the given reconformationMode.
-            scalar edgeSearchDistCoeffSqrInitial(int reconfMode) const;
-
-            //- Return the edgeSearchDistCoeffSqr for conformation
-            //  iterations for the given reconformationMode.
-            scalar edgeSearchDistCoeffSqrIteration(int reconfMode) const;
+            //- Return the edgeSearchDistCoeffSqr for conformation.
+            scalar edgeSearchDistCoeffSqr() const;
 
-            //- Return the surfacePtReplaceDistCoeffSqr for initial
-            //  conformation for the given reconformationMode.
-            scalar surfacePtReplaceDistCoeffSqrInitial(int reconfMode) const;
+            //- Return the surfacePtReplaceDistCoeffSqr for conformation.
+            scalar surfacePtReplaceDistCoeffSqr() const;
 
-            //- Return the surfacePtReplaceDistCoeffSqr for
-            //  conformation iterations for the given
-            //  reconformationMode.
-            scalar surfacePtReplaceDistCoeffSqrIteration(int reconfMode) const;
+            //- Return the maxConformationIterations
+            label maxConformationIterations() const;
 
-            //- Return the maxConformationIterations for the given
-            //  reconformationMode.
-            label maxConformationIterations(int reconfMode) const;
-
-            //- Return the iterationToInitialHitRatioLimit for the
-            //  given reconformationMode.
-            scalar iterationToInitialHitRatioLimit(int reconfMode) const;
+            //- Return the iterationToInitialHitRatioLimit
+            scalar iterationToInitialHitRatioLimit() const;
 
             //- Return the objOutput Switch
             inline Switch objOutput() const;
@@ -389,6 +273,12 @@ public:
             //- Return the sizeAndAlignmentRebuildFrequency
             inline label sizeAndAlignmentRebuildFrequency() const;
 
+            //- Return the aspectRatio
+            inline scalar aspectRatio() const;
+
+            //- Return the aspectRatioDirection
+            inline const vector& aspectRatioDirection() const;
+
             //- Return the insertionDistCoeff
             inline scalar insertionDistCoeff() const;
 
@@ -401,44 +291,14 @@ public:
             //- Return removalDistCoeff
             inline scalar removalDistCoeff() const;
 
-            //- Write tetMesh at output time
-            inline Switch writeTetDualMesh() const;
-
-            //- Return the filterSizeCoeff
-            inline scalar filterSizeCoeff() const;
+            //- Filter edges at output time
+            inline Switch filterEdges() const;
 
-            //- Return the mergeClosenessCoeff
-            inline scalar mergeClosenessCoeff() const;
+            //- Filter faces at output time
+            inline Switch filterFaces() const;
 
-            //- Return the edgeMergeAngle
-            inline scalar edgeMergeAngle() const;
-
-            //- Return the continueFilteringOnBadInitialPolyMesh Switch
-            inline Switch continueFilteringOnBadInitialPolyMesh() const;
-
-            //- Return the filterErrorReductionCoeff
-            inline scalar filterErrorReductionCoeff() const;
-
-            //- Return the maxCollapseIterations
-            inline label maxCollapseIterations() const;
-
-            //- Return the maxConsecutiveEqualFaceSets
-            inline label maxConsecutiveEqualFaceSets() const;
-
-            //- Return the filterCountSkipThreshold
-            inline label filterCountSkipThreshold() const;
-
-            //- Return the maxCollapseIterations
-            inline label minCollapseFaces() const;
-
-            //- Return the surfaceStepFaceAngle
-            inline scalar surfaceStepFaceAngle() const;
-
-            //- Return the edgeCollapseGuardFraction
-            inline scalar edgeCollapseGuardFraction() const;
-
-            //- Return the maxCollapseFaceToPointSideLengthCoeff
-            inline scalar maxCollapseFaceToPointSideLengthCoeff() const;
+            //- Write tetMesh at output time
+            inline Switch writeTetDualMesh() const;
 };
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControlsI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControlsI.H
index 50df7e8f5841b36d61322b0931f6840a4de52cf1..befc7b5666ac0c84f320419ae0fa69e481c728fa 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControlsI.H
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/cvControls/cvControlsI.H
@@ -88,6 +88,30 @@ inline Foam::label Foam::cvControls::surfaceConformationRebuildFrequency() const
 }
 
 
+inline Foam::scalar Foam::cvControls::edgeSearchDistCoeffSqr() const
+{
+    return edgeSearchDistCoeffSqr_;
+}
+
+
+inline Foam::scalar Foam::cvControls::surfacePtReplaceDistCoeffSqr() const
+{
+    return surfacePtReplaceDistCoeffSqr_;
+}
+
+
+inline Foam::label Foam::cvControls::maxConformationIterations() const
+{
+    return maxConformationIterations_;
+}
+
+
+inline Foam::scalar Foam::cvControls::iterationToInitialHitRatioLimit() const
+{
+    return iterationToInitialHitRatioLimit_;
+}
+
+
 inline Foam::Switch Foam::cvControls::objOutput() const
 {
     return objOutput_;
@@ -148,77 +172,19 @@ inline Foam::scalar Foam::cvControls::removalDistCoeff() const
 }
 
 
-inline Foam::Switch Foam::cvControls::writeTetDualMesh() const
-{
-    return writeTetDualMesh_;
-}
-
-
-inline Foam::scalar Foam::cvControls::filterSizeCoeff() const
-{
-    return filterSizeCoeff_;
-}
-
-
-inline Foam::scalar Foam::cvControls::mergeClosenessCoeff() const
-{
-    return mergeClosenessCoeff_;
-}
-
-
-inline Foam::scalar Foam::cvControls::edgeMergeAngle() const
-{
-    return edgeMergeAngle_;
-}
-
-
-inline Foam::Switch
-Foam::cvControls::continueFilteringOnBadInitialPolyMesh() const
+inline Foam::Switch Foam::cvControls::filterEdges() const
 {
-    return continueFilteringOnBadInitialPolyMesh_;
+    return filterEdges_;
 }
 
-
-inline Foam::scalar Foam::cvControls::filterErrorReductionCoeff() const
+inline Foam::Switch Foam::cvControls::filterFaces() const
 {
-    return filterErrorReductionCoeff_;
+    return filterFaces_;
 }
 
-
-inline Foam::label Foam::cvControls::filterCountSkipThreshold() const
-{
-    return filterCountSkipThreshold_;
-}
-
-
-inline Foam::label Foam::cvControls::maxCollapseIterations() const
-{
-    return maxCollapseIterations_;
-}
-
-
-inline Foam::label Foam::cvControls::maxConsecutiveEqualFaceSets() const
-{
-    return maxConsecutiveEqualFaceSets_;
-}
-
-
-inline Foam::scalar Foam::cvControls::surfaceStepFaceAngle() const
-{
-    return surfaceStepFaceAngle_;
-}
-
-
-inline Foam::scalar Foam::cvControls::edgeCollapseGuardFraction() const
-{
-    return edgeCollapseGuardFraction_;
-}
-
-
-inline Foam::scalar
-Foam::cvControls::maxCollapseFaceToPointSideLengthCoeff() const
+inline Foam::Switch Foam::cvControls::writeTetDualMesh() const
 {
-    return maxCollapseFaceToPointSideLengthCoeff_;
+    return writeTetDualMesh_;
 }
 
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/autoDensity/autoDensity.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/autoDensity/autoDensity.C
index 2b7d83f2b2ae1c7e37d187eae1a54e2255b471e0..0aace4f77fca09c19a7c72a0d1873672bdd62762 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/autoDensity/autoDensity.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/autoDensity/autoDensity.C
@@ -339,7 +339,7 @@ bool Foam::autoDensity::fillBox
 
         pointField corners(bb.points());
 
-        scalarField cornerSizes = cvMesh_.cellSizeControl().cellSize(corners);
+        scalarField cornerSizes = cvMesh_.cellShapeControls().cellSize(corners);
 
         Field<bool> insideCorners = combinedWellInside(corners, cornerSizes);
 
@@ -448,7 +448,7 @@ bool Foam::autoDensity::fillBox
                         );
                 }
 
-                lineSizes = cvMesh_.cellSizeControl().cellSize(linePoints);
+                lineSizes = cvMesh_.cellShapeControls().cellSize(linePoints);
 
                 Field<bool> insideLines = combinedWellInside
                 (
@@ -547,7 +547,7 @@ bool Foam::autoDensity::fillBox
         // corner when only some these points are required.
         shuffle(samplePoints);
 
-        scalarField sampleSizes = cvMesh_.cellSizeControl().cellSize
+        scalarField sampleSizes = cvMesh_.cellShapeControls().cellSize
         (
             samplePoints
         );
@@ -713,7 +713,7 @@ bool Foam::autoDensity::fillBox
 
             point p = min + cmptMultiply(span, rnd.vector01());
 
-            scalar localSize = cvMesh_.cellSizeControl().cellSize(p);
+            scalar localSize = cvMesh_.cellShapeControls().cellSize(p);
 
             bool insidePoint = false;
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/bodyCentredCubic/bodyCentredCubic.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/bodyCentredCubic/bodyCentredCubic.C
index 751a743e6d9c0b705985156c2b40e1754c70b942..c69e7ac8fb314d334c595d103e9dd70ffe7fd9fc 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/bodyCentredCubic/bodyCentredCubic.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/bodyCentredCubic/bodyCentredCubic.C
@@ -167,7 +167,7 @@ List<Vb::Point> bodyCentredCubic::initialPoints() const
                 minimumSurfaceDistanceCoeffSqr_
                *sqr
                 (
-                    cvMesh_.cellSizeControl().cellSize(points)
+                    cvMesh_.cellShapeControls().cellSize(points)
                 )
             );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/faceCentredCubic/faceCentredCubic.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/faceCentredCubic/faceCentredCubic.C
index a1c1f383b068728f3b6d7edf69675a2940495cc8..af2e7dfbf4d833d0e76585bc8c322bad152aa3a9 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/faceCentredCubic/faceCentredCubic.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/faceCentredCubic/faceCentredCubic.C
@@ -228,7 +228,7 @@ List<Vb::Point> faceCentredCubic::initialPoints() const
                 minimumSurfaceDistanceCoeffSqr_
                *sqr
                 (
-                    cvMesh_.cellSizeControl().cellSize(points)
+                    cvMesh_.cellShapeControls().cellSize(points)
                 )
             );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/pointFile/pointFile.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/pointFile/pointFile.C
index eb67cf60e241507af524755b8340142b14ea6600..19861f3e817b26968eca7e463f5ab5e01dddfdda 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/pointFile/pointFile.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/pointFile/pointFile.C
@@ -132,7 +132,7 @@ List<Vb::Point> pointFile::initialPoints() const
         minimumSurfaceDistanceCoeffSqr_
        *sqr
         (
-            cvMesh_.cellSizeControl().cellSize(points)
+            cvMesh_.cellShapeControls().cellSize(points)
         )
     );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/uniformGrid/uniformGrid.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/uniformGrid/uniformGrid.C
index 3bc914ea43b36ac1e70a4e461a2302e594aeb176..2538c90702d18efb3548ead731d88ab57bacf1ae 100644
--- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/uniformGrid/uniformGrid.C
+++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/initialPointsMethod/uniformGrid/uniformGrid.C
@@ -144,7 +144,7 @@ List<Vb::Point> uniformGrid::initialPoints() const
                 minimumSurfaceDistanceCoeffSqr_
                *sqr
                 (
-                    cvMesh_.cellSizeControl().cellSize(points)
+                    cvMesh_.cellShapeControls().cellSize(points)
                 )
             );
 
diff --git a/applications/utilities/mesh/generation/cvMesh/cvMesh.C b/applications/utilities/mesh/generation/cvMesh/cvMesh.C
index f15ebea29abb5ff77b1e8566a28d39a5d6050942..cf21964271a17bf2338271777471d3728700d2a5 100644
--- a/applications/utilities/mesh/generation/cvMesh/cvMesh.C
+++ b/applications/utilities/mesh/generation/cvMesh/cvMesh.C
@@ -21,11 +21,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-    As a special exception, you have permission to link this program with the
-    CGAL library and distribute executables, as long as you follow the
-    requirements of the GNU GPL in regard to all of the software in the
-    executable aside from CGAL.
-
 Application
     cvMesh
 
@@ -44,11 +39,6 @@ using namespace Foam;
 
 int main(int argc, char *argv[])
 {
-    argList::addBoolOption
-    (
-        "noFilter",
-        "Do not filter the mesh"
-    );
     Foam::argList::addBoolOption
     (
         "checkGeometry",
@@ -60,11 +50,8 @@ int main(int argc, char *argv[])
 
     runTime.functionObjects().off();
 
-    const bool noFilter = !args.optionFound("noFilter");
     const bool checkGeometry = args.optionFound("checkGeometry");
 
-    Info<< "Mesh filtering is " << (noFilter ? "on" : "off") << endl;
-
     IOdictionary cvMeshDict
     (
         IOobject
@@ -112,15 +99,9 @@ int main(int argc, char *argv[])
 
         Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
             << "  ClockTime = " << runTime.elapsedClockTime() << " s"
-            << nl << endl;
+            << endl;
     }
 
-    mesh.writeMesh(runTime.constant(), noFilter);
-
-    Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
-        << "  ClockTime = " << runTime.elapsedClockTime() << " s"
-        << nl << endl;
-
     Info<< nl << "End" << nl << endl;
 
     return 0;
diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/Make/options b/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/Make/options
index ed71a800294b791b6968359c38a257306d79da23..0322435c8c9c6d6512c5e3ec2e0a91e08199d84f 100644
--- a/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/Make/options
+++ b/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/Make/options
@@ -14,14 +14,14 @@ EXE_INC = \
     -I$(LIB_SRC)/triSurface/lnInclude \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
-    -I$(LIB_SRC)/fileFormats/lnInclude \
-    -I$(LIB_SRC)/sampling/lnInclude \
-    -I$(LIB_SRC)/dynamicMesh/lnInclude
+    -I$(LIB_SRC)/dynamicMesh/lnInclude \
+    -I../vectorTools
 
 EXE_LIBS = \
     $(CGAL_LIBS) \
     -lboost_thread \
     -lmpfr \
+    -lgmp \
     -lconformalVoronoiMesh \
     -ldecompositionMethods /* -L$(FOAM_LIBBIN)/dummy -lscotchDecomp */ \
     -ledgeMesh \
diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/cvMeshBackgroundMesh.C b/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/cvMeshBackgroundMesh.C
index 485c5568b4846f077ba4e6aabed1ccee647a91ff..53766c59a02c2209f86ae725362b7a24eb8edeb5 100644
--- a/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/cvMeshBackgroundMesh.C
+++ b/applications/utilities/mesh/generation/cvMesh/cvMeshBackgroundMesh/cvMeshBackgroundMesh.C
@@ -36,7 +36,7 @@ Description
 #include "triSurface.H"
 #include "searchableSurfaces.H"
 #include "conformationSurfaces.H"
-#include "cellSizeControlSurfaces.H"
+#include "cellShapeControl.H"
 #include "backgroundMeshDecomposition.H"
 #include "cellShape.H"
 #include "cellModeller.H"
@@ -450,10 +450,15 @@ int main(int argc, char *argv[])
         cvMeshDict.subDict("surfaceConformation")
     );
 
-    cellSizeControlSurfaces cellSizeControl
+    autoPtr<cellShapeControl> cellShapeControls
     (
-        allGeometry,
-        cvMeshDict.subDict("motionControl")
+        cellShapeControl::New
+        (
+            runTime,
+            cvMeshDict.subDict("motionControl"),
+            allGeometry,
+            geometryToConformTo
+        )
     );
 
 
@@ -464,7 +469,7 @@ int main(int argc, char *argv[])
 
         // Determine the number of cells in each direction.
         const vector span = bb.span();
-        vector nScalarCells = span/cellSizeControl.defaultCellSize();
+        vector nScalarCells = span/cellShapeControls().defaultCellSize();
 
         // Calculate initial cell size to be a little bit smaller than the
         // defaultCellSize to avoid initial refinement triggering.
@@ -580,7 +585,7 @@ int main(int argc, char *argv[])
         20.0,   //maxCellWeightCoeff
         runTime,
         geometryToConformTo,
-        cellSizeControl,
+        cellShapeControls(),
         rndGen,
         cvMeshDict
     );
diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshDict b/applications/utilities/mesh/generation/cvMesh/cvMeshDict
index 513d73573baba9fd0b01188b00a30fb9a0ef89a9..28f3b0043bc210b672a0b30d10fd035cc8bbeb19 100644
--- a/applications/utilities/mesh/generation/cvMesh/cvMeshDict
+++ b/applications/utilities/mesh/generation/cvMesh/cvMeshDict
@@ -263,7 +263,7 @@ initialPoints
 // It determines the cell size given a location. It then uses all
 // the rules
 // - defaultCellSize
-// - cellSizeControlGeometry
+// - cellShapeControl
 // to determine target cell size. Rule with highest priority wins. If same
 // priority smallest cell size wins.
 motionControl
@@ -271,10 +271,28 @@ motionControl
     // Absolute cell size of back ground mesh. This is the maximum cell size.
     defaultCellSize     0.00075;
 
-    // Assign a priority to all requests for cell sizes, the highest overrules.
-    defaultPriority     0;
+    //cellShapeControl    constantControl;
+    //cellShapeControl    fileControl;
+    cellShapeControl    surfaceControl;
 
-    cellSizeControlGeometry
+    // Provide constant values for cell size and alignment
+    constantControlCoeffs
+    {
+        cellSize      0.00075;
+        cellAlignment (1 0 0 0 1 0 0 0 1);
+    }
+
+    // Read in the points of the background grid used for cell shape control
+    // from a file, with corresponding files for alignment and size
+    fileControlCoeffs
+    {
+        pointFile       "";
+        sizesFile       "";
+        alignmentsFile  "";
+    }
+
+    // Calculate the sizes and alignments from surfaces
+    surfaceControlCoeffs
     {
         ref7_outside
         {
@@ -319,6 +337,16 @@ motionControl
         }
     }
 
+    // Provide an aspect ratio and the direction in which it acts on the mesh.
+    // Default is 1.0 if this section is not present in the dictionary
+    cellAspectRatioControl
+    {
+        // Aspect ratio.
+        aspectRatio                 2.0;
+        // Direction of action of the aspect ratio
+        aspectRatioDirection        (1 0 0);
+    }
+
     // Underrelaxation for point motion. Simulated annealing: starts off at 1
     // and lowers to 0 (at simulation endTime) to converge points.
     // adaptiveLinear is preferred choice.
@@ -396,6 +424,12 @@ motionControl
 // Do not change. See cvControls.H
 polyMeshFiltering
 {
+    // Filter small edges
+    filterEdges                             on;
+
+    // Filter small and sliver faces
+    filterFaces                             off;
+
     // Write the underlying Delaunay tet mesh at output time
     writeTetDualMesh                        false;  //true;
 
diff --git a/wmake/rules/General/CGAL b/wmake/rules/General/CGAL
index cfb02d716abda593740b3b21149e67ac1ffa9803..167a420ab6d938a0b176382123424ffc88b35576 100644
--- a/wmake/rules/General/CGAL
+++ b/wmake/rules/General/CGAL
@@ -7,4 +7,5 @@ CGAL_INC = \
 
 CGAL_LIBS = \
     -L$(MPFR_ARCH_PATH)/lib \
+    -L$(GMP_ARCH_PATH)/lib \
     -L$(BOOST_ARCH_PATH)/lib