diff --git a/src/surfMesh/keyedSurface/keyedSurface.C b/src/surfMesh/keyedSurface/keyedSurface.C
index 45a75e0a0f7dffae7297fb9e653d17722d92242d..b861cde471023e1b939406b754bced2bec5252d2 100644
--- a/src/surfMesh/keyedSurface/keyedSurface.C
+++ b/src/surfMesh/keyedSurface/keyedSurface.C
@@ -287,7 +287,7 @@ void Foam::keyedSurface::setPatches
 
 
 // Read surf grouping, points, faces directly from Istream
-bool Foam::keyedSurface::read(Istream& is)
+bool Foam::keyedSurface::read(Istream& is, const bool doTriangulate)
 {
     List<surfGroup> patchLst(is);
     is >> points() >> faces();
@@ -311,6 +311,11 @@ bool Foam::keyedSurface::read(Istream& is)
         }
     }
 
+    if (doTriangulate)
+    {
+        triangulate();
+    }
+
     return is.good();
 }
 
@@ -633,11 +638,11 @@ Foam::keyedSurface::keyedSurface
 }
 
 
-Foam::keyedSurface::keyedSurface(Istream& is)
+Foam::keyedSurface::keyedSurface(Istream& is, const bool triangulate)
 :
     MeshStorage(List<FaceType>(), pointField())
 {
-    read(is);
+    read(is, triangulate);
 }
 
 
@@ -924,7 +929,7 @@ bool Foam::keyedSurface::read
     // handle 'native' format directly
     if (ext == nativeExt)
     {
-        return read(IFstream(fName)());
+        return read(IFstream(fName)(), triangulate);
     }
     else
     {
diff --git a/src/surfMesh/keyedSurface/keyedSurface.H b/src/surfMesh/keyedSurface/keyedSurface.H
index 2d15435a1c2751811961d32f91f4d58e7c9fdc1e..023efa5e8d70a2204bea13f16e5e595c529dfc90 100644
--- a/src/surfMesh/keyedSurface/keyedSurface.H
+++ b/src/surfMesh/keyedSurface/keyedSurface.H
@@ -71,7 +71,7 @@ class keyedSurface;
 class meshedSurface;
 class polyBoundaryMesh;
 
-Istream& operator>>(Istream&, keyedSurface&);
+// Istream& operator>>(Istream&, keyedSurface&);
 Ostream& operator<<(Ostream&, const keyedSurface&);
 
 
@@ -123,7 +123,7 @@ private:
     // Private member functions
 
         //- Read OpenFOAM Surface format
-        bool read(Istream&);
+        bool read(Istream&, const bool triangulate=false);
 
         //- Disable setSize with value
         void setSize(const label, const FaceType&);
@@ -153,11 +153,6 @@ protected:
         //- Sets patch names from hashed values (name -> id)
         void setPatches(const HashTable<label>& groupToPatch);
 
-        //- Join the faces by removing duplicate points.
-        //  Returns true if any points merged
-        bool stitchFaces(const scalar tol=SMALL, const bool verbose=false);
-
-
         //- Return non-const access to global points
         pointField& points()
         {
@@ -266,8 +261,7 @@ public:
         );
 
         //- Construct from Istream
-        keyedSurface(Istream&);
-
+        keyedSurface(Istream&, const bool triangulate=false);
         //- Construct from objectRegistry
         keyedSurface(const Time&);
 
@@ -308,7 +302,7 @@ public:
 
     // Destructor
 
-        ~keyedSurface();
+        virtual ~keyedSurface();
 
 
     // Member Function Selectors
@@ -410,6 +404,14 @@ public:
         //- Scale points. A non-positive factor is ignored
         virtual void scalePoints(const scalar&);
 
+        //- Triangulate the surface, return the number of added faces.
+        label triangulate();
+
+        //- Join the faces by removing duplicate points.
+        //  Returns true if any points merged
+        bool stitchFaces(const scalar tol=SMALL, const bool verbose=false);
+
+        //- Check/fix duplicate/degenerate faces
         void checkFaces(const bool verbose);
 
         //- Remove invalid faces
@@ -468,6 +470,7 @@ public:
 
         // friend Istream& operator>>(Istream&, keyedSurface&);
         friend Ostream& operator<<(Ostream&, const keyedSurface&);
+
 };
 
 
diff --git a/src/surfMesh/keyedSurface/keyedSurfaceCleanup.C b/src/surfMesh/keyedSurface/keyedSurfaceCleanup.C
index 176e0b7fbaf2508290cb19eb0975a5ef8b3292e5..5390d3d1685b1e1930a4a1b038c7629188b015a0 100644
--- a/src/surfMesh/keyedSurface/keyedSurfaceCleanup.C
+++ b/src/surfMesh/keyedSurface/keyedSurfaceCleanup.C
@@ -230,4 +230,58 @@ void Foam::keyedSurface::checkFaces(const bool verbose)
     }
 }
 
