diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/Make/files b/applications/utilities/mesh/manipulation/singleCellMesh/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..db941393b0800179cca310b587885dab85390ac7
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/singleCellMesh/Make/files
@@ -0,0 +1,3 @@
+singleCellMesh.C
+
+EXE = $(FOAM_APPBIN)/singleCellMesh
diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/Make/options b/applications/utilities/mesh/manipulation/singleCellMesh/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..89e52b6d520dc088e6516df08f0f521f188a6353
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/singleCellMesh/Make/options
@@ -0,0 +1,6 @@
+EXE_INC = \
+    -I$(LIB_SRC)/finiteVolume/lnInclude
+
+EXE_LIBS = \
+    -lfiniteVolume
+
diff --git a/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C b/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..fe1e2850b97cccd5304e6809d91b01649ee97a37
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/singleCellMesh/singleCellMesh.C
@@ -0,0 +1,142 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2007 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Application
+    singleCellMesh
+
+Description
+    Removes all but one cells of the mesh. Used to generate mesh and fields
+    that can be used for boundary-only data.
+    Might easily result in illegal mesh though so only look at boundaries
+    in paraview.
+
+\*---------------------------------------------------------------------------*/
+
+
+#include "argList.H"
+#include "fvMesh.H"
+#include "volFields.H"
+#include "Time.H"
+#include "ReadFields.H"
+#include "singleCellFvMesh.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+template<class GeoField>
+void interpolateFields
+(
+    const singleCellFvMesh& scMesh,
+    const PtrList<GeoField>& flds
+)
+{
+    forAll(flds, i)
+    {
+        tmp<GeoField> scFld = scMesh.interpolate(flds[i]);
+        GeoField* scFldPtr = scFld.ptr();
+        scFldPtr->writeOpt() = IOobject::AUTO_WRITE;
+        scFldPtr->store();
+    }
+}
+
+
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    Foam::argList::validOptions.insert("overwrite", "");
+#   include "addTimeOptions.H"
+#   include "setRootCase.H"
+#   include "createTime.H"
+    // Get times list
+    instantList Times = runTime.times();
+#   include "checkTimeOptions.H"
+    runTime.setTime(Times[startTime], startTime);
+#   include "createMesh.H"
+    const word oldInstance = mesh.pointsInstance();
+
+    bool overwrite = args.optionFound("overwrite");
+
+
+    // Read objects in time directory
+    IOobjectList objects(mesh, runTime.timeName());
+
+    // Read vol fields.
+    PtrList<volScalarField> vsFlds;
+    ReadFields(mesh, objects, vsFlds);
+
+    PtrList<volVectorField> vvFlds;
+    ReadFields(mesh, objects, vvFlds);
+
+    PtrList<volSphericalTensorField> vstFlds;
+    ReadFields(mesh, objects, vstFlds);
+
+    PtrList<volSymmTensorField> vsymtFlds;
+    ReadFields(mesh, objects, vsymtFlds);
+
+    PtrList<volTensorField> vtFlds;
+    ReadFields(mesh, objects, vtFlds);
+
+
+    if (!overwrite)
+    {
+        runTime++;
+    }
+
+    // Create the mesh
+    singleCellFvMesh scMesh
+    (
+        IOobject
+        (
+            mesh.name(),
+            mesh.polyMesh::instance(),
+            runTime,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE
+        ),
+        mesh
+    );
+
+
+    // Map and store the fields on the scMesh.
+    interpolateFields(scMesh, vsFlds);
+    interpolateFields(scMesh, vvFlds);
+    interpolateFields(scMesh, vstFlds);
+    interpolateFields(scMesh, vsymtFlds);
+    interpolateFields(scMesh, vtFlds);
+
+
+    // Write
+    Info<< "Writing mesh to time " << runTime.timeName() << endl;
+    scMesh.write();
+
+
+    Info<< "End\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H b/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H
new file mode 100644
index 0000000000000000000000000000000000000000..4afb30dd22888ee7cff0cf4357fe2ad5560ba186
--- /dev/null
+++ b/src/OpenFOAM/meshes/primitiveMesh/primitivePatch/uindirectPrimitivePatch.H
@@ -0,0 +1,53 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Typedef
+    Foam::uindirectPrimitivePatch
+
+Description
+    Foam::uindirectPrimitivePatch
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef uindirectPrimitivePatch_H
+#define uindirectPrimitivePatch_H
+
+#include "PrimitivePatch.H"
+#include "face.H"
+#include "UIndirectList.H"
+#include "pointField.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    typedef PrimitivePatch<face, UIndirectList, const pointField&>
+        uindirectPrimitivePatch;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files
index c387ac994d85f7ec289e4540a869539167ca71d2..5fe44b935751f8c95bdc23e7e561c1b40ac7b359 100644
--- a/src/finiteVolume/Make/files
+++ b/src/finiteVolume/Make/files
@@ -1,6 +1,7 @@
 fvMesh/fvMeshGeometry.C
 fvMesh/fvMesh.C
 
