diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
index 48b28a07e491f777ee2c718757f28dd3e4d28107..5297be327f2d6fe69f8725f0987f51a1b4c0f4aa 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
@@ -40,13 +40,14 @@ Description
 #include "rhoThermo.H"
 #include "turbulenceModel.H"
 #include "fixedGradientFvPatchFields.H"
+#include "zeroGradientFvPatchFields.H"
 #include "regionProperties.H"
 #include "compressibleCourantNo.H"
 #include "solidRegionDiffNo.H"
 #include "solidThermo.H"
 #include "radiationModel.H"
 #include "fvIOoptionList.H"
-
+#include "coordinateSystem.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
index d076652a1dd2b9759add875df934b731a11b3145..a3615c4309ad487272c631ce96d2c81a9834e0f8 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/chtMultiRegionSimpleFoam.C
@@ -37,6 +37,7 @@ Description
 #include "solidThermo.H"
 #include "radiationModel.H"
 #include "fvIOoptionList.H"
+#include "coordinateSystem.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
index 7573002af52e47423c72abede50f870fa812cdcf..93f7146730fb5180b92f1396fa4bf12698d052e3 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam/solid/solveSolid.H
@@ -3,7 +3,9 @@
     {
         fvScalarMatrix hEqn
         (
-           - fvm::laplacian(betav*alpha, h, "laplacian(alpha,h)")
+            thermo.isotropic()
+            ? -fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
+            : -fvm::laplacian(betav*tAnialpha(), h, "laplacian(alpha,h)")
            + fvOptions(rho, h)
         );
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H
index df3915980b546d54504a774b894929a170db062d..703ed6e4c2cde1456c96ebda5b01920793298c81 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/createSolidFields.H
@@ -1,4 +1,5 @@
     // Initialise solid field pointer lists
+    PtrList<coordinateSystem> coordinates(solidRegions.size());
     PtrList<solidThermo> thermos(solidRegions.size());
     PtrList<radiation::radiationModel> radiations(solidRegions.size());
     PtrList<fv::IOoptionList> solidHeatSources(solidRegions.size());
@@ -23,6 +24,16 @@
             new fv::IOoptionList(solidRegions[i])
         );
 
+        if (!thermos[i].isotropic())
+        {
+            Info<< "    Adding coordinateSystems\n" << endl;
+            coordinates.set
+            (
+                i,
+                coordinateSystem::New(solidRegions[i], thermos[i])
+            );
+        }
+
         IOobject betavSolidIO
         (
             "betavSolid",
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H
index ad8894a631552af47a127e7fbcaabc62b36f588a..a36fa7e98fcb163da272d8defcd3206033b79e9a 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/setRegionSolidFields.H
@@ -8,10 +8,36 @@
     tmp<volScalarField> tcp = thermo.Cp();
     const volScalarField& cp = tcp();
 
-    tmp<volScalarField> talpha = thermo.alpha();
-    const volScalarField& alpha = talpha();
-    tmp<volScalarField> tkappa = thermo.kappa();
-    const volScalarField& kappa = tkappa();
+    tmp<volSymmTensorField> tAnialpha;
+
+    if (!thermo.isotropic())
+    {
+        tmp<volVectorField> tkappaCp = thermo.Kappa()/cp;
+
+        const coordinateSystem& coodSys = coordinates[i];
+        tAnialpha =
+            tmp<volSymmTensorField>
+            (
+                new volSymmTensorField
+                (
+                    IOobject
+                    (
+                        "Anialpha",
+                        runTime.timeName(),
+                        mesh,
+                        IOobject::NO_READ,
+                        IOobject::NO_WRITE
+                    ),
+                    mesh,
+                    tkappaCp().dimensions(),
+                    zeroGradientFvPatchVectorField::typeName
+                )
+            );
+
+        volSymmTensorField& Anialpha = tAnialpha();
+        Anialpha.internalField() = coodSys.R().transformVector(tkappaCp());
+        Anialpha.correctBoundaryConditions();
+    }
 
     volScalarField& h = thermo.he();
 
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.C b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.C
index 437ea78327462d81682bd59c630399111835002f..9ec57f2f92fad8c27b2bbec760753fc0788bdcfe 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.C
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -56,38 +56,4 @@ Foam::scalar Foam::solidRegionDiffNo
     return DiNum;
 }
 
-
-Foam::scalar Foam::solidRegionDiffNo
-(
-    const fvMesh& mesh,
-    const Time& runTime,
-    const volScalarField& Cprho,
-    const volSymmTensorField& kappadirectional
-)
-{
-    scalar DiNum = 0.0;
-    scalar meanDiNum = 0.0;
-
-    volScalarField kappa(mag(kappadirectional));
-
-    //- Take care: can have fluid domains with 0 cells so do not test for
-    //  zero internal faces.
-    surfaceScalarField kapparhoCpbyDelta
-    (
-        mesh.surfaceInterpolation::deltaCoeffs()
-      * fvc::interpolate(kappa)
-      / fvc::interpolate(Cprho)
-    );
-
-    DiNum = gMax(kapparhoCpbyDelta.internalField())*runTime.deltaT().value();
-
-    meanDiNum = (average(kapparhoCpbyDelta)).value()*runTime.deltaT().value();
-
-    Info<< "Region: " << mesh.name() << " Diffusion Number mean: " << meanDiNum
-        << " max: " << DiNum << endl;
-
-    return DiNum;
-}
-
-
 // ************************************************************************* //
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.H
index cb4dd30b6a3801b7674abfe4a17c27e516a819e6..77eda7c843551345d460e98f5d371b3972df5217 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffNo.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -41,15 +41,6 @@ namespace Foam
         const volScalarField& Cprho,
         const volScalarField& kappa
     );
-
-    scalar solidRegionDiffNo
-    (
-        const fvMesh& mesh,
-        const Time& runTime,
-        const volScalarField& Cprho,
-        const volSymmTensorField& kappa
-    );
-
 }
 
 #endif
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H
index 878780baf1df939beceb7efde5ff738d5da93d84..a7a65b17bd4c9863a23d0749d64e3cbcb5af5348 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solidRegionDiffusionNo.H
@@ -1,18 +1,29 @@
-    scalar DiNum = -GREAT;
+scalar DiNum = -GREAT;
 
-    forAll(solidRegions, i)
+forAll(solidRegions, i)
+{
+    #include "setRegionSolidFields.H"
+
+    tmp<volScalarField> magKappa;
+    if (thermo.isotropic())
+    {
+        magKappa = thermo.kappa();
+    }
+    else
     {
-        #include "setRegionSolidFields.H"
+        magKappa = mag(thermo.Kappa());
+    }
 
-        DiNum = max
+    DiNum = max
+    (
+        solidRegionDiffNo
         (
-            solidRegionDiffNo
-            (
-                solidRegions[i],
-                runTime,
-                rho*cp,
-                kappa
-            ),
-            DiNum
-        );
-    }
+            solidRegions[i],
+            runTime,
+            rho*cp,
+            magKappa()
+        ),
+        DiNum
+    );
+
+}
diff --git a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
index 86f23292e37445c2cddc27fe4c651290e4cd9e1d..7bf7562d9b6736cff2e9c81cffdfe71a8b89f570 100644
--- a/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
+++ b/applications/solvers/heatTransfer/chtMultiRegionFoam/solid/solveSolid.H
@@ -9,7 +9,11 @@ if (finalIter)
         tmp<fvScalarMatrix> hEqn
         (
             fvm::ddt(betav*rho, h)
-          - fvm::laplacian(betav*alpha, h, "laplacian(alpha,h)")
+          - (
+               thermo.isotropic()
+             ? fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
+             : fvm::laplacian(betav*tAnialpha(), h, "laplacian(alpha,h)")
+            )
           ==
             fvOptions(rho, h)
         );