+
+Foam::label Foam::keyedSurface::triangulate()
+{
+    label nTri = 0;
+    List<FaceType>& faceLst = faces();
+
+    // determine how many triangles are needed
+    forAll (faceLst, faceI)
+    {
+        nTri += faceLst[faceI].size() - 2;
+    }
+
+    // nothing to do
+    if (nTri <= faceLst.size())
+    {
+        return 0;
+    }
+
+    List<FaceType> newFaces(nTri);
+    List<label>    newRegions(nTri);
+
+    // note the number of *additional* faces
+    nTri -= faceLst.size();
+
+    // Reset the point labels to the unique points array
+    label newFaceI = 0;
+    forAll (faceLst, faceI)
+    {
+        const FaceType& f = faceLst[faceI];
+
+        FaceType fTri(3);
+
+        // Do simple face triangulation around f[0].
+        // we could also use face::triangulation
+        fTri[0] = f[0];
+        for (label fp = 1; fp < f.size() - 1; ++fp)
+        {
+            label fp1 = (fp + 1) % f.size();
+
+            fTri[1] = f[fp];
+            fTri[2] = f[fp1];
+
+            newFaces[newFaceI] = fTri;
+            newRegions[newFaceI] = regions_[faceI];
+            newFaceI++;
+        }
+    }
+
+    faceLst.transfer(newFaces);
+    regions_.transfer(newRegions);
+
+    return nTri;
+}
+
 // ************************************************************************* //
diff --git a/src/surfMesh/meshedSurface/meshedSurface.C b/src/surfMesh/meshedSurface/meshedSurface.C
index 3e81b834440a9bed16f15c8c5479ca7ce14bf35c..ecb37996c9a09b7c1f6af18c0c5523fc96dac933 100644
--- a/src/surfMesh/meshedSurface/meshedSurface.C
+++ b/src/surfMesh/meshedSurface/meshedSurface.C
@@ -275,7 +275,7 @@ void Foam::meshedSurface::sortFacesByRegion
 
 
 // Read surf grouping, points, faces directly from Istream
-bool Foam::meshedSurface::read(Istream& is)
+bool Foam::meshedSurface::read(Istream& is, const bool doTriangulate)
 {
     List<surfGroup> patchLst(is);
     is >> points() >> faces();
@@ -291,6 +291,11 @@ bool Foam::meshedSurface::read(Istream& is)
         );
     }
 
+    if (doTriangulate)
+    {
+        triangulate();
+    }
+
     return is.good();
 }
 
@@ -576,11 +581,11 @@ Foam::meshedSurface::meshedSurface
 }
 
 
-Foam::meshedSurface::meshedSurface(Istream& is)
+Foam::meshedSurface::meshedSurface(Istream& is, const bool triangulate)
 :
     MeshStorage(List<FaceType>(), pointField())
 {
-    read(is);
+    read(is, triangulate);
 }
 
 
@@ -840,7 +845,7 @@ bool Foam::meshedSurface::read
     // handle 'native' format directly
     if (ext == nativeExt)
     {
-        return read(IFstream(fName)());
+        return read(IFstream(fName)(), triangulate);
     }
     else
     {
diff --git a/src/surfMesh/meshedSurface/meshedSurface.H b/src/surfMesh/meshedSurface/meshedSurface.H
index bada9064dc1c80da61d018aa802c38ae14c7e4ef..6f184c6ea90923d1a737003d1ff0d8081b1f61d1 100644
--- a/src/surfMesh/meshedSurface/meshedSurface.H
+++ b/src/surfMesh/meshedSurface/meshedSurface.H
@@ -123,7 +123,7 @@ private:
         void checkPatches();
 
         //- Read OpenFOAM Surface format
-        bool read(Istream&);
+        bool read(Istream&, const bool triangulate=false);
 
 
 protected:
@@ -237,7 +237,7 @@ public:
         );
 
         //- Construct from Istream
-        meshedSurface(Istream&);
+        meshedSurface(Istream&, const bool triangulate=false);
 
         //- Construct from objectRegistry
         meshedSurface(const Time&);
@@ -265,7 +265,7 @@ public:
 
     // Destructor
 
-        ~meshedSurface();
+        virtual ~meshedSurface();
 
 
     // Member Function Selectors
diff --git a/src/surfMesh/meshedSurface/meshedSurfaceCleanup.C b/src/surfMesh/meshedSurface/meshedSurfaceCleanup.C
index 5e07716424ea324cc57044cf6c07c021ed6df55f..23e6af08c40654ff6001b48cc8147c7cfe369ab1 100644
--- a/src/surfMesh/meshedSurface/meshedSurfaceCleanup.C
+++ b/src/surfMesh/meshedSurface/meshedSurfaceCleanup.C
@@ -263,10 +263,9 @@ void Foam::meshedSurface::checkFaces(const bool verbose)
 Foam::label Foam::meshedSurface::triangulate()
 {
     label nTri = 0;
-
     List<FaceType>& faceLst = faces();
 
-    // estimate how may triangles are needed
+    // determine how many triangles are needed
     forAll (faceLst, faceI)
     {
         nTri += faceLst[faceI].size() - 2;