diff --git a/ReleaseNotes-dev b/ReleaseNotes-dev
index 8daf5ef6f457d65afab4186c1e88699dd6a06243..aa3c87699df9b1f9068507eaa41f570a456dee8a 100644
--- a/ReleaseNotes-dev
+++ b/ReleaseNotes-dev
@@ -105,7 +105,15 @@
     + Additional wall functions for primary region momentum and temperature
       taking film into account
     + Parallel aware
-*** *New* ptscotch decomposition method
+*** *New* ptscotch decomposition method.
+*** *New* multiLevel decomposition method.
+    Decomposes in levels, e.g. first decompose onto number of nodes and
+    then onto number of cores per node. This will minimise off-node
+    communication. Each level can use any of the other decomposition methods
+*** *New* structured decomposition method.
+    Does a 2D decomposition of a mesh. Valid only for an 'extruded' mesh, i.e.
+    columns of cells originating from a patch. Bases decomposition on this
+    patch and assigns the cells according to the patch decomposition.
 *** *Updated* scotch decomposition method to run in parallel by doing
     decomposition on the master. Unfortunately scotch and ptscotch cannot
     be linked in to the same executable.
@@ -229,7 +237,8 @@
         (nonuniformTransform)cyclic <zoneA>_<zoneB>
       + extrudes into master direction (i.e. away from the owner cell
         if flipMap is false)