diff --git a/applications/test/PatchTools/Make/files b/applications/test/PatchTools/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..d148320dc59930d5d7a5428af43acb1a2ce70dc2
--- /dev/null
+++ b/applications/test/PatchTools/Make/files
@@ -0,0 +1,3 @@
+Test-PatchTools.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-PatchTools
diff --git a/applications/test/PatchTools/Make/options b/applications/test/PatchTools/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..3d00e249a66f6ee6588d843f9f96365eb695e931
--- /dev/null
+++ b/applications/test/PatchTools/Make/options
@@ -0,0 +1,7 @@
+EXE_INC = \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/surfMesh/lnInclude
+
+EXE_LIBS = \
+    -lfiniteVolume
diff --git a/applications/test/PatchTools/Test-PatchTools.C b/applications/test/PatchTools/Test-PatchTools.C
new file mode 100644
index 0000000000000000000000000000000000000000..4cf3eb0a0bf1adce5d52223349e10b8b7d3f6651
--- /dev/null
+++ b/applications/test/PatchTools/Test-PatchTools.C
@@ -0,0 +1,297 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012-2013 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
+    testPatchTools
+
+Description
+    Test app for PatchTools functionality
+
+\*---------------------------------------------------------------------------*/
+
+#include "PatchTools.H"
+#include "argList.H"
+#include "fvMesh.H"
+#include "volFields.H"
+#include "Time.H"
+#include "OBJstream.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//template<class PatchType>
+//Foam::tmp<Foam::pointField>
+//areaPointNormals
+//(
+//    const polyMesh& mesh,
+//    const PatchType& p,
+//    const labelList& meshFaces
+//)
+//{
+//    // Assume patch is smaller than the globalData().coupledPatch() (?) so
+//    // loop over patch meshPoints.
+//
+//    const labelList& meshPoints = p.meshPoints();
+//
+//    const globalMeshData& globalData = mesh.globalData();
+//    const indirectPrimitivePatch& coupledPatch = globalData.coupledPatch();
+//    const Map<label>& coupledPatchMP = coupledPatch.meshPointMap();
+//    const mapDistribute& map = globalData.globalPointSlavesMap();
+//    const globalIndexAndTransform& transforms =
+//        globalData.globalTransforms();
+//
+//
+//    // 1. Start off with local (area-weighted) normals
+//    //    (note:without calculating pointNormals
+//    //     to avoid them being stored)
+//
+//    tmp<pointField> textrudeN(new pointField(p.nPoints(), vector::zero));
+//    pointField& extrudeN = textrudeN();
+//    {
+//        const faceList& localFaces = p.localFaces();
+//        const vectorField& faceAreas = mesh.faceAreas();
+//
+//        forAll(localFaces, faceI)
+//        {
+//            const face& f = localFaces[faceI];
+//            const vector& n = faceAreas[meshFaces[faceI]];
+//            forAll(f, fp)
+//            {
+//                extrudeN[f[fp]] += n;
+//            }
+//        }
+//    }
+//
+//
+//    // Collect local pointFaces
+//    List<List<point> > pointFaceNormals(map.constructSize());
+//    {
+//        const vectorField& faceAreas = mesh.faceAreas();
+//
+//        forAll(meshPoints, patchPointI)
+//        {
+//            label meshPointI = meshPoints[patchPointI];
+//            Map<label>::const_iterator fnd = coupledPatchMP.find(meshPointI);
+//            if (fnd != coupledPatchMP.end())
+//            {
+//                label coupledPointI = fnd();
+//
+//                List<point>& pNormals = pointFaceNormals[coupledPointI];
+//                const labelList& pFaces = p.pointFaces()[patchPointI];
+//                pNormals.setSize(pFaces.size());
+//                forAll(pFaces, i)
+//                {
+//                    pNormals[i] =  faceAreas[meshFaces[pFaces[i]]];
+//                }
+//            }
+//        }
+//    }
+//
+//    // Pull remote data into local slots
+//    map.distribute
+//    (
+//        transforms,
+//        pointFaceNormals,
+//        listTransform()
+//    );
+//
+//
+//    // Combine normals
+//    const labelListList& slaves = globalData.globalPointSlaves();
+//    const labelListList& transformedSlaves =
+//        globalData.globalPointTransformedSlaves();
+//
+//
+//    pointField coupledPointNormals(map.constructSize(), vector::zero);
+//
+//    forAll(meshPoints, patchPointI)
+//    {
+//        label meshPointI = meshPoints[patchPointI];
+//        Map<label>::const_iterator fnd = coupledPatchMP.find(meshPointI);
+//        if (fnd != coupledPatchMP.end())
+//        {
+//            label coupledPointI = fnd();
+//            const labelList& slaveSlots = slaves[coupledPointI];
+//            const labelList& transformedSlaveSlots =
+//                transformedSlaves[coupledPointI];
+//
+//            label nFaces = slaveSlots.size()+transformedSlaveSlots.size();
+//            if (nFaces > 0)
+//            {
+//                // Combine
+//                point& n = coupledPointNormals[coupledPointI];
+//
+//                n += sum(pointFaceNormals[coupledPointI]);
+//
+//                forAll(slaveSlots, i)
+//                {
+//                    n += sum(pointFaceNormals[slaveSlots[i]]);
+//                }
+//                forAll(transformedSlaveSlots, i)
+//                {
+//                    n += sum(pointFaceNormals[transformedSlaveSlots[i]]);
+//                }
+//
+//                // Put back into slave slots
+//                forAll(slaveSlots, i)
+//                {
+//                    coupledPointNormals[slaveSlots[i]] = n;
+//                }
+//                forAll(transformedSlaveSlots, i)
+//                {
+//                    coupledPointNormals[transformedSlaveSlots[i]] = n;
+//                }
+//            }
+//        }
+//    }
+//
+//
+//    // Send back
+//    map.reverseDistribute
+//    (
+//        transforms,
+//        coupledPointNormals.size(),
+//        coupledPointNormals,
+//        mapDistribute::transform()
+//    );
+//
+//
+//    // Override patch normals
+//    forAll(meshPoints, patchPointI)
+//    {
+//        label meshPointI = meshPoints[patchPointI];
+//        Map<label>::const_iterator fnd = coupledPatchMP.find(meshPointI);
+//        if (fnd != coupledPatchMP.end())
+//        {
+//            label coupledPointI = fnd();
+//            extrudeN[patchPointI] = coupledPointNormals[coupledPointI];
+//        }
+//    }
+//
+//    extrudeN /= mag(extrudeN)+VSMALL;
+//
+//    return textrudeN;
+//}
+
+
+
+// Main program:
+
+int main(int argc, char *argv[])
+{
+#   include "addTimeOptions.H"
+    argList::validArgs.append("patch");
+#   include "setRootCase.H"
+#   include "createTime.H"
+
+#   include "createMesh.H"
+
+    const word patchName = args[1];
+    label patchI = mesh.boundaryMesh().findPatchID(patchName);
+    const polyPatch& pp = mesh.boundaryMesh()[patchI];
+
+    const indirectPrimitivePatch& cpp = mesh.globalData().coupledPatch();
+
+    {
+        OBJstream str(runTime.path()/"edgePatchNormals.obj");
+
+        labelList patchEdges;
+        labelList coupledEdges;
+        PackedBoolList sameEdgeOrientation;
+        PatchTools::matchEdges
+        (
+            pp,
+            cpp,
+            patchEdges,
+            coupledEdges,
+            sameEdgeOrientation
+        );
+
+        const pointField en
+        (
+            PatchTools::edgeNormals
+            (
+                mesh,
+                pp,
+                patchEdges,
+                coupledEdges
+            )
+        );
+
+        forAll(en, patchEdgeI)
+        {
+            const edge& patchE = pp.edges()[patchEdgeI];
+            //str.write(pp.localPoints()[pointI], en[pointI]);
+            const point pt = patchE.centre(pp.localPoints());
+            str.write(linePointRef(pt, pt + 0.1*en[patchEdgeI]));
+        }
+    }
+
+
+    return 0;
+
+
+//    {
+//        OBJstream str(runTime.path()/"unweightedPatchNormals.obj");
+//
+//        const pointField pn
+//        (
+//            PatchTools::pointNormals
+//            (
+//                mesh,
+//                pp,
+//                identity(pp.size())+pp.start()
+//            )
+//        );
+//        forAll(pn, pointI)
+//        {
+//            str.write(linePointRef(pp.localPoints()[pointI], pn[pointI]));
+//        }
+//    }
+//    {
+//        OBJstream str(runTime.path()/"areaWeightedPatchNormals.obj");
+//
+//        const pointField pn
+//        (
+//            areaPointNormals
+//            (
+//                mesh,
+//                pp,
+//                identity(pp.size())+pp.start()
+//            )
+//        );
+//        forAll(pn, pointI)
+//        {
+//            str.write(linePointRef(pp.localPoints()[pointI], pn[pointI]));
+//        }
+//    }
+
+
+    Pout<< "End\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/etc/codeTemplates/source/_Template.C b/etc/codeTemplates/source/_Template.C
index db0fb9ba1afe9e8c4e25f8626982fdf2b61879e4..d34155cec46b009656ec1e78bc2049cba15c5865 100644
--- a/etc/codeTemplates/source/_Template.C
+++ b/etc/codeTemplates/source/_Template.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/etc/codeTemplates/source/_Template.H b/etc/codeTemplates/source/_Template.H
index 1226ef835c0ff1514cc2cc48cc61e28164c538db..2f7c479705e296e796573c0de7ce184873ebefe5 100644
--- a/etc/codeTemplates/source/_Template.H
+++ b/etc/codeTemplates/source/_Template.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/etc/codeTemplates/source/_TemplateApp.C b/etc/codeTemplates/source/_TemplateApp.C
index 070100f96e6dcaefdf21a146b6e8c6fc7093a9de..602a0c44a75a00d819dbaeaba65fb665e44f4943 100644
--- a/etc/codeTemplates/source/_TemplateApp.C
+++ b/etc/codeTemplates/source/_TemplateApp.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/etc/codeTemplates/source/_TemplateI.H b/etc/codeTemplates/source/_TemplateI.H
index 8de09a51e1848a6fe80ad91172d539194fd9b1f5..7e5c62ed284f15daa51cc45feffc33c018aabc20 100644
--- a/etc/codeTemplates/source/_TemplateI.H
+++ b/etc/codeTemplates/source/_TemplateI.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/etc/codeTemplates/source/_TemplateIO.C b/etc/codeTemplates/source/_TemplateIO.C
index bb2972330be0573d75699f879d187f0e909074e8..0427c8a3c69d2c43bf1e02c6be0f9fb0a896b008 100644
--- a/etc/codeTemplates/source/_TemplateIO.C
+++ b/etc/codeTemplates/source/_TemplateIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/etc/controlDict b/etc/controlDict
index 8d67716f3ccfbe54064e84d4f52c29e8e3de629d..b9c41cb3a432c8e9842c4fa5ea9f4968a612ce19 100644
--- a/etc/controlDict
+++ b/etc/controlDict
@@ -46,6 +46,8 @@ InfoSwitches
 
 OptimisationSwitches
 {
+    // On NFS mounted file system: maximum wait for files to appear/get
+    // updated. Set to 0 on distributed case.
     fileModificationSkew 10;
 
     //- Modification checking:
@@ -1005,6 +1007,22 @@ DimensionSets
         // but not scaled (only supported for dimensionedScalar, etc)
         //writeUnits (kg m s K mol A Cd);
     }
+
+    USCSCoeffs
+    {
+        // Basic units
+        lb  lb  [ 1 0 0 0 0 0 0 ] 1.0;
+        ft  ft  [ 0 1 0 0 0 0 0 ] 1.0;
+        s   s   [ 0 0 1 0 0 0 0 ] 1.0;
+        R   R   [ 0 0 0 1 0 0 0 ] 1.0;
+        mol mol [ 0 0 0 0 1 0 0 ] 1.0;
+        A   A   [ 0 0 0 0 0 1 0 ] 1.0;
+        Cd  Cd  [ 0 0 0 0 0 0 1 ] 1.0;
+
+        // Set of units used for printing. Can be any basic or derived
+        // but not scaled (only supported for dimensionedScalar, etc)
+        //writeUnits (lb ft s R mol A Cd);
+    }
 }
 
 