+fvMesh/singleCellFvMesh/singleCellFvMesh.C
 fvMesh/fvMeshSubset/fvMeshSubset.C
 
 fvBoundaryMesh = fvMesh/fvBoundaryMesh
diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..65965f15d94612cdee4cee766e017666dc73a4df
--- /dev/null
+++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.C
@@ -0,0 +1,640 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2009 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+\*---------------------------------------------------------------------------*/
+
+#include "singleCellFvMesh.H"
+#include "syncTools.H"
+#include "uindirectPrimitivePatch.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+// Conversion is a two step process:
+// - from original (fine) patch faces to agglomerations (aggloms might not
+//   be in correct patch order)
+// - from agglomerations to coarse patch faces
+void Foam::singleCellFvMesh::agglomerateMesh
+(
+    const fvMesh& mesh,
+    const labelListList& agglom
+)
+{
+    const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
+
+    // Check agglomeration within patch face range and continuous
+    labelList nAgglom(oldPatches.size());
+
+    forAll(oldPatches, patchI)
+    {
+        const polyPatch& pp = oldPatches[patchI];
+
+        nAgglom[patchI] = max(agglom[patchI])+1;
+
+        forAll(pp, i)
+        {
+            if (agglom[patchI][i] < 0  || agglom[patchI][i] >= pp.size())
+            {
+                FatalErrorIn
+                (
+                    "singleCellFvMesh::agglomerateMesh(..)"
+                )   << "agglomeration on patch " << patchI
+                    << " is out of range 0.." << pp.size()-1
+                    << exit(FatalError);
+            }
+        }
+    }
+
+    // Check agglomeration is sync
+    {
+        // Get neighbouring agglomeration
+        labelList nbrAgglom(mesh.nFaces()-mesh.nInternalFaces());
+        forAll(oldPatches, patchI)
+        {
+            const polyPatch& pp = oldPatches[patchI];
+
+            if (pp.coupled())
+            {
+                label offset = pp.start()-mesh.nInternalFaces();
+                forAll(pp, i)
+                {
+                    nbrAgglom[offset+i] = agglom[patchI][i];
+                }
+            }
+        }
+        syncTools::swapBoundaryFaceList(mesh, nbrAgglom, false);
+
+
+        // Get correspondence between this agglomeration and remote one
+        Map<label> localToNbr(nbrAgglom.size()/10);
+
+        forAll(oldPatches, patchI)
+        {
+            const polyPatch& pp = oldPatches[patchI];
+
+            if (pp.coupled())
+            {
+                label offset = pp.start()-mesh.nInternalFaces();
+
+                forAll(pp, i)
+                {
+                    label bFaceI = offset+i;
+                    label myZone = agglom[patchI][i];
+                    label nbrZone = nbrAgglom[bFaceI];
+
+                    Map<label>::const_iterator iter = localToNbr.find(myZone);
+
+                    if (iter == localToNbr.end())
+                    {
+                        // First occurence of this zone. Store correspondence
+                        // to remote zone number.
+                        localToNbr.insert(myZone, nbrZone);
+                    }
+                    else
+                    {
+                        // Check that zone numbers are still the same.
+                        if (iter() != nbrZone)
+                        {
+                            FatalErrorIn
+                            (
+                                "singleCellFvMesh::agglomerateMesh(..)"
+                            )   << "agglomeration is not synchronised across"
+                                << " coupled patch " << pp.name()
+                                << endl
+                                << "Local agglomeration " << myZone
+                                << ". Remote agglomeration " << nbrZone
+                                << exit(FatalError);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    label coarseI = 0;
+    forAll(nAgglom, patchI)
+    {
+        coarseI += nAgglom[patchI];
+    }
+    // New faces
+    faceList patchFaces(coarseI);
+    // New patch start and size
+    labelList patchStarts(oldPatches.size());
+    labelList patchSizes(oldPatches.size());
+
+    // From new patch face back to agglomeration
+    patchFaceMap_.setSize(oldPatches.size());
+
+    // Face counter
+    coarseI = 0;
+
+
+    forAll(oldPatches, patchI)
+    {
+        const polyPatch& pp = oldPatches[patchI];
+
+        if (pp.size() > 0)
+        {
+            patchFaceMap_[patchI].setSize(nAgglom[patchI]);
+
+            // Patchfaces per agglomeration
+            labelListList agglomToPatch
+            (
+                invertOneToMany(nAgglom[patchI], agglom[patchI])
+            );
+
+            // From agglomeration to compact patch face
+            labelList agglomToFace(nAgglom[patchI], -1);
+
+            patchStarts[patchI] = coarseI;
+
+            forAll(pp, i)
+            {
+                label myAgglom = agglom[patchI][i];
+
+                if (agglomToFace[myAgglom] == -1)
+                {
+                    // Agglomeration not yet done. We now have:
+                    // - coarseI                  : current coarse mesh face
+                    // - patchStarts[patchI]      : coarse mesh patch start
+                    // - myAgglom                 : agglomeration
+                    // -  agglomToPatch[myAgglom] : fine mesh faces for zone
+                    label coarsePatchFaceI = coarseI - patchStarts[patchI];
+                    patchFaceMap_[patchI][coarsePatchFaceI] = myAgglom;
+                    agglomToFace[myAgglom] = coarsePatchFaceI;
+
+                    const labelList& fineFaces = agglomToPatch[myAgglom];
+
+                    // Create overall map from fine mesh faces to coarseI.
+                    forAll(fineFaces, fineI)
+                    {
+                        reverseFaceMap_[pp.start()+fineFaces[fineI]] = coarseI;
+                    }
+
+                    // Construct single face
+                    uindirectPrimitivePatch upp
+                    (
+                        UIndirectList<face>(pp, fineFaces),
+                        pp.points()
+                    );
+
+                    if (upp.edgeLoops().size() != 1)
+                    {
+                        FatalErrorIn
+                        (
+                            "singleCellFvMesh::agglomerateMesh(..)"
+                        )   << "agglomeration does not create a"
+                            << " single, non-manifold"
+                            << " face for agglomeration " << coarseI
+                            << exit(FatalError);   
+                    }
+
+                    patchFaces[coarseI++] = face
+                    (
+                        renumber
+                        (
+                            upp.meshPoints(),
+                            upp.edgeLoops()[0]
+                        )
+                    );
+                }
+            }
+
+            patchSizes[patchI] = coarseI-patchStarts[patchI];
+        }
+    }
+
+    //Pout<< "patchStarts:" << patchStarts << endl;
+    //Pout<< "patchSizes:" << patchSizes << endl;
+
+    // Compact numbering for points
+    reversePointMap_.setSize(mesh.nPoints());
+    reversePointMap_.labelList::operator=(-1);
+    label newI = 0;
+
+    forAll(patchFaces, coarseI)
+    {
+        face& f = patchFaces[coarseI];
+
+        forAll(f, fp)
+        {
+            if (reversePointMap_[f[fp]] == -1)
+            {
+                reversePointMap_[f[fp]] = newI++;
+            }
+
+            f[fp] = reversePointMap_[f[fp]];
+        }
+    }
+
+    pointMap_ = invert(newI, reversePointMap_);
+
+    // Subset used points
+    pointField boundaryPoints(mesh.points(), pointMap_);
+
+    // Add patches (on still zero sized mesh)
+    List<polyPatch*> newPatches(oldPatches.size());
+    forAll(oldPatches, patchI)
+    {
+        newPatches[patchI] = oldPatches[patchI].clone
+        (
+            boundaryMesh(),
+            patchI,
+            0,
+            0
+        ).ptr();
+    }
+    addFvPatches(newPatches);
+
+    // Owner, neighbour is trivial
+    labelList owner(patchFaces.size(), 0);
+    labelList neighbour(0);
+
+
+    // actually change the mesh
+    resetPrimitives
+    (
+        xferMove(boundaryPoints),
+        xferMove(patchFaces),
+        xferMove(owner),
+        xferMove(neighbour),
+        patchSizes,
+        patchStarts,
+        true                //syncPar
+    );
+
+
+    // Adapt the zones
+    cellZones().clear();
+    cellZones().setSize(mesh.cellZones().size());
+    {
+        forAll(mesh.cellZones(), zoneI)
+        {
+            const cellZone& oldFz = mesh.cellZones()[zoneI];
+
+            DynamicList<label> newAddressing;
+
+            //Note: uncomment if you think it makes sense. Note that value
+            // of cell0 is the average.
+            //// Was old cell0 in this cellZone?
+            //if (oldFz.localID(0) != -1)
+            //{
+            //    newAddressing.append(0);
+            //}
+
+            cellZones().set
+            (
+                zoneI,
+                oldFz.clone
+                (
+                    newAddressing,
+                    zoneI,
+                    cellZones()
+                )
+            );
+        }
+    }
+
+    faceZones().clear();
+    faceZones().setSize(mesh.faceZones().size());
+    {
+        forAll(mesh.faceZones(), zoneI)
+        {
+            const faceZone& oldFz = mesh.faceZones()[zoneI];
+
+            DynamicList<label> newAddressing(oldFz.size());
+            DynamicList<bool> newFlipMap(oldFz.size());
+
+            forAll(oldFz, i)
+            {
+                label newFaceI = reverseFaceMap_[oldFz[i]];
+
+                if (newFaceI != -1)
+                {
+                    newAddressing.append(newFaceI);
+                    newFlipMap.append(oldFz.flipMap()[i]);
+                }
+            }
+
+            faceZones().set
+            (
+                zoneI,
+                oldFz.clone
+                (
+                    newAddressing,
+                    newFlipMap,
+                    zoneI,
+                    faceZones()
+                )
+            );
+        }
+    }
+
+
+    pointZones().clear();
+    pointZones().setSize(mesh.pointZones().size());
+    {
+        forAll(mesh.pointZones(), zoneI)
+        {
+            const pointZone& oldFz = mesh.pointZones()[zoneI];
+
+            DynamicList<label> newAddressing(oldFz.size());
+
+            forAll(oldFz, i)
+            {
+                label newPointI  = reversePointMap_[oldFz[i]];
+                if (newPointI != -1)
+                {
+                    newAddressing.append(newPointI);
+                }
+            }
+
+            pointZones().set
+            (
+                zoneI,
+                oldFz.clone
+                (
+                    pointZones(),
+                    zoneI,
+                    newAddressing
+                )
+            );
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::singleCellFvMesh::singleCellFvMesh
+(
+    const IOobject& io,
+    const fvMesh& mesh
+)
+:
+    fvMesh
+    (
+        io,
+        xferCopy(pointField()), //points
+        xferCopy(faceList()),   //faces
+        xferCopy(labelList()),  //allOwner
+        xferCopy(labelList()),  //allNeighbour
+        false                   //syncPar
+    ),
+    patchFaceAgglomeration_
+    (
+        IOobject
+        (
+            "patchFaceAgglomeration",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        0
+    ),
+    patchFaceMap_
+    (
+        IOobject
+        (
+            "patchFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.boundaryMesh().size()
+    ),
+    reverseFaceMap_
+    (
+        IOobject
+        (
+            "reverseFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nFaces()
+    ),
+    pointMap_
+    (
+        IOobject
+        (
+            "pointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nPoints()
+    ),
+    reversePointMap_
+    (
+        IOobject
+        (
+            "reversePointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nPoints()
+    )
+{
+    const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
+
+    labelListList agglom(oldPatches.size());
+
+    forAll(oldPatches, patchI)
+    {
+        agglom[patchI] = identity(oldPatches[patchI].size());
+    }
+
+    agglomerateMesh(mesh, agglom);
+}
+
+
+Foam::singleCellFvMesh::singleCellFvMesh
+(
+    const IOobject& io,
+    const fvMesh& mesh,
+    const labelListList& patchFaceAgglomeration
+)
+:
+    fvMesh
+    (
+        io,
+        xferCopy(pointField()), //points
+        xferCopy(faceList()),   //faces
+        xferCopy(labelList()),  //allOwner
+        xferCopy(labelList()),  //allNeighbour
+        false                   //syncPar
+    ),
+    patchFaceAgglomeration_
+    (
+        IOobject
+        (
+            "patchFaceAgglomeration",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        patchFaceAgglomeration
+    ),
+    patchFaceMap_
+    (
+        IOobject
+        (
+            "patchFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.boundaryMesh().size()
+    ),
+    reverseFaceMap_
+    (
+        IOobject
+        (
+            "reverseFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nFaces()
+    ),
+    pointMap_
+    (
+        IOobject
+        (
+            "pointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nPoints()
+    ),
+    reversePointMap_
+    (
+        IOobject
+        (
+            "reversePointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        ),
+        mesh.nPoints()
+    )
+{
+    agglomerateMesh(mesh, patchFaceAgglomeration);
+}
+
+
+Foam::singleCellFvMesh::singleCellFvMesh(const IOobject& io)
+:
+    fvMesh(io),
+    patchFaceAgglomeration_
+    (
+        IOobject
+        (
+            "patchFaceAgglomeration",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        )
+    ),
+    patchFaceMap_
+    (
+        IOobject
+        (
+            "patchFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        )
+    ),
+    reverseFaceMap_
+    (
+        IOobject
+        (
+            "reverseFaceMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        )
+    ),
+    pointMap_
+    (
+        IOobject
+        (
+            "pointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        )
+    ),
+    reversePointMap_
+    (
+        IOobject
+        (
+            "reversePointMap",
+            io.instance(),
+            fvMesh::meshSubDir,
+            *this,
+            io.readOpt(),
+            io.writeOpt()
+        )
+    )
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..2a412f1f933c2043d811a48496a0dd26a3c5532a
--- /dev/null
+++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMesh.H
@@ -0,0 +1,245 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2009 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Class
+    Foam::singleCellFvMesh
+
+Description
+    fvMesh as subset of other mesh. Consists of one cell and all original
+    bounday faces. Useful when manipulating boundary data. Single internal
+    cell only needed to be able to manipulate in a standard way.
+
+SourceFiles
+    singleCellFvMesh.C
+    singleCellFvMeshInterpolate.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef singleCellFvMesh_H
+#define singleCellFvMesh_H
+
+#include "fvPatchFieldMapper.H"
+#include "fvMesh.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                          Class singleCellFvMesh Declaration
+\*---------------------------------------------------------------------------*/
+
+class singleCellFvMesh
+:
+    public fvMesh
+{
+    // Private data
+
+        const labelListIOList patchFaceAgglomeration_;
+
+        //- From patch faces back to agglomeration or fine mesh
+        labelListIOList patchFaceMap_;
+
+        //- From fine mesh faces to coarse mesh
+        labelIOList reverseFaceMap_;
+
+        //- From coarse points back to original mesh
+        labelIOList pointMap_;
+
+        //- From fine points to coarse mesh
+        labelIOList reversePointMap_;
+
+
+    // Private Member Functions
+
+        //- Calculate agglomerated mesh
+        void agglomerateMesh(const fvMesh&, const labelListList&);
+
+
+        //- Disallow default bitwise copy construct
+        singleCellFvMesh(const singleCellFvMesh&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const singleCellFvMesh&);
+
+
+public:
+
+        //- Patch field mapper class for non-agglomerated meshes
+        class directPatchFieldMapper
+        :
+            public fvPatchFieldMapper
+        {
+            // Private data
+
+                const unallocLabelList& directAddressing_;
+
+        public:
+
+                //- Construct given addressing
+                directPatchFieldMapper(const unallocLabelList& directAddressing)
+                :
+                    directAddressing_(directAddressing)
+                {}
+
+                virtual label size() const
+                {
+                    return directAddressing_.size();
+                }
+
+                virtual bool direct() const
+                {
+                    return true;
+                }
+
+                virtual const unallocLabelList& directAddressing() const
+                {
+                    return directAddressing_;
+                }
+        };
+
+        //- Patch field mapper class for agglomerated meshes
+        class agglomPatchFieldMapper
+        :
+            public fvPatchFieldMapper
+        {
+            // Private data
+
+                const labelListList& addressing_;
+                const scalarListList& weights_;
+
+        public:
+
+                //- Construct given addressing
+                agglomPatchFieldMapper
+                (
+                    const labelListList& addressing,
+                    const scalarListList& weights
+                )
+                :
+                    addressing_(addressing),
+                    weights_(weights)
+                {}
+
+                virtual label size() const
+                {
+                    return addressing_.size();
+                }
+
+                virtual bool direct() const
+                {
+                    return false;
+                }
+
+                virtual const labelListList& addressing() const
+                {
+                    return addressing_;
+                }
+
+                virtual const scalarListList& weights() const
+                {
+                    return weights_;
+                }
+        };
+
+
+
+    // Constructors
+
+        //- Construct from fvMesh and no agglomeration
+        singleCellFvMesh(const IOobject& io, const fvMesh&);
+
+        //- Construct from fvMesh and agglomeration of boundary faces.
+        //  agglomeration is per patch, per patch face index the agglomeration
+        //  the face goes into.
+        singleCellFvMesh
+        (
+            const IOobject& io,
+            const fvMesh&,
+            const labelListList& patchFaceAgglomeration
+        );
+
+        //- Read from IOobject
+        singleCellFvMesh(const IOobject& io);
+
+    // Member Functions
+
+        bool agglomerate() const
+        {
+            return patchFaceAgglomeration_.size() > 0;
+        }
+
+        //- From patchFace on this back to original mesh or agglomeration
+        const labelListList& patchFaceMap() const
+        {
+            return patchFaceMap_;
+        }
+
+        //- From point on this back to original mesh
+        const labelList& pointMap() const
+        {
+            return pointMap_;
+        }
+
+        //- From face on original mesh to face on this
+        const labelList& reverseFaceMap() const
+        {
+            return reverseFaceMap_;
+        }
+
+        //- From point on original mesh to point on this (or -1 for removed
+        //  points)
+        const labelList& reversePointMap() const
+        {
+            return reversePointMap_;
+        }
+
+        //- Map volField. Internal field set to average, patch fields straight
+        //  copies.
+        template<class Type>
+        tmp<GeometricField<Type, fvPatchField, volMesh> >
+        interpolate
+        (
+            const GeometricField<Type, fvPatchField, volMesh>&
+        ) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+#   include "singleCellFvMeshInterpolate.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C
new file mode 100644
index 0000000000000000000000000000000000000000..9e3a21a7b8711261d07377482390a7f3c7302109
--- /dev/null
+++ b/src/finiteVolume/fvMesh/singleCellFvMesh/singleCellFvMeshInterpolate.C
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+\*---------------------------------------------------------------------------*/
+
+#include "singleCellFvMesh.H"
+#include "Time.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+tmp<GeometricField<Type, fvPatchField, volMesh> > singleCellFvMesh::interpolate
+(
+    const GeometricField<Type, fvPatchField, volMesh>& vf
+) const
+{
+    // Create internal-field values
+    Field<Type> internalField(1, gAverage(vf));
+
+    // Create and map the patch field values
+    PtrList<fvPatchField<Type> > patchFields(vf.boundaryField().size());
+
+    if (agglomerate())
+    {
+        forAll(vf.boundaryField(), patchI)
+        {
+            const labelList& agglom = patchFaceAgglomeration_[patchI];
+            label nAgglom = max(agglom)+1;
+
+            // Use inverse of agglomeration. This is from agglomeration to
+            // original (fine) mesh patch face.
+            labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
+            inplaceReorder(patchFaceMap_[patchI], coarseToFine);
+            scalarListList coarseWeights(nAgglom);
+            forAll(coarseToFine, coarseI)
+            {
+                const labelList& fineFaces = coarseToFine[coarseI];
+                coarseWeights[coarseI] = scalarList
+                (
+                    fineFaces.size(),
+                    1.0/fineFaces.size()
+                );
+            }
+
+            patchFields.set
+            (
+                patchI,
+                fvPatchField<Type>::New
+                (
+                    vf.boundaryField()[patchI],
+                    boundary()[patchI],
+                    DimensionedField<Type, volMesh>::null(),
+                    agglomPatchFieldMapper(coarseToFine, coarseWeights)
+                )
+            );
+        }
+    }
+    else
+    {
+        forAll(vf.boundaryField(), patchI)
+        {
+            labelList map(identity(vf.boundaryField()[patchI].size()));
+
+            patchFields.set
+            (
+                patchI,
+                fvPatchField<Type>::New
+                (
+                    vf.boundaryField()[patchI],
+                    boundary()[patchI],
+                    DimensionedField<Type, volMesh>::null(),
+                    directPatchFieldMapper(map)
+                )
+            );
+        }
+    }
+
+    // Create the complete field from the pieces
+    tmp<GeometricField<Type, fvPatchField, volMesh> > tresF
+    (
+        new GeometricField<Type, fvPatchField, volMesh>
+        (
+            IOobject
+            (
+                vf.name(),
+                time().timeName(),
+                *this,
+                IOobject::NO_READ,
+                IOobject::NO_WRITE
+            ),
+            *this,
+            vf.dimensions(),
+            internalField,
+            patchFields
+        )
+    );
+
+    return tresF;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// ************************************************************************* //