-    + =topoSet=: replacement of cellSet,faceSet,pointSet utilities.
+    + =topoSet=: replacement of cellSet,faceSet,pointSet utilities. Multiple
+      commands operating on different sets.
       Comparable to a dictionary driven =setSet= utility.
 *** Updated utilities
     + =setFields=: optionally use faceSets to set patch values (see
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
index 26283baa2ede28469c0e4dc8dd6603c10c6107e3..94a3b75c1f902cfa10be5e513013749ba8be43bb 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict
@@ -37,6 +37,7 @@ method          scotch;
 // method          metis;
 // method          manual;
 // method          multiLevel;
+// method          structured;  // does 2D decomposition of structured mesh
 
 multiLevelCoeffs
 {
@@ -108,6 +109,15 @@ manualCoeffs
 }
 
 
+structuredCoeffs
+{
+    // Patches to do 2D decomposition on. Structured mesh only; cells have
+    // to be in 'columns' on top of patches.
+    patches     (bottomPatch);
+}
+
+
+
 //// Is the case distributed
 //distributed     yes;
 //// Per slave (so nProcs-1 entries) the directory above the case.
diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
index 4882c118a0bded103994f2264c9ff2169acdc4e1..36a6ad2eb4c10fe1ff21a4dc5f2c6af8a3465034 100644
--- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
+++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
@@ -860,6 +860,16 @@ bool Foam::domainDecomposition::writeDecomposition()
     scalar avgProcPatches = scalar(totProcPatches)/nProcs_;
     scalar avgProcFaces = scalar(totProcFaces)/nProcs_;
 
+    // In case of all faces on one processor. Just to avoid division by 0.
+    if (totProcPatches == 0)
+    {
+        avgProcPatches = 1;
+    }
+    if (totProcFaces == 0)
+    {
+        avgProcFaces = 1;
+    }
+
     Info<< nl
         << "Number of processor faces = " << totProcFaces/2 << nl
         << "Max number of cells = " << maxProcCells
diff --git a/applications/utilities/parallelProcessing/redistributeMeshPar/redistributeMeshPar.C b/applications/utilities/parallelProcessing/redistributeMeshPar/redistributeMeshPar.C
index 8812e78e64e9db58f617bf180807feeba3807b81..509bff88986f1cb87e2742980a013bd24414bd19 100644
--- a/applications/utilities/parallelProcessing/redistributeMeshPar/redistributeMeshPar.C
+++ b/applications/utilities/parallelProcessing/redistributeMeshPar/redistributeMeshPar.C
@@ -475,6 +475,16 @@ void printMeshData(const polyMesh& mesh)
     scalar avgProcPatches = scalar(totProcPatches)/Pstream::nProcs();
     scalar avgProcFaces = scalar(totProcFaces)/Pstream::nProcs();
 
+    // In case of all faces on one processor. Just to avoid division by 0.
+    if (totProcPatches == 0)
+    {
+        avgProcPatches = 1;
+    }
+    if (totProcFaces == 0)
+    {
+        avgProcFaces = 1;
+    }
+
     Info<< nl
         << "Number of processor faces = " << totProcFaces/2 << nl
         << "Max number of cells = " << maxProcCells
diff --git a/applications/utilities/surface/surfaceSubset/surfaceSubset.C b/applications/utilities/surface/surfaceSubset/surfaceSubset.C
index fb41623074d1eaba2993cd6c3b14379f0a5ec8c9..0fb1feed703b5d85e99bc874ab1c3e853f98a99e 100644
--- a/applications/utilities/surface/surfaceSubset/surfaceSubset.C
+++ b/applications/utilities/surface/surfaceSubset/surfaceSubset.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2011 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -249,7 +249,11 @@ int main(int argc, char *argv[])
         // search engine
         indexedOctree<treeDataTriSurface> selectTree
         (
-            treeDataTriSurface(selectSurf),
+            treeDataTriSurface
+            (
+                selectSurf,
+                indexedOctree<treeDataTriSurface>::perturbTol()
+            ),
             bb.extend(rndGen, 1E-4),    // slightly randomize bb
             8,      // maxLevel
             10,     // leafsize
diff --git a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C
index 10cb44fa272e2d7581a50d0a6083019745358525..a35b62474b93a655c98c0964ffecb999fafe0e43 100644
--- a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C
+++ b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C
@@ -714,7 +714,7 @@ Foam::point Foam::indexedOctree<Type>::pushPoint
 )
 {
     // Get local length scale.
-    const vector perturbVec = perturbTol_*(bb.span());
+    const vector perturbVec = perturbTol_*bb.span();
 
     point perturbedPt(pt);
 
diff --git a/src/meshTools/indexedOctree/treeDataTriSurface.C b/src/meshTools/indexedOctree/treeDataTriSurface.C
index 63c76de4825b465120f21a8f8c4c0b5c274e99c6..3ce85caa795a70f1078c4aa8a53723a962ec5aba 100644
--- a/src/meshTools/indexedOctree/treeDataTriSurface.C
+++ b/src/meshTools/indexedOctree/treeDataTriSurface.C
@@ -179,9 +179,14 @@ defineTypeNameAndDebug(Foam::treeDataTriSurface, 0);
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 // Construct from components
-Foam::treeDataTriSurface::treeDataTriSurface(const triSurface& surface)
+Foam::treeDataTriSurface::treeDataTriSurface
+(
+    const triSurface& surface,
+    const scalar planarTol
+)
 :
-    surface_(surface)
+    surface_(surface),
+    planarTol_(planarTol)
 {}
 
 
@@ -437,7 +442,7 @@ bool Foam::treeDataTriSurface::intersects
         dir,
         points,
         intersection::HALF_RAY,
-        indexedOctree<treeDataTriSurface>::perturbTol()
+        planarTol_
     );
 
     if (inter.hit() && inter.distance() <= 1)
diff --git a/src/meshTools/indexedOctree/treeDataTriSurface.H b/src/meshTools/indexedOctree/treeDataTriSurface.H
index 47778c61c598c348c0a523546e799ad92ac2ee69..4029b507ff29307b45a44f7d514ace1d5a1265a4 100644
--- a/src/meshTools/indexedOctree/treeDataTriSurface.H
+++ b/src/meshTools/indexedOctree/treeDataTriSurface.H
@@ -55,8 +55,11 @@ class treeDataTriSurface
 {
     // Private data
 
+        //- Reference to triSurface
         const triSurface& surface_;
 
+        //- Tolerance to use for intersection tests
+        const scalar planarTol_;
 
     // Private Member Functions
 
@@ -83,8 +86,9 @@ public:
 
     // Constructors
 
-        //- Construct from triSurface. Holds reference.
-        treeDataTriSurface(const triSurface&);
+        //- Construct from triSurface and tolerance for intersection
+        //  tests. Holds reference.
+        treeDataTriSurface(const triSurface&, const scalar planarTol);
 
 
     // Member Functions
diff --git a/src/meshTools/searchableSurface/triSurfaceMesh.C b/src/meshTools/searchableSurface/triSurfaceMesh.C
index c3c7c69b34b679fabae31596f057431daef1c72c..c532ac3d399754382004951df214177767d82208 100644
--- a/src/meshTools/searchableSurface/triSurfaceMesh.C
+++ b/src/meshTools/searchableSurface/triSurfaceMesh.C
@@ -492,7 +492,7 @@ void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
 
 
 const Foam::indexedOctree<Foam::treeDataTriSurface>&
-    Foam::triSurfaceMesh::tree() const
+Foam::triSurfaceMesh::tree() const
 {
     if (tree_.empty())
     {
@@ -528,7 +528,7 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>&
         (
             new indexedOctree<treeDataTriSurface>
             (
-                treeDataTriSurface(*this),
+                treeDataTriSurface(*this, tolerance_),
                 bb,
                 maxTreeDepth_,  // maxLevel
                 10,             // leafsize
@@ -544,7 +544,7 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>&
 
 
 const Foam::indexedOctree<Foam::treeDataEdge>&
- Foam::triSurfaceMesh::edgeTree() const
+Foam::triSurfaceMesh::edgeTree() const
 {
     if (edgeTree_.empty())
     {
diff --git a/src/meshTools/triSurface/triSurfaceSearch/triSurfaceSearch.C b/src/meshTools/triSurface/triSurfaceSearch/triSurfaceSearch.C
index 19a3e4953cc6b0abb8ddf42feea3b006b96c9049..92d8f8ad6dbb9d2d9dcfd280352499f83978f76a 100644
--- a/src/meshTools/triSurface/triSurfaceSearch/triSurfaceSearch.C
+++ b/src/meshTools/triSurface/triSurfaceSearch/triSurfaceSearch.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2011 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -64,7 +64,11 @@ Foam::triSurfaceSearch::triSurfaceSearch(const triSurface& surface)
     (
         new indexedOctree<treeDataTriSurface>
         (
-            treeDataTriSurface(surface_),
+            treeDataTriSurface
+            (
+                surface_,
+                indexedOctree<treeDataTriSurface>::perturbTol()
+            ),
             treeBb,
             8,      // maxLevel
             10,     // leafsize
diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
index 1cfb22887b7c795b97956e4b1336a75eaab9a84c..44d3cc027b778033ed40815d4c244e4288acbd30 100644
--- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
+++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C
@@ -448,8 +448,8 @@ void Foam::decompositionMethod::calcCellCells
     // Count number of faces (internal + coupled)
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    // Number of faces per cell
-    labelList nFacesPerCell(mesh.nCells(), 0);
+    // Number of faces per coarse cell
+    labelList nFacesPerCell(nCoarse, 0);
 
     for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
     {
@@ -481,7 +481,11 @@ void Foam::decompositionMethod::calcCellCells
             {
                 label own = agglom[faceOwner[faceI]];
                 label globalNei = globalNeighbour[bFaceI];
-                if (cellPair.insert(labelPair(own, globalNei)))
+                if
+                (
+                    globalAgglom.toGlobal(own) != globalNei
+                 && cellPair.insert(labelPair(own, globalNei))
+                )
                 {
                     nFacesPerCell[own]++;
                 }