diff --git a/src/OpenFOAM/db/IOobject/IOobjectReadHeader.C b/src/OpenFOAM/db/IOobject/IOobjectReadHeader.C
index b30adee72ac286174bd3048c6aadcb8d8fff989b..41f0ff99166416a885652f11cfbeac5f5bc7940d 100644
--- a/src/OpenFOAM/db/IOobject/IOobjectReadHeader.C
+++ b/src/OpenFOAM/db/IOobject/IOobjectReadHeader.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -86,7 +86,7 @@ bool Foam::IOobject::readHeader(Istream& is)
     }
     else
     {
-        SeriousIOErrorIn("IOobject::readHeader(Istream&)", is)
+        IOWarningIn("IOobject::readHeader(Istream&)", is)
             << "First token could not be read or is not the keyword 'FoamFile'"
             << nl << nl << "Check header is of the form:" << nl << endl;
 
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
index cfe9de327350bb6180104bb15450141ad607e51c..8a12740cb6c9fefd3ed4f4b6f419e5a181d6875f 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -27,16 +27,9 @@ License
 #include "addToMemberFunctionSelectionTable.H"
 #include "IStringStream.H"
 #include "OStringStream.H"
-#include "IOstreams.H"
-#include "stringOps.H"
 #include "dynamicCode.H"
 #include "dynamicCodeContext.H"
-#include "dlLibraryTable.H"
-#include "OSspecific.H"
 #include "Time.H"
-#include "PstreamReduceOps.H"
-
-#include "long.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -149,7 +142,9 @@ Foam::functionEntries::codeStream::getFunction
     // create library if required
     if (!lib)
     {
-        bool create = Pstream::master();
+        bool create =
+            Pstream::master()
+         || (regIOobject::fileModificationSkew <= 0);   // not NFS
 
         if (create)
         {
@@ -196,9 +191,52 @@ Foam::functionEntries::codeStream::getFunction
 
         //- Only block if we're not doing master-only reading. (flag set by
         //  regIOobject::read, IOdictionary constructor)
-        if (!regIOobject::masterOnlyReading)
+        if
+        (
+           !regIOobject::masterOnlyReading
+         && regIOobject::fileModificationSkew > 0
+        )
         {
-            reduce(create, orOp<bool>());
+            //- Since the library has only been compiled on the master the
+            //  other nodes need to pick this library up through NFS
+            //  We do this by just polling a few times using the
+            //  fileModificationSkew.
+
+            off_t mySize = Foam::fileSize(libPath);
+            off_t masterSize = mySize;
+            Pstream::scatter(masterSize);
+
+            if (mySize < masterSize)
+            {
+                Pout<< "Local file " << libPath
+                    << " not of same size (" << mySize
+                    << ") as master ("
+                    << masterSize << "). Waiting for "
+                    << regIOobject::fileModificationSkew
+                    << " seconds." << endl;
+                Foam::sleep(regIOobject::fileModificationSkew);
+
+                // Recheck local size
+                mySize = Foam::fileSize(libPath);
+
+                if (mySize < masterSize)
+                {
+                    FatalIOErrorIn
+                    (
+                        "functionEntries::codeStream::execute(..)",
+                        parentDict
+                    )   << "Cannot read (NFS mounted) library " << nl
+                        << libPath << nl
+                        << "on processor " << Pstream::myProcNo()
+                        << " detected size " << mySize
+                        << " whereas master size is " << masterSize
+                        << " bytes." << nl
+                        << "If your case is not NFS mounted"
+                        << " (so distributed) set fileModificationSkew"
+                        << " to 0"
+                        << exit(FatalIOError);
+                }
+            }
         }
 
         if (isA<IOdictionary>(topDict(parentDict)))
diff --git a/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchTools.H b/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchTools.H
index 968b0b52441cf3898afbd93a340ddf25559d3071..439c120b450df4b5c3247089086e9fc4562275c5 100644
--- a/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchTools.H
+++ b/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchTools.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -221,8 +221,7 @@ public:
     );
 
 
-    //- Return parallel consistent point normals for patches (on boundary faces)
-    //  using mesh points.
+    //- Return parallel consistent point normals for patches using mesh points.
     template
     <
         class Face,
@@ -231,10 +230,27 @@ public:
         class PointType
     >
     static tmp<pointField> pointNormals
+    (
+        const polyMesh&,
+        const PrimitivePatch<Face, FaceList, PointField, PointType>&
+    );
+
+
+    //- Return parallel consistent edge normals for patches using mesh points.
+    //  Supply with patch matching info from matchEdges.
+    template
+    <
+        class Face,
+        template<class> class FaceList,
+        class PointField,
+        class PointType
+    >
+    static tmp<pointField> edgeNormals
     (
         const polyMesh&,
         const PrimitivePatch<Face, FaceList, PointField, PointType>&,
-        const labelList& meshFaces
+        const labelList& patchEdges,
+        const labelList& coupledEdges
     );
 
 
diff --git a/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchToolsNormals.C b/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchToolsNormals.C
index 02707b9cc58e4dcb3c5ce6c2812ff1b7072f749d..a5cb7fdbb982c4a7d8eae8d1be45bf09d378e8a0 100644
--- a/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchToolsNormals.C
+++ b/src/OpenFOAM/meshes/primitiveMesh/PatchTools/PatchToolsNormals.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -79,8 +79,7 @@ Foam::tmp<Foam::pointField>
 Foam::PatchTools::pointNormals
 (
     const polyMesh& mesh,
-    const PrimitivePatch<Face, FaceList, PointField, PointType>& p,
-    const labelList& meshFaces
+    const PrimitivePatch<Face, FaceList, PointField, PointType>& p
 )
 {
     // Assume patch is smaller than the globalData().coupledPatch() (?) so
@@ -224,4 +223,90 @@ Foam::PatchTools::pointNormals
 }
 
 
+template
+<
+    class Face,
+    template<class> class FaceList,
+    class PointField,
+    class PointType
+>
+
+Foam::tmp<Foam::pointField>
+Foam::PatchTools::edgeNormals
+(
+    const polyMesh& mesh,
+    const PrimitivePatch<Face, FaceList, PointField, PointType>& p,
+    const labelList& patchEdges,
+    const labelList& coupledEdges
+)
+{
+    // 1. Start off with local normals
+
+    tmp<pointField> tedgeNormals(new pointField(p.nEdges(), vector::zero));
+    pointField& edgeNormals = tedgeNormals();
+    {
+        const labelListList& edgeFaces = p.edgeFaces();
+        const vectorField& faceNormals = p.faceNormals();
+
+        forAll(edgeFaces, edgeI)
+        {
+            const labelList& eFaces = edgeFaces[edgeI];
+            forAll(eFaces, i)
+            {
+                edgeNormals[edgeI] += faceNormals[eFaces[i]];
+            }
+        }
+        edgeNormals /= mag(edgeNormals)+VSMALL;
+    }
+
+
+
+    const globalMeshData& globalData = mesh.globalData();
+    const mapDistribute& map = globalData.globalEdgeSlavesMap();
+
+
+    // Convert patch-edge data into cpp-edge data
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    //- Construct with all data in consistent orientation
+    pointField cppEdgeData(map.constructSize(), vector::zero);
+
+    forAll(patchEdges, i)
+    {
+        label patchEdgeI = patchEdges[i];
+        label coupledEdgeI = coupledEdges[i];
+        cppEdgeData[coupledEdgeI] = edgeNormals[patchEdgeI];
+    }
+
+
+    // Synchronise
+    // ~~~~~~~~~~~
+
+    globalData.syncData
+    (
+        cppEdgeData,
+        globalData.globalEdgeSlaves(),
+        globalData.globalEdgeTransformedSlaves(),
+        map,
+        globalData.globalTransforms(),
+        plusEqOp<point>(),              // add since normalised later on
+        mapDistribute::transform()
+    );
+    cppEdgeData /= mag(cppEdgeData)+VSMALL;
+
+
+    // Back from cpp-edge to patch-edge data
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    forAll(patchEdges, i)
+    {
+        label patchEdgeI = patchEdges[i];
+        label coupledEdgeI = coupledEdges[i];
+        edgeNormals[patchEdgeI] = cppEdgeData[coupledEdgeI];
+    }
+
+    return tedgeNormals;
+}
+
+
 // ************************************************************************* //
diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
index b224ef609d8ec8448bff2192dbda73517c1cc296..3eb051006f8f1b9c3fef79f2cc47f6ee1afe91a8 100644
--- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
+++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriver.C
@@ -1464,15 +1464,7 @@ void Foam::autoLayerDriver::getPatchDisplacement
     // Determine pointNormal
     // ~~~~~~~~~~~~~~~~~~~~~
 
-    pointField pointNormals
-    (
-        PatchTools::pointNormals
-        (
-            mesh,
-            pp,
-            pp.addressing()
-        )
-    );
+    pointField pointNormals(PatchTools::pointNormals(mesh, pp));
 
 
     // Determine local length scale on patch
diff --git a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
index bf25526141c8bc6043add647bdb8a4a8c1f60bf2..d6556a95083f401061c99db53c78fdc4f74b9f3e 100644
--- a/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
+++ b/src/mesh/autoMesh/autoHexMesh/autoHexMeshDriver/autoLayerDriverShrink.C
@@ -826,15 +826,7 @@ void Foam::autoLayerDriver::medialAxisSmoothingInfo
     // Determine pointNormal
     // ~~~~~~~~~~~~~~~~~~~~~
 
-    pointField pointNormals
-    (
-        PatchTools::pointNormals
-        (
-            mesh,
-            pp,
-            pp.addressing()
-        )
-    );
+    pointField pointNormals(PatchTools::pointNormals(mesh, pp));
 
     // pointNormals
     if (debug&meshRefinement::MESH || debug&meshRefinement::LAYERINFO)
@@ -1074,15 +1066,7 @@ void Foam::autoLayerDriver::medialAxisSmoothingInfo
                         << featureAngle << " degrees." << endl;
 
                     scalar featureAngleCos = Foam::cos(degToRad(featureAngle));
-                    pointField pointNormals
-                    (
-                        PatchTools::pointNormals
-                        (
-                            mesh,
-                            pp,
-                            identity(pp.size())+pp.start()
-                        )
-                    );
+                    pointField pointNormals(PatchTools::pointNormals(mesh, pp));
 
                     forAll(meshPoints, i)
                     {
diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index c8bc7b23a9e403d10a8071abfb580f44ee8ba7ab..dbed9146d33499774583e979eae88d8799650304 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -188,6 +188,9 @@ mappedPatches/mappedPolyPatch/mappedVariableThicknessWallPolyPatch.C
 mappedPatches/mappedPointPatch/mappedPointPatch.C
 mappedPatches/mappedPointPatch/mappedWallPointPatch.C
 
+meshStructure/meshStructure.C
+meshStructure/topoDistanceData.C
+meshStructure/pointTopoDistanceData.C
 
 regionCoupled/patches/regionCoupledPolyPatch/regionCoupledBase.C
 regionCoupled/patches/regionCoupledPolyPatch/regionCoupledPolyPatch.C
diff --git a/src/meshTools/meshStructure/meshStructure.C b/src/meshTools/meshStructure/meshStructure.C
new file mode 100644
index 0000000000000000000000000000000000000000..d16495d6efd6bddffa3a5fb3c5e612408e243183
--- /dev/null
+++ b/src/meshTools/meshStructure/meshStructure.C
@@ -0,0 +1,387 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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 "meshStructure.H"
+#include "FaceCellWave.H"
+#include "topoDistanceData.H"
+#include "pointTopoDistanceData.H"
+#include "PointEdgeWave.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+defineTypeNameAndDebug(meshStructure, 0);
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+bool Foam::meshStructure::isStructuredCell
+(
+    const polyMesh& mesh,
+    const label layerI,
+    const label cellI
+) const
+{
+    const cell& cFaces = mesh.cells()[cellI];
+
+    // Count number of side faces
+    label nSide = 0;
+    forAll(cFaces, i)
+    {
+        if (faceToPatchEdgeAddressing_[cFaces[i]] != -1)
+        {
+            nSide++;
+        }
+    }
+
+    if (nSide != cFaces.size()-2)
+    {
+        return false;
+    }
+
+    // Check that side faces have correct point layers
+    forAll(cFaces, i)
+    {
+        if (faceToPatchEdgeAddressing_[cFaces[i]] != -1)
+        {
+            const face& f = mesh.faces()[cFaces[i]];
+
+            label nLayer = 0;
+            label nLayerPlus1 = 0;
+            forAll(f, fp)
+            {
+                label pointI = f[fp];
+                if (pointLayer_[pointI] == layerI)
+                {
+                    nLayer++;
+                }
+                else if (pointLayer_[pointI] == layerI+1)
+                {
+                    nLayerPlus1++;
+                }
+            }
+
+            if (f.size() != 4 || (nLayer+nLayerPlus1 != 4))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+void Foam::meshStructure::correct
+(
+    const polyMesh& mesh,
+    const uindirectPrimitivePatch& pp
+)
+{
+    // Field on cells and faces.
+    List<topoDistanceData> cellData(mesh.nCells());
+    List<topoDistanceData> faceData(mesh.nFaces());
+
+    {
+        if (debug)
+        {
+            Info<< typeName << " : seeding "
+                << returnReduce(pp.size(), sumOp<label>()) << " patch faces"
+                << nl << endl;
+        }
+
+
+        // Start of changes
+        labelList patchFaces(pp.size());
+        List<topoDistanceData> patchData(pp.size());
+        forAll(pp, patchFaceI)
+        {
+            patchFaces[patchFaceI] = pp.addressing()[patchFaceI];
+            patchData[patchFaceI] = topoDistanceData(patchFaceI, 0);
+        }
+
+
+        // Propagate information inwards
+        FaceCellWave<topoDistanceData> distanceCalc
+        (
+            mesh,
+            patchFaces,
+            patchData,
+            faceData,
+            cellData,
+            mesh.globalData().nTotalCells()+1
+        );
+
+
+        // Determine cells from face-cell-walk
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        cellToPatchFaceAddressing_.setSize(mesh.nCells());
+        cellLayer_.setSize(mesh.nCells());
+        forAll(cellToPatchFaceAddressing_, cellI)
+        {
+            cellToPatchFaceAddressing_[cellI] = cellData[cellI].data();
+            cellLayer_[cellI] = cellData[cellI].distance();
+        }
+
+
+
+        // Determine faces from face-cell-walk
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        faceToPatchFaceAddressing_.setSize(mesh.nFaces());
+        faceToPatchEdgeAddressing_.setSize(mesh.nFaces());
+        faceToPatchEdgeAddressing_ = labelMin;
+        faceLayer_.setSize(mesh.nFaces());
+
+        forAll(faceToPatchFaceAddressing_, faceI)
+        {
+            label own = mesh.faceOwner()[faceI];
+            label patchFaceI = faceData[faceI].data();
+            label patchDist = faceData[faceI].distance();
+
+            if (mesh.isInternalFace(faceI))
+            {
+                label nei = mesh.faceNeighbour()[faceI];
+
+                if (cellData[own].distance() == cellData[nei].distance())
+                {
+                    // side face
+                    faceToPatchFaceAddressing_[faceI] = 0;
+                    faceLayer_[faceI] = cellData[own].distance();
+                }
+                else if (cellData[own].distance() < cellData[nei].distance())
+                {
+                    // unturned face
+                    faceToPatchFaceAddressing_[faceI] = patchFaceI+1;
+                    faceToPatchEdgeAddressing_[faceI] = -1;
+                    faceLayer_[faceI] = patchDist;
+                }
+                else
+                {
+                    // turned face
+                    faceToPatchFaceAddressing_[faceI] = -(patchFaceI+1);
+                    faceToPatchEdgeAddressing_[faceI] = -1;
+                    faceLayer_[faceI] = patchDist;
+                }
+            }
+            else if (patchDist == cellData[own].distance())
+            {
+                // starting face
+                faceToPatchFaceAddressing_[faceI] = -(patchFaceI+1);
+                faceToPatchEdgeAddressing_[faceI] = -1;
+                faceLayer_[faceI] = patchDist;
+            }
+            else
+            {
+                // unturned face or side face. Cannot be determined until
+                // we determine the point layers. Problem is that both are
+                // the same number of steps away from the initial seed face.
+            }
+        }
+    }
+
+
+    // Determine points from separate walk on point-edge
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    {
+        pointToPatchPointAddressing_.setSize(mesh.nPoints());
+        pointLayer_.setSize(mesh.nPoints());
+
+        if (debug)
+        {
+            Info<< typeName << " : seeding "
+                << returnReduce(pp.nPoints(), sumOp<label>()) << " patch points"
+                << nl << endl;
+        }
+
+        // Field on edges and points.
+        List<pointTopoDistanceData> edgeData(mesh.nEdges());
+        List<pointTopoDistanceData> pointData(mesh.nPoints());
+
+        // Start of changes
+        labelList patchPoints(pp.nPoints());
+        List<pointTopoDistanceData> patchData(pp.nPoints());
+        forAll(pp.meshPoints(), patchPointI)
+        {
+            patchPoints[patchPointI] = pp.meshPoints()[patchPointI];
+            patchData[patchPointI] = pointTopoDistanceData(patchPointI, 0);
+        }
+
+
+        // Walk
+        PointEdgeWave<pointTopoDistanceData> distanceCalc
+        (
+            mesh,
+            patchPoints,
+            patchData,
+
+            pointData,
+            edgeData,
+            mesh.globalData().nTotalPoints()  // max iterations
+        );
+
+        forAll(pointData, pointI)
+        {
+            pointToPatchPointAddressing_[pointI] = pointData[pointI].data();
+            pointLayer_[pointI] = pointData[pointI].distance();
+        }
+
+
+        // Derive from originating patch points what the patch edges were.
+        EdgeMap<label> pointsToEdge(pp.nEdges());
+        forAll(pp.edges(), edgeI)
+        {
+            pointsToEdge.insert(pp.edges()[edgeI], edgeI);
+        }
+
+        // Look up on faces
+        forAll(faceToPatchEdgeAddressing_, faceI)
+        {
+            if (faceToPatchEdgeAddressing_[faceI] == labelMin)
+            {
+                // Face not yet done. Check if all points on same level
+                // or if not see what edge it originates from
+
+                const face& f = mesh.faces()[faceI];
+
+                label levelI = pointLayer_[f[0]];
+                for (label fp = 1; fp < f.size(); fp++)
+                {
+                    if (pointLayer_[f[fp]] != levelI)
+                    {
+                        levelI = -1;
+                        break;
+                    }
+                }
+
+                if (levelI != -1)
+                {
+                    // All same level
+                    //Pout<< "Horizontal boundary face " << faceI
+                    //    << " at:" << mesh.faceCentres()[faceI]
+                    //    << " data:" << faceData[faceI]
+                    //    << " pointDatas:"
+                    //    << UIndirectList<pointTopoDistanceData>(pointData, f)
+                    //    << endl;
+
+                    label patchFaceI = faceData[faceI].data();
+                    label patchDist = faceData[faceI].distance();
+
+                    faceToPatchEdgeAddressing_[faceI] = -1;
+                    faceToPatchFaceAddressing_[faceI] = patchFaceI+1;
+                    faceLayer_[faceI] = patchDist;
+                }
+                else
+                {
+                    // Points of face on different levels
+
+                    // See if there is any edge
+                    forAll(f, fp)
+                    {
+                        label pointI = f[fp];
+                        label nextPointI = f.nextLabel(fp);
+
+                        EdgeMap<label>::const_iterator fnd = pointsToEdge.find
+                        (
+                            edge
+                            (
+                                pointData[pointI].data(),
+                                pointData[nextPointI].data()
+                            )
+                        );
+                        if (fnd != pointsToEdge.end())
+                        {
+                            faceToPatchEdgeAddressing_[faceI] = fnd();
+                            faceToPatchFaceAddressing_[faceI] = 0;
+                            label own = mesh.faceOwner()[faceI];
+                            faceLayer_[faceI] = cellData[own].distance();
+
+                            // Note: could test whether the other edges on the
+                            // face are consistent
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+
+    // Use maps to find out mesh structure.
+    {
+        label nLayers = gMax(cellLayer_)+1;
+        labelListList layerToCells(invertOneToMany(nLayers, cellLayer_));
+
+        structured_ = true;
+        forAll(layerToCells, layerI)
+        {
+            const labelList& lCells = layerToCells[layerI];
+
+            forAll(lCells, lCellI)
+            {
+                label cellI = lCells[lCellI];
+
+                structured_ = isStructuredCell
+                (
+                    mesh,
+                    layerI,
+                    cellI
+                );
+
+                if (!structured_)
+                {
+                    break;
+                }
+            }
+
+            if (!structured_)
+            {
+                break;
+            }
+        }
+
+        reduce(structured_, andOp<bool>());
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::meshStructure::meshStructure
+(
+    const polyMesh& mesh,
+    const uindirectPrimitivePatch& pp
+)
+{
+    correct(mesh, pp);
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/meshStructure/meshStructure.H b/src/meshTools/meshStructure/meshStructure.H
new file mode 100644
index 0000000000000000000000000000000000000000..24bbbc875eda17838a7c82cbd9e88655a79b8220
--- /dev/null
+++ b/src/meshTools/meshStructure/meshStructure.H
@@ -0,0 +1,175 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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::meshStructure
+
+Description
+    Detect extruded mesh structure given a set of patch faces.
+
+SourceFiles
+    meshStructure.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef meshStructure_H
+#define meshStructure_H
+
+#include "labelList.H"
+#include "uindirectPrimitivePatch.H"
+#include "className.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class polyMesh;
+
+
+/*---------------------------------------------------------------------------*\
+                         Class meshStructure Declaration
+\*---------------------------------------------------------------------------*/
+
+class meshStructure
+{
+    // Private data
+
+        //- Cell to patch face
+        labelList cellToPatchFaceAddressing_;
+
+        //- Cell to layer
+        labelList cellLayer_;
+
+        //- Face to patch face
+        labelList faceToPatchFaceAddressing_;
+
+        //- Face to patch edge
+        labelList faceToPatchEdgeAddressing_;
+
+        //- Face to layer
+        labelList faceLayer_;
+
+        //- Point to patch point
+        labelList pointToPatchPointAddressing_;
+
+        //- Point to layer
+        labelList pointLayer_;
+
+        //- Is mesh structured?
+        bool structured_;
+
+
+   // Private Member Functions
+
+        //- Is cell structured
+        bool isStructuredCell
+        (
+            const polyMesh& mesh,
+            const label layerI,
+            const label cellI
+        ) const;
+
+        //- Calculate all maps.
+        void correct
+        (
+            const polyMesh& mesh,
+            const uindirectPrimitivePatch& pp
+        );
+
+
+public:
+
+    // Declare name of the class and its debug switch
+    ClassName("meshStructure");
+
+    // Constructors
+
+        //- Construct null
+        meshStructure(const polyMesh& mesh, const uindirectPrimitivePatch&);
+
+
+    // Member Functions
+
+        //- Is mesh structured?
+        inline bool structured() const;
+
+        //- Cell to patch face
+        inline const labelList& cellToPatchFaceAddressing() const;
+
+        //- Cell to patch face
+        inline labelList& cellToPatchFaceAddressing();
+
+        //- Cell to layer
+        inline const labelList& cellLayer() const;
+
+        //- Cell to layer
+        inline labelList& cellLayer();
+
+        //- Face to patch face
+        inline const labelList& faceToPatchFaceAddressing() const;
+
+        //- Face to patch face
+        inline labelList& faceToPatchFaceAddressing();
+
+        //- Face to patch edge
+        inline const labelList& faceToPatchEdgeAddressing() const;
+
+        //- Face to patch edge
+        inline labelList& faceToPatchEdgeAddressing();
+
+        //- Face to layer
+        inline const labelList& faceLayer() const;
+
+        //- Face to layer
+        inline labelList& faceLayer();
+
+        //- Point to patch point
+        inline const labelList& pointToPatchPointAddressing() const;
+
+        //- Point to patch point
+        inline labelList& pointToPatchPointAddressing();
+
+        //- Point to layer
+        inline const labelList& pointLayer() const;
+
+        //- Point to layer
+        inline labelList& pointLayer();
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "meshStructureI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/meshStructure/meshStructureI.H b/src/meshTools/meshStructure/meshStructureI.H
new file mode 100644
index 0000000000000000000000000000000000000000..9367f41eb578a90307ece9e0f0ac68bc928781ce
--- /dev/null
+++ b/src/meshTools/meshStructure/meshStructureI.H
@@ -0,0 +1,120 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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 "meshStructure.H"
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+bool Foam::meshStructure::structured() const
+{
+    return structured_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::cellToPatchFaceAddressing() const
+{
+    return cellToPatchFaceAddressing_;
+}
+
+
+Foam::labelList& Foam::meshStructure::cellToPatchFaceAddressing()
+{
+    return cellToPatchFaceAddressing_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::cellLayer() const
+{
+    return cellLayer_;
+}
+
+
+Foam::labelList& Foam::meshStructure::cellLayer()
+{
+    return cellLayer_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::faceToPatchFaceAddressing() const
+{
+    return faceToPatchFaceAddressing_;
+}
+
+
+Foam::labelList& Foam::meshStructure::faceToPatchFaceAddressing()
+{
+    return faceToPatchFaceAddressing_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::faceToPatchEdgeAddressing() const
+{
+    return faceToPatchEdgeAddressing_;
+}
+
+
+Foam::labelList& Foam::meshStructure::faceToPatchEdgeAddressing()
+{
+    return faceToPatchEdgeAddressing_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::faceLayer() const
+{
+    return faceLayer_;
+}
+
+
+Foam::labelList& Foam::meshStructure::faceLayer()
+{
+    return faceLayer_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::pointToPatchPointAddressing() const
+{
+    return pointToPatchPointAddressing_;
+}
+
+
+Foam::labelList& Foam::meshStructure::pointToPatchPointAddressing()
+{
+    return pointToPatchPointAddressing_;
+}
+
+
+const Foam::labelList& Foam::meshStructure::pointLayer() const
+{
+    return pointLayer_;
+}
+
+
+Foam::labelList& Foam::meshStructure::pointLayer()
+{
+    return pointLayer_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/meshStructure/pointTopoDistanceData.C b/src/meshTools/meshStructure/pointTopoDistanceData.C
new file mode 100644
index 0000000000000000000000000000000000000000..95a1e00518ef1ebe75082a01c9ba61ac65aa71c6
--- /dev/null
+++ b/src/meshTools/meshStructure/pointTopoDistanceData.C
@@ -0,0 +1,50 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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 "pointTopoDistanceData.H"
+
+// * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::operator<<
+(
+    Foam::Ostream& os,
+    const Foam::pointTopoDistanceData& wDist
+)
+{
+    return os << wDist.data_ << token::SPACE << wDist.distance_;
+}
+
+
+Foam::Istream& Foam::operator>>
+(
+    Foam::Istream& is,
+    Foam::pointTopoDistanceData& wDist
+)
+{
+    return is >> wDist.data_ >> wDist.distance_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/meshStructure/pointTopoDistanceData.H b/src/meshTools/meshStructure/pointTopoDistanceData.H
new file mode 100644
index 0000000000000000000000000000000000000000..d8c7cf8830bc42a0b8cdcab8f352039d5b9d1647
--- /dev/null
+++ b/src/meshTools/meshStructure/pointTopoDistanceData.H
@@ -0,0 +1,227 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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::pointTopoDistanceData
+
+Description
+    For use with PointEdgeWave. Determines topological distance to
+    starting points
+
+SourceFiles
+    pointTopoDistanceDataI.H
+    pointTopoDistanceData.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pointTopoDistanceData_H
+#define pointTopoDistanceData_H
+
+#include "point.H"
+#include "tensor.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class polyPatch;
+class polyMesh;
+
+/*---------------------------------------------------------------------------*\
+                       Class pointTopoDistanceData Declaration
+\*---------------------------------------------------------------------------*/
+
+class pointTopoDistanceData
+{
+    // Private data
+
+        //- Starting data
+        label data_;
+
+        //- Distance
+        label distance_;
+
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        inline pointTopoDistanceData();
+
+        //- Construct from count
+        inline pointTopoDistanceData
+        (
+            const label data,
+            const label distance
+        );
+
+
+    // Member Functions
+
+        // Access
+
+
+            inline label data() const
+            {
+                return data_;
+            }
+            inline label distance() const
+            {
+                return distance_;
+            }
+
+
+        // Needed by PointEdgeWave
+
+
+            //- Check whether origin has been changed at all or
+            //  still contains original (invalid) value.
+            template<class TrackingData>
+            inline bool valid(TrackingData& td) const;
+
+            //- Check for identical geometrical data. Used for cyclics checking.
+            template<class TrackingData>
+            inline bool sameGeometry
+            (
+                const pointTopoDistanceData&,
+                const scalar tol,
+                TrackingData& td
+            ) const;
+
+            //- Convert origin to relative vector to leaving point
+            //  (= point coordinate)
+            template<class TrackingData>
+            inline void leaveDomain
+            (
+                const polyPatch& patch,
+                const label patchPointI,
+                const point& pos,
+                TrackingData& td
+            );
+
+            //- Convert relative origin to absolute by adding entering point
+            template<class TrackingData>
+            inline void enterDomain
+            (
+                const polyPatch& patch,
+                const label patchPointI,
+                const point& pos,
+                TrackingData& td
+            );
+
+            //- Apply rotation matrix to origin
+            template<class TrackingData>
+            inline void transform
+            (
+                const tensor& rotTensor,
+                TrackingData& td
+            );
+
+            //- Influence of edge on point
+            template<class TrackingData>
+            inline bool updatePoint
+            (
+                const polyMesh& mesh,
+                const label pointI,
+                const label edgeI,
+                const pointTopoDistanceData& edgeInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Influence of different value on same point.
+            //  Merge new and old info.
+            template<class TrackingData>
+            inline bool updatePoint
+            (
+                const polyMesh& mesh,
+                const label pointI,
+                const pointTopoDistanceData& newPointInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Influence of different value on same point.
+            //  No information about current position whatsoever.
+            template<class TrackingData>
+            inline bool updatePoint
+            (
+                const pointTopoDistanceData& newPointInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Influence of point on edge.
+            template<class TrackingData>
+            inline bool updateEdge
+            (
+                const polyMesh& mesh,
+                const label edgeI,
+                const label pointI,
+                const pointTopoDistanceData& pointInfo,
+                const scalar tol,
+                TrackingData& td
+            );
+
+            //- Same (like operator==)
+            template<class TrackingData>
+            inline bool equal(const pointTopoDistanceData&, TrackingData&)
+            const;
+
+
+    // Member Operators
+
+        // Needed for List IO
+        inline bool operator==(const pointTopoDistanceData&) const;
+        inline bool operator!=(const pointTopoDistanceData&) const;
+
+    // IOstream Operators
+
+        friend Ostream& operator<<(Ostream&, const pointTopoDistanceData&);
+        friend Istream& operator>>(Istream&, pointTopoDistanceData&);
+};
+
+
+//- Data associated with pointTopoDistanceData type are contiguous
+template<>
+inline bool contiguous<pointTopoDistanceData>()
+{
+    return true;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "pointTopoDistanceDataI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/meshStructure/pointTopoDistanceDataI.H b/src/meshTools/meshStructure/pointTopoDistanceDataI.H
new file mode 100644
index 0000000000000000000000000000000000000000..c42dbffce2e7f01795d215fe81b5b05d7aa3c8c8
--- /dev/null
+++ b/src/meshTools/meshStructure/pointTopoDistanceDataI.H
@@ -0,0 +1,233 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2013 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 "polyMesh.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+// Null constructor
+inline Foam::pointTopoDistanceData::pointTopoDistanceData()
+:
+    data_(-1),
+    distance_(-1)
+{}
+
+
+// Construct from components
+inline Foam::pointTopoDistanceData::pointTopoDistanceData
+(
+    const label data,
+    const label distance
+)
+:
+    data_(data),
+    distance_(distance)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template <class TrackingData>
+inline bool Foam::pointTopoDistanceData::valid(TrackingData& td) const
+{
+    return distance_ != -1;
+}
+
+
+// No geometric data so never any problem on cyclics
+template <class TrackingData>
+inline bool Foam::pointTopoDistanceData::sameGeometry
+(
+    const pointTopoDistanceData&,
+    const scalar tol,
+    TrackingData& td
+) const
+{
+    return true;
+}
+
+
+// No geometric data.
+template <class TrackingData>
+inline void Foam::pointTopoDistanceData::leaveDomain
+(
+    const polyPatch& patch,
+    const label patchPointI,
+    const point& coord,
+    TrackingData& td
+)
+{}
+
+
+// No geometric data.
+template <class TrackingData>
+inline void Foam::pointTopoDistanceData::transform
+(
+    const tensor& rotTensor,
+    TrackingData& td
+)
+{}
+
+
+// No geometric data.
+template <class TrackingData>
+inline void Foam::pointTopoDistanceData::enterDomain
+(
+    const polyPatch& patch,
+    const label patchPointI,
+    const point& coord,
+    TrackingData& td
+)
+{}
+
+
+// Update this with information from connected edge
+template <class TrackingData>
+inline bool Foam::pointTopoDistanceData::updatePoint
+(
+    const polyMesh& mesh,
+    const label pointI,
+    const label edgeI,
+    const pointTopoDistanceData& edgeInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    if (distance_ == -1)
+    {
+        data_ = edgeInfo.data_;
+        distance_ = edgeInfo.distance_ + 1;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+// Update this with new information on same point
+template<class TrackingData>
+inline bool Foam::pointTopoDistanceData::updatePoint
+(
+    const polyMesh& mesh,
+    const label pointI,
+    const pointTopoDistanceData& newPointInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    if (distance_ == -1)
+    {
+        operator=(newPointInfo);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+// Update this with new information on same point. No extra information.
+template<class TrackingData>
+inline bool Foam::pointTopoDistanceData::updatePoint
+(
+    const pointTopoDistanceData& newPointInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    if (distance_ == -1)
+    {
+        operator=(newPointInfo);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+// Update this with information from connected point
+template<class TrackingData>
+inline bool Foam::pointTopoDistanceData::updateEdge
+(
+    const polyMesh& mesh,
+    const label edgeI,
+    const label pointI,
+    const pointTopoDistanceData& pointInfo,
+    const scalar tol,
+    TrackingData& td
+)
+{
+    if (distance_ == -1)
+    {
+        operator=(pointInfo);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+template <class TrackingData>
+inline bool Foam::pointTopoDistanceData::equal
+(
+    const pointTopoDistanceData& rhs,
+    TrackingData& td
+) const
+{
+    return operator==(rhs);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+inline bool Foam::pointTopoDistanceData::operator==
+(
+    const Foam::pointTopoDistanceData& rhs
+) const
+{
+    return data() == rhs.data() && distance() == rhs.distance();
+}
+
+
+inline bool Foam::pointTopoDistanceData::operator!=
+(
+    const Foam::pointTopoDistanceData& rhs
+) const
+{
+    return !(*this == rhs);
+}
+
+
+// ************************************************************************* //
diff --git a/src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.C b/src/meshTools/meshStructure/topoDistanceData.C
similarity index 95%
rename from src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.C
rename to src/meshTools/meshStructure/topoDistanceData.C
index a7683eeb243229e49d28b7e62a37845331564522..e5938cccfc24ab62994f7ea474a38cd530430f5c 100644
--- a/src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.C
+++ b/src/meshTools/meshStructure/topoDistanceData.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.H b/src/meshTools/meshStructure/topoDistanceData.H
similarity index 98%
rename from src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.H
rename to src/meshTools/meshStructure/topoDistanceData.H
index dc18cb46006207f703f11d054235e44ee569d9a2..be6f73ee753f80bb55ed876ea44129dd5a41acbe 100644
--- a/src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceData.H
+++ b/src/meshTools/meshStructure/topoDistanceData.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
diff --git a/src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceDataI.H b/src/meshTools/meshStructure/topoDistanceDataI.H
similarity index 100%
rename from src/parallel/decompose/decompositionMethods/structuredDecomp/topoDistanceDataI.H
rename to src/meshTools/meshStructure/topoDistanceDataI.H
diff --git a/src/parallel/decompose/decompositionMethods/Make/files b/src/parallel/decompose/decompositionMethods/Make/files
index 5e54b366af42ba69866e138d23b27b460b156701..c2837d2eb320880626cf8fa1cca120dfa718e39a 100644
--- a/src/parallel/decompose/decompositionMethods/Make/files
+++ b/src/parallel/decompose/decompositionMethods/Make/files
@@ -4,7 +4,6 @@ simpleGeomDecomp/simpleGeomDecomp.C
 hierarchGeomDecomp/hierarchGeomDecomp.C
 manualDecomp/manualDecomp.C
 multiLevelDecomp/multiLevelDecomp.C
-structuredDecomp/topoDistanceData.C
 structuredDecomp/structuredDecomp.C
 noDecomp/noDecomp.C
 
diff --git a/src/thermophysicalModels/solidSpecie/transport/const/constAnIsoSolidTransport.H b/src/thermophysicalModels/solidSpecie/transport/const/constAnIsoSolidTransport.H
index 60b846fd7ad03646e72b769e294bafa3ae402d3f..718f648143354953ad3b02ed04e8b19548e42b06 100644
--- a/src/thermophysicalModels/solidSpecie/transport/const/constAnIsoSolidTransport.H
+++ b/src/thermophysicalModels/solidSpecie/transport/const/constAnIsoSolidTransport.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -111,6 +111,9 @@ public:
             return "constAnIso<" + Thermo::typeName() + '>';
         }
 
+        //- Is the thermal conductivity isotropic
+        static const bool isotropic = false;
+
         //- Isotropic thermal conductivity [W/mK]
         inline scalar kappa(const scalar p, const scalar T) const;
 
diff --git a/src/thermophysicalModels/solidSpecie/transport/const/constIsoSolidTransport.H b/src/thermophysicalModels/solidSpecie/transport/const/constIsoSolidTransport.H
index 5b49beab675742b8b004c4381e942c9a1a0f4cd2..fc9cb4438a5d999d22bd58777a512a27f533d75a 100644
--- a/src/thermophysicalModels/solidSpecie/transport/const/constIsoSolidTransport.H
+++ b/src/thermophysicalModels/solidSpecie/transport/const/constIsoSolidTransport.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -112,6 +112,9 @@ public:
             return "constIso<" + Thermo::typeName() + '>';
         }
 
+        //- Is the thermal conductivity isotropic
+        static const bool isotropic = true;
+
         //- Isotropic thermal conductivity [W/mK]
         inline scalar kappa(const scalar p, const scalar T) const;
 
diff --git a/src/thermophysicalModels/solidSpecie/transport/exponential/exponentialSolidTransport.H b/src/thermophysicalModels/solidSpecie/transport/exponential/exponentialSolidTransport.H
index 00cc81e1b3be90735d58939f5009204c87e80d4f..3592626d8045b8846d58a092bde25a53ab74750d 100644
--- a/src/thermophysicalModels/solidSpecie/transport/exponential/exponentialSolidTransport.H
+++ b/src/thermophysicalModels/solidSpecie/transport/exponential/exponentialSolidTransport.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -121,6 +121,9 @@ public:
             return "exponential<" + Thermo::typeName() + '>';
         }
 
+        //- Is the thermal conductivity isotropic
+        static const bool isotropic = true;
+
         //- Thermal conductivity [W/mK]
         inline scalar kappa(const scalar p, const scalar T) const;
 
diff --git a/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.H b/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.H
index 8d13ea6e28a61c7467f6b90b0922e40e5b587125..146656d69e97a30e7dbebf5a4eb1a86a9b64ff38 100644
--- a/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.H
+++ b/src/thermophysicalModels/solidThermo/solidThermo/heSolidThermo.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -99,6 +99,12 @@ public:
             //- Anisotropic thermal conductivity [W/m/K]
             virtual tmp<volVectorField> Kappa() const;
 
+            //- Return true if thermal conductivity is isotropic
+            virtual bool isotropic() const
+            {
+                return MixtureType::thermoType::isotropic;
+            }
+
 
         // Per patch calculation
 
diff --git a/src/thermophysicalModels/solidThermo/solidThermo/solidThermo.H b/src/thermophysicalModels/solidThermo/solidThermo/solidThermo.H
index e3cf9b8e19d641b554e549be24ac75700857dbe9..04934ca950cf559da6bdf6fdbb9fc35245fb7e23 100644
--- a/src/thermophysicalModels/solidThermo/solidThermo/solidThermo.H
+++ b/src/thermophysicalModels/solidThermo/solidThermo/solidThermo.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2013-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -144,6 +144,9 @@ public:
             //- Thermal conductivity [W/m/K]
             virtual tmp<volVectorField> Kappa() const = 0;
 
+            //- Return true if thermal conductivity is isotropic
+            virtual bool isotropic() const = 0;
+
 
         // Per patch calculation