diff --git a/src/postProcessing/functionObjects/field/Make/files b/src/postProcessing/functionObjects/field/Make/files
index 1ea75cf3ff..ba19ff80a0 100644
--- a/src/postProcessing/functionObjects/field/Make/files
+++ b/src/postProcessing/functionObjects/field/Make/files
@@ -29,6 +29,11 @@ streamLine/streamLineParticle.C
streamLine/streamLineParticleCloud.C
streamLine/streamLineFunctionObject.C
+wallBoundedStreamLine/wallBoundedStreamLine.C
+wallBoundedStreamLine/wallBoundedStreamLineFunctionObject.C
+wallBoundedStreamLine/wallBoundedStreamLineParticle.C
+wallBoundedStreamLine/wallBoundedStreamLineParticleCloud.C
+
surfaceInterpolateFields/surfaceInterpolateFields.C
surfaceInterpolateFields/surfaceInterpolateFieldsFunctionObject.C
diff --git a/src/postProcessing/functionObjects/field/wallBoundedStreamLine/controlDict b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/controlDict
new file mode 100644
index 0000000000..4a3f4fe29c
--- /dev/null
+++ b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/controlDict
@@ -0,0 +1,144 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| ========= | |
+| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
+| \\ / O peration | Version: 2.0.0 |
+| \\ / A nd | Web: www.OpenFOAM.org |
+| \\/ M anipulation | |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+ version 2.0;
+ format ascii;
+ class dictionary;
+ object controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application icoFoam;
+
+startFrom startTime;
+
+startTime 0;
+
+stopAt endTime;
+
+endTime 0.5;
+
+deltaT 0.005;
+
+writeControl timeStep;
+
+writeInterval 20;
+
+purgeWrite 0;
+
+writeFormat ascii;
+
+writePrecision 6;
+
+writeCompression off;
+
+timeFormat general;
+
+timePrecision 6;
+
+runTimeModifiable true;
+
+functions
+{
+ readFields
+ {
+ // Where to load it from (if not already in solver)
+ functionObjectLibs ("libfieldFunctionObjects.so");
+
+ type readFields;
+ fields (p U k);
+ }
+
+ near
+ {
+ // Where to load it from
+ functionObjectLibs ("libfieldFunctionObjects.so");
+
+ type nearWallFields;
+
+ // Output every
+ outputControl outputTime;
+ //outputInterval 1;
+
+ // Fields to be sampled. Per field original name and mapped field to
+ // create.
+ fields
+ (
+ (U UNear)
+ );
+
+ // Patches/groups to sample (regular expressions)
+ patches (motorBike);
+
+ // Distance to sample
+ distance 0.001;
+ }
+ streamLines
+ {
+ // Where to load it from (if not already in solver)
+ functionObjectLibs ("libfieldFunctionObjects.so");
+ type wallBoundedStreamLine;
+
+ // Output every
+ outputControl timeStep; //outputTime;
+ // outputInterval 10;
+
+ setFormat vtk; //gnuplot; //xmgr; //raw; //jplot;
+
+ // Velocity field to use for tracking.
+ UName UNear;
+
+ // Interpolation method. Default is cellPoint. See sampleDict.
+ //interpolationScheme pointMVC;
+
+ // Tracked forwards (+U) or backwards (-U)
+ trackForward true;
+
+ interpolationScheme cellPoint;
+
+ // Names of fields to sample. Should contain above velocity field!
+ fields (p U k UNear);
+
+ // Steps particles can travel before being removed
+ lifeTime 100;
+
+ // Cloud name to use
+ cloudName particleTracks;
+
+ // Seeding method. See the sampleSets in sampleDict.
+ seedSampleSet patchSeed; //cloud;//triSurfaceMeshPointSet;
+
+ uniformCoeffs
+ {
+ type uniform;
+ axis x; //distance;
+
+ start (0.0035 0.0999 0.0001);
+ end (0.0035 0.0999 0.0099);
+ nPoints 20;
+ }
+
+ cloudCoeffs
+ {
+ type cloud;
+ axis x; //distance;
+ points ((0.351516548679288 -0.0116085375585099 1.24));
+ }
+ patchSeedCoeffs
+ {
+ type patchSeed;//patchCloud; //cloud; //uniform;
+ patches (motorBike);
+ axis x; //distance;
+ maxPoints 20000;
+ }
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C
new file mode 100644
index 0000000000..4b6f6761f7
--- /dev/null
+++ b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C
@@ -0,0 +1,887 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "Pstream.H"
+#include "functionObjectList.H"
+#include "wallBoundedStreamLine.H"
+#include "fvMesh.H"
+#include "wallBoundedStreamLineParticleCloud.H"
+#include "ReadFields.H"
+#include "meshSearch.H"
+#include "sampledSet.H"
+#include "globalIndex.H"
+#include "mapDistribute.H"
+#include "interpolationCellPoint.H"
+#include "PatchTools.H"
+#include "meshSearchMeshObject.H"
+#include "faceSet.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+defineTypeNameAndDebug(Foam::wallBoundedStreamLine, 0);
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+Foam::autoPtr
+Foam::wallBoundedStreamLine::wallPatch() const
+{
+ const fvMesh& mesh = dynamic_cast(obr_);
+
+ const polyBoundaryMesh& patches = mesh.boundaryMesh();
+
+ label nFaces = 0;
+
+ forAll(patches, patchI)
+ {
+ //if (!polyPatch::constraintType(patches[patchI].type()))
+ if (isA(patches[patchI]))
+ {
+ nFaces += patches[patchI].size();
+ }
+ }
+
+ labelList addressing(nFaces);
+
+ nFaces = 0;
+
+ forAll(patches, patchI)
+ {
+ //if (!polyPatch::constraintType(patches[patchI].type()))
+ if (isA(patches[patchI]))
+ {
+ const polyPatch& pp = patches[patchI];
+
+ forAll(pp, i)
+ {
+ addressing[nFaces++] = pp.start()+i;
+ }
+ }
+ }
+
+ return autoPtr
+ (
+ new indirectPrimitivePatch
+ (
+ IndirectList
+ (
+ mesh.faces(),
+ addressing
+ ),
+ mesh.points()
+ )
+ );
+}
+
+
+Foam::tetIndices Foam::wallBoundedStreamLine::findNearestTet
+(
+ const PackedBoolList& isWallPatch,
+ const point& seedPt,
+ const label cellI
+) const
+{
+ const fvMesh& mesh = dynamic_cast(obr_);
+
+ const cell& cFaces = mesh.cells()[cellI];
+
+ label minFaceI = -1;
+ label minTetPtI = -1;
+ scalar minDistSqr = sqr(GREAT);
+
+ forAll(cFaces, cFaceI)
+ {
+ label faceI = cFaces[cFaceI];
+
+ if (isWallPatch[faceI])
+ {
+ const face& f = mesh.faces()[faceI];
+ const label fp0 = mesh.tetBasePtIs()[faceI];
+ const point& basePoint = mesh.points()[f[fp0]];
+
+ label fp = f.fcIndex(fp0);
+ for (label i = 2; i < f.size(); i++)
+ {
+ const point& thisPoint = mesh.points()[f[fp]];
+ label nextFp = f.fcIndex(fp);
+ const point& nextPoint = mesh.points()[f[nextFp]];
+
+ const triPointRef tri(basePoint, thisPoint, nextPoint);
+
+ scalar d2 = magSqr(tri.centre() - seedPt);
+ if (d2 < minDistSqr)
+ {
+ minDistSqr = d2;
+ minFaceI = faceI;
+ minTetPtI = i-1;
+ }
+ fp = nextFp;
+ }
+ }
+ }
+
+ // Put particle in tet
+ return tetIndices
+ (
+ cellI,
+ minFaceI,
+ minTetPtI,
+ mesh
+ );
+}
+
+
+void Foam::wallBoundedStreamLine::track()
+{
+ const Time& runTime = obr_.time();
+ const fvMesh& mesh = dynamic_cast(obr_);
+
+
+ // Determine the 'wall' patches
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // These are the faces that need to be followed
+
+ autoPtr boundaryPatch(wallPatch());
+ PackedBoolList isWallPatch(mesh.nFaces());
+ forAll(boundaryPatch().addressing(), i)
+ {
+ isWallPatch[boundaryPatch().addressing()[i]] = 1;
+ }
+
+
+
+ // Find nearest wall particle for the seedPoints
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ IDLList initialParticles;
+ wallBoundedStreamLineParticleCloud particles
+ (
+ mesh,
+ cloudName_,
+ initialParticles
+ );
+
+ {
+ // Get the seed points
+ // ~~~~~~~~~~~~~~~~~~~
+
+ const sampledSet& seedPoints = sampledSetPtr_();
+
+
+ forAll(seedPoints, i)
+ {
+ const point& seedPt = seedPoints[i];
+ label cellI = seedPoints.cells()[i];
+
+ tetIndices ids(findNearestTet(isWallPatch, seedPt, cellI));
+
+ if (ids.face() != -1 && isWallPatch[ids.face()])
+ {
+ //Pout<< "Seeding particle :" << nl
+ // << " seedPt:" << seedPt << nl
+ // << " face :" << ids.face() << nl
+ // << " at :" << mesh.faceCentres()[ids.face()] << nl
+ // << " cell :" << mesh.cellCentres()[ids.cell()] << nl
+ // << endl;
+
+ particles.addParticle
+ (
+ new wallBoundedStreamLineParticle
+ (
+ mesh,
+ ids.faceTri(mesh).centre(),
+ ids.cell(),
+ ids.face(), // tetFace
+ ids.tetPt(),
+ -1, // not on a mesh edge
+ -1, // not on a diagonal edge
+ lifeTime_ // lifetime
+ )
+ );
+ }
+ else
+ {
+ Pout<< type() << " : ignoring seed " << seedPt
+ << " since not in wall cell." << endl;
+ }
+ }
+ }
+
+ label nSeeds = returnReduce(particles.size(), sumOp