diff --git a/src/sampling/probes/patchProbes.C b/src/sampling/probes/patchProbes.C
index b6792ea08cd35ba9befff7b07b9f6ead6c9c5508..3c6d2329b38215138874c1da2e040b8ecc502d61 100644
--- a/src/sampling/probes/patchProbes.C
+++ b/src/sampling/probes/patchProbes.C
@@ -46,32 +46,41 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
 
     const polyBoundaryMesh& bm = mesh.boundaryMesh();
 
-    label patchI = bm.findPatchID(patchName_);
+    // All the info for nearest. Construct to miss
+    List<mappedPatchBase::nearInfo> nearest(this->size());
 
-    if (patchI == -1)
-    {
-        FatalErrorIn
-        (
-            " Foam::patchProbes::findElements(const fvMesh&)"
-        )   << " Unknown patch name "
-            << patchName_ << endl
-            << exit(FatalError);
-    }
 
-     // All the info for nearest. Construct to miss
-    List<mappedPatchBase::nearInfo> nearest(this->size());
+    const labelList patchIDs(bm.patchSet(patchNames_).sortedToc());
 
-    const polyPatch& pp = bm[patchI];
+    label nFaces = 0;
+    forAll(patchIDs, i)
+    {
+        nFaces += bm[patchIDs[i]].size();
+    }
 
-    if (pp.size() > 0)
+    if (nFaces > 0)
     {
-        labelList bndFaces(pp.size());
-        forAll(bndFaces, i)
+        // Collect mesh faces and bounding box
+        labelList bndFaces(nFaces);
+        treeBoundBox overallBb(treeBoundBox::invertedBox);
+
+        nFaces = 0;
+        forAll(patchIDs, i)
         {
-            bndFaces[i] =  pp.start() + i;
+            const polyPatch& pp = bm[patchIDs[i]];
+            forAll(pp, i)
+            {
+                bndFaces[nFaces++] = pp.start()+i;
+                const face& f = pp[i];
+                forAll(f, fp)
+                {
+                    const point& pt = pp.points()[f[fp]];
+                    overallBb.min() = min(overallBb.min(), pt);
+                    overallBb.max() = max(overallBb.max(), pt);
+                }
+            }
         }
 
-        treeBoundBox overallBb(pp.points());
         Random rndGen(123456);
         overallBb = overallBb.extend(rndGen, 1e-4);
         overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
@@ -106,11 +115,7 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
 
             if (!info.hit())
             {
-                info = boundaryTree.findNearest
-                (
-                    sample,
-                    Foam::sqr(GREAT)
-                );
+                info = boundaryTree.findNearest(sample, Foam::sqr(GREAT));
             }
 
             label faceI = boundaryTree.shapes().faceLabels()[info.index()];
@@ -129,20 +134,26 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
                 << " This sample will not be included "
                 << endl;
             }
-            else
+            else if (info.hit())
             {
-                const point& fc = mesh.faceCentres()[faceI];
+                // Note: do we store the face centre or the actual nearest?
+                // We interpolate using the faceI only though (no
+                // interpolation) so it does not actually matter much, just for
+                // the location written to the header.
+
+                //const point& facePt = mesh.faceCentres()[faceI];
+                const point& facePt = info.hitPoint();
 
                 mappedPatchBase::nearInfo sampleInfo;
 
                 sampleInfo.first() = pointIndexHit
                 (
                     true,
-                    fc,
+                    facePt,
                     faceI
                 );
 
-                sampleInfo.second().first() = magSqr(fc-sample);
+                sampleInfo.second().first() = magSqr(facePt-sample);
                 sampleInfo.second().second() = Pstream::myProcNo();
 
                 nearest[probeI]= sampleInfo;
@@ -155,6 +166,14 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
     Pstream::listCombineGather(nearest, mappedPatchBase::nearestEqOp());
     Pstream::listCombineScatter(nearest);
 
+
+    // Update actual probe locations
+    forAll(nearest, sampleI)
+    {
+        operator[](sampleI) = nearest[sampleI].first().rawPoint();
+    }
+
+
     if (debug)
     {
         Info<< "patchProbes::findElements" << " : " << endl;
@@ -165,26 +184,41 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
 
             Info<< "    " << sampleI << " coord:"<< operator[](sampleI)
                 << " found on processor:" << procI
-                << " in local cell/face:" << localI
-                << " with fc:" << nearest[sampleI].first().rawPoint() << endl;
+                << " in local face:" << localI
+                << " with location:" << nearest[sampleI].first().rawPoint()
+                << endl;
         }
     }
 
 
     // Extract any local faces to sample
-    elementList_.setSize(nearest.size(), -1);
+    elementList_.setSize(nearest.size());
+    elementList_ = -1;
+    faceList_.setSize(nearest.size());
+    faceList_ = -1;
 
     forAll(nearest, sampleI)
     {
         if (nearest[sampleI].second().second() == Pstream::myProcNo())
         {
             // Store the face to sample
-            elementList_[sampleI] = nearest[sampleI].first().index();
+            faceList_[sampleI] = nearest[sampleI].first().index();
         }
     }
 }
 
 
+void Foam::patchProbes::readDict(const dictionary& dict)
+{
+    if (!dict.readIfPresent("patches", patchNames_))
+    {
+        word patchName(dict.lookup("patchName"));
+        patchNames_ = wordReList(1, wordRe(patchName));
+    }
+    probes::readDict(dict);
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::patchProbes::patchProbes
@@ -192,19 +226,22 @@ Foam::patchProbes::patchProbes
     const word& name,
     const objectRegistry& obr,
     const dictionary& dict,
-    const bool loadFromFiles
+    const bool loadFromFiles,
+    const bool doFindElements
 )
 :
-    probes(name, obr, dict, loadFromFiles)
+    probes(name, obr, dict, loadFromFiles, false)
 {
-    // When constructing probes above it will have called the
-    // probes::findElements (since the virtual mechanism not yet operating).
-    // Not easy to workaround (apart from feeding through flag into constructor)
-    // so clear out any cells found for now.
-    elementList_.clear();
-    faceList_.clear();
-
-    read(dict);
+    readDict(dict);
+
+    if (doFindElements)
+    {
+        // Find the elements
+        findElements(mesh_);
+
+        // Open the probe streams
+        prepare();
+    }
 }
 
 
@@ -232,10 +269,16 @@ void Foam::patchProbes::write()
     }
 }
 
+
 void Foam::patchProbes::read(const dictionary& dict)
 {
-    dict.lookup("patchName") >> patchName_;
-    probes::read(dict);
+    readDict(dict);
+
+    // Find the elements
+    findElements(mesh_);
+
+    // Open the probe streams
+    prepare();
 }
 
 
diff --git a/src/sampling/probes/patchProbes.H b/src/sampling/probes/patchProbes.H
index 2425b67f776bff4d4bc5464b42a9acea84d55fb9..e24b05efcec3f5ad4d9a621af52f3ac3369d450a 100644
--- a/src/sampling/probes/patchProbes.H
+++ b/src/sampling/probes/patchProbes.H
@@ -25,9 +25,45 @@ Class
     Foam::patchProbes
 
 Description
-    Set of locations to sample.at patches
+    Set of locations to sample at patches
 
     Call write() to sample and write files.
+    - find nearest location on nearest face
+    - update *this with location (so header contains 'snapped' locations
+    - use *this as the sampling location
+
+    Example of function object specification:
+    \verbatim
+    patchProbes
+    {
+        type            patchProbes;
+        functionObjectLibs ( "libsampling.so" );
+
+        // Name of the directory for probe data
+        name            patchProbes;
+
+        // Patches to sample (wildcards allowed)
+        patches         (".*inl.*");
+
+        // Write at same frequency as fields
+        outputControl   outputTime;
+        outputInterval  1;
+
+        // Fields to be probed
+        fields
+        (
+            p U
+        );
+
+        // Locations to probe. These get snapped onto the nearest point
+        // on the selected patches
+        probeLocations
+        (
+            ( -100 0 0.01 )      // at inlet
+        );
+    }
+    \endverbatim
+
 
 SourceFiles
     patchProbes.C
@@ -58,13 +94,15 @@ class patchProbes
 :
     public probes
 {
-    // Private data
+protected:
+
+    // Protected data
 
-        //- Patch name
-        word patchName_;
+        //- Patches to sample
+        wordReList patchNames_;
 
 
-    // Private Member Functions
+    // Protected Member Functions
 
         //- Sample and write a particular volume field
         template<class Type>
@@ -73,7 +111,6 @@ class patchProbes
             const GeometricField<Type, fvPatchField, volMesh>&
         );
 
-
         //- Sample and write a particular surface field
         template<class Type>
         void sampleAndWrite
@@ -81,17 +118,14 @@ class patchProbes
             const GeometricField<Type, fvsPatchField, surfaceMesh>&
         );
 
-
         //- Sample and write all the fields of the given type
         template<class Type>
         void sampleAndWrite(const fieldGroup<Type>&);
 
-
          //- Sample and write all the surface fields of the given type
         template<class Type>
         void sampleAndWriteSurfaceFields(const fieldGroup<Type>&);
 
-
         //- Sample a volume field at all locations
         template<class Type>
         tmp<Field<Type> > sample
@@ -99,7 +133,6 @@ class patchProbes
             const GeometricField<Type, fvPatchField, volMesh>&
         ) const;
 
-
         //- Sample a surface field at all locations
         template<class Type>
         tmp<Field<Type> > sample
@@ -107,11 +140,18 @@ class patchProbes
             const GeometricField<Type, fvsPatchField, surfaceMesh>&
         ) const;
 
-
         //- Sample a single field on all sample locations
         template<class Type>
         tmp<Field<Type> > sample(const word& fieldName) const;
 
+        //- Find elements containing patchProbes
+        virtual void findElements(const fvMesh&);
+
+        //- Read dictionary settings
+        void readDict(const dictionary& dict);
+
+
+private:
 
         //- Disallow default bitwise copy construct
         patchProbes(const patchProbes&);
@@ -135,7 +175,8 @@ public:
             const word& name,
             const objectRegistry&,
             const dictionary&,
-            const bool loadFromFiles = false
+            const bool loadFromFiles = false,
+            const bool findElements = true
         );
 
 
@@ -149,9 +190,6 @@ public:
 
         //- Read
         virtual void read(const dictionary&);
-
-        //- Find elements containing patchProbes
-        virtual void findElements(const fvMesh&);
 };
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/sampling/probes/patchProbesTemplates.C b/src/sampling/probes/patchProbesTemplates.C
index 7e8ddd74b427bfcdaddc957e16f053a768c6b1d5..e0ff2206e74b893c498f5ebf2529efb1ef9d92bf 100644
--- a/src/sampling/probes/patchProbesTemplates.C
+++ b/src/sampling/probes/patchProbesTemplates.C
@@ -208,7 +208,7 @@ Foam::patchProbes::sample
 
     forAll(*this, probeI)
     {
-        label faceI = elementList_[probeI];
+        label faceI = faceList_[probeI];
 
         if (faceI >= 0)
         {
@@ -259,7 +259,7 @@ Foam::patchProbes::sample
 
     forAll(*this, probeI)
     {
-        label faceI = elementList_[probeI];
+        label faceI = faceList_[probeI];
 
         if (faceI >= 0)
         {
@@ -274,4 +274,6 @@ Foam::patchProbes::sample
 
     return tValues;
 }
+
+
 // ************************************************************************* //
diff --git a/src/sampling/probes/probes.C b/src/sampling/probes/probes.C
index 38ef3a63b47cca6388358bd289e320a3842d8f51..fd13764fab37c3e3725d1b462a9b51ddec0ef67d 100644
--- a/src/sampling/probes/probes.C
+++ b/src/sampling/probes/probes.C
@@ -265,6 +265,25 @@ Foam::label Foam::probes::prepare()
 }
 
 
+void Foam::probes::readDict(const dictionary& dict)
+{
+    dict.lookup("probeLocations") >> *this;
+    dict.lookup("fields") >> fieldSelection_;
+
+    dict.readIfPresent("fixedLocations", fixedLocations_);
+    if (dict.readIfPresent("interpolationScheme", interpolationScheme_))
+    {
+        if (!fixedLocations_ && interpolationScheme_ != "cell")
+        {
+            WarningIn("void Foam::probes::read(const dictionary&)")
+                << "Only cell interpolation can be applied when "
+                << "not using fixedLocations. InterpolationScheme "
+                << "entry will be ignored";
+        }
+    }
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::probes::probes
@@ -272,7 +291,8 @@ Foam::probes::probes
     const word& name,
     const objectRegistry& obr,
     const dictionary& dict,
-    const bool loadFromFiles
+    const bool loadFromFiles,
+    const bool doFindElements
 )
 :
     pointField(0),
@@ -283,7 +303,18 @@ Foam::probes::probes
     fixedLocations_(true),
     interpolationScheme_("cell")
 {
-    read(dict);
+    // Read dictionary (but do not search for elements)
+    readDict(dict);
+
+    // Optionally find elements in constructor
+    if (doFindElements)
+    {
+        // Find the elements
+        findElements(mesh_);
+
+        // Open the probe streams
+        prepare();
+    }
 }
 
 
@@ -334,24 +365,12 @@ void Foam::probes::write()
 
 void Foam::probes::read(const dictionary& dict)
 {
-    dict.lookup("probeLocations") >> *this;
-    dict.lookup("fields") >> fieldSelection_;
+    readDict(dict);
 
-    dict.readIfPresent("fixedLocations", fixedLocations_);
-    if (dict.readIfPresent("interpolationScheme", interpolationScheme_))
-    {
-        if (!fixedLocations_ && interpolationScheme_ != "cell")
-        {
-            WarningIn("void Foam::probes::read(const dictionary&)")
-                << "Only cell interpolation can be applied when "
-                << "not using fixedLocations.  InterpolationScheme "
-                << "entry will be ignored";
-        }
-    }
-
-    // Initialise cells to sample from supplied locations
+    // Find the elements
     findElements(mesh_);
 
+    // Open the probe streams
     prepare();
 }
 
@@ -382,20 +401,28 @@ void Foam::probes::updateMesh(const mapPolyMesh& mpm)
             forAll(elementList_, i)
             {
                 label cellI = elementList_[i];
-                label newCellI = reverseMap[cellI];
-                if (newCellI == -1)
+                if (cellI != -1)
                 {
-                    // cell removed
-                }
-                else if (newCellI < -1)
-                {
-                    // cell merged
-                    elems.append(-newCellI - 2);
+                    label newCellI = reverseMap[cellI];
+                    if (newCellI == -1)
+                    {
+                        // cell removed
+                    }
+                    else if (newCellI < -1)
+                    {
+                        // cell merged
+                        elems.append(-newCellI - 2);
+                    }
+                    else
+                    {
+                        // valid new cell
+                        elems.append(newCellI);
+                    }
                 }
                 else
                 {
-                    // valid new cell
-                    elems.append(newCellI);
+                    // Keep -1 elements so the size stays the same
+                    elems.append(-1);
                 }
             }
 
@@ -410,20 +437,28 @@ void Foam::probes::updateMesh(const mapPolyMesh& mpm)
             forAll(faceList_, i)
             {
                 label faceI = faceList_[i];
-                label newFaceI = reverseMap[faceI];
-                if (newFaceI == -1)
-                {
-                    // face removed
-                }
-                else if (newFaceI < -1)
+                if (faceI != -1)
                 {
-                    // face merged
-                    elems.append(-newFaceI - 2);
+                    label newFaceI = reverseMap[faceI];
+                    if (newFaceI == -1)
+                    {
+                        // face removed
+                    }
+                    else if (newFaceI < -1)
+                    {
+                        // face merged
+                        elems.append(-newFaceI - 2);
+                    }
+                    else
+                    {
+                        // valid new face
+                        elems.append(newFaceI);
+                    }
                 }
                 else
                 {
-                    // valid new face
-                    elems.append(newFaceI);
+                    // Keep -1 elements
+                    elems.append(-1);
                 }
             }
 
diff --git a/src/sampling/probes/probes.H b/src/sampling/probes/probes.H
index 5cc8c9f50c0ec9a050f5b857b56c9f9ffbfad830..ec759f11139df2fc067fad5accba6a2cbc185796 100644
--- a/src/sampling/probes/probes.H
+++ b/src/sampling/probes/probes.H
@@ -32,6 +32,42 @@ Description
 
     Call write() to sample and write files.
 
+    Example of function object specification:
+    \verbatim
+    probes
+    {
+        type            probes;
+        functionObjectLibs ( "libsampling.so" );
+
+        // Name of the directory for probe data
+        name            probes;
+
+        // Write at same frequency as fields
+        outputControl   outputTime;
+        outputInterval  1;
+
+        // Fields to be probed
+        fields
+        (
+            p U
+        );
+
+        // Optional: do not recalculate cells if mesh moves
+        fixedLocations  false;
+
+        // Optional: interpolation scheme to use (default is cell)
+        interpolationScheme cellPoint;
+
+        probeLocations
+        (
+            ( 1e-06 0 0.01 )      // at inlet
+            (0.21 -0.20999 0.01)  // at outlet1
+            (0.21 0.20999 0.01)   // at outlet2
+            (0.21 0 0.01)         // at central block
+        );
+    }
+    \endverbatim
+
 SourceFiles
     probes.C
 
@@ -91,13 +127,13 @@ protected:
 
         //- Name of this set of probes,
         //  Also used as the name of the probes directory.
-        word name_;
+        const word name_;
 
         //- Const reference to fvMesh
         const fvMesh& mesh_;
 
         //- Load fields from files (not from objectRegistry)
-        bool loadFromFiles_;
+        const bool loadFromFiles_;
 
 
         // Read from dictonary
@@ -106,7 +142,7 @@ protected:
             wordReList fieldSelection_;
 
             //- Fixed locations, default = yes
-            //  Note: set to false for moving mesh calations where locations
+            //  Note: set to false for moving mesh calculations where locations
             //        should move with the mesh
             bool fixedLocations_;
 
@@ -141,7 +177,7 @@ protected:
             HashPtrTable<OFstream> probeFilePtrs_;
 
 
-    // Private Member Functions
+    // Protected Member Functions
 
         //- Clear old field groups
         void clearFieldGroups();
@@ -159,6 +195,8 @@ protected:
         //  returns number of fields to sample
         label prepare();
 
+        //- Read dictionary settings
+        void readDict(const dictionary& dict);
 
 private:
 
@@ -207,7 +245,8 @@ public:
             const word& name,
             const objectRegistry&,
             const dictionary&,
-            const bool loadFromFiles = false
+            const bool loadFromFiles = false,
+            const bool findElements = true
         );