diff --git a/applications/utilities/surface/surfaceConvert/surfaceConvert.C b/applications/utilities/surface/surfaceConvert/surfaceConvert.C
index deb3dccca04dbe20311935fe7787e64c0a9d4449..90c57cf4f51de5026f21443474926f8af3bb6365 100644
--- a/applications/utilities/surface/surfaceConvert/surfaceConvert.C
+++ b/applications/utilities/surface/surfaceConvert/surfaceConvert.C
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
 {
     argList::addNote
     (
-        "convert between surface formats"
+        "convert between surface formats, using triSurface library components"
     );
 
     argList::noParallel();
@@ -96,16 +96,6 @@ int main(int argc, char *argv[])
 
     argList args(argc, argv);
 
-    if (args.optionFound("writePrecision"))
-    {
-        label writePrecision = args.optionRead<label>("writePrecision");
-
-        IOstream::defaultPrecision(writePrecision);
-        Sout.precision(writePrecision);
-
-        Info<< "Output write precision set to " << writePrecision << endl;
-    }
-
     const fileName importName = args[1];
     const fileName exportName = args[2];
 
@@ -116,6 +106,26 @@ int main(int argc, char *argv[])
             << exit(FatalError);
     }
 
+    // Check that reading/writing is supported
+    if
+    (
+        !triSurface::canRead(importName, true)
+     || !triSurface::canWriteType(exportName.ext(), true)
+    )
+    {
+        return 1;
+    }
+
+    if (args.optionFound("writePrecision"))
+    {
+        label writePrecision = args.optionRead<label>("writePrecision");
+
+        IOstream::defaultPrecision(writePrecision);
+        Sout.precision(writePrecision);
+
+        Info<< "Output write precision set to " << writePrecision << endl;
+    }
+
     const scalar scaleFactor = args.optionLookupOrDefault<scalar>("scale", -1);
 
     Info<< "Reading : " << importName << endl;
diff --git a/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C b/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
index 4146776126543b16d34912353427f213057687bf..02f902ead2dc5c18e7daa84d271857dcc77ecdbe 100644
--- a/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
+++ b/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
@@ -75,7 +75,7 @@ int main(int argc, char *argv[])
 {
     argList::addNote
     (
-        "convert between surface formats"
+        "convert between surface formats, using MeshSurface library components"
     );
 
     argList::noParallel();
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
             << exit(FatalError);
     }
 
-    // check that reading/writing is supported
+    // Check that reading/writing is supported
     if
     (
         !MeshedSurface<face>::canRead(importName, true)
diff --git a/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatch/PrimitivePatch.H b/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatch/PrimitivePatch.H
index 6e732b9fd824f72b34273fc0100e983f214e3dc5..6a0d07fc9a5fb52cf31a370795f3e3baa75381ad 100644
--- a/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatch/PrimitivePatch.H
+++ b/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatch/PrimitivePatch.H
@@ -288,6 +288,10 @@ public:
 
     // Member Functions
 
+        //- Suppress direct swapping, since storage containers may be const
+        void swap(PrimitivePatch&) = delete;
+
+
     // Access
 
         //- Return reference to global points
@@ -320,9 +324,9 @@ public:
             label nInternalEdges() const;
 
             //- Is internal edge?
-            bool isInternalEdge(const label edgeI) const
+            bool isInternalEdge(const label edgei) const
             {
-                return edgeI < nInternalEdges();
+                return edgei < nInternalEdges();
             }
 
             //- Return list of boundary points,
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
index 609aff6e9bf8afbbe8b22f773b7cb2bb86c46a0d..debfd67c6c4a7e9d69de570212fbe618f4e79d33 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
@@ -365,13 +365,18 @@ namespace stringOps
         const std::string& delim
     );
 
-    //- Split string into sub-strings using a fixed field width
+    //- Split string into sub-strings using a fixed field width.
     //  Behaviour is ill-defined if width is zero.
+    //  \param str the string to be split
+    //  \param width the fixed field width for each sub-string
+    //  \param start the optional offset of where to start the splitting.
+    //      Any text prior to start is ignored in the operation.
     template<class StringType>
     Foam::SubStrings<StringType> splitFixed
     (
         const StringType& str,
-        const std::string::size_type width
+        const std::string::size_type width,
+        const std::string::size_type start = 0
     );
 
     //- Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C b/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
index 53c72fa2b5b44c7517b1f80d52dafa341946a745..86f9409d0fe3b67fac513b4fa54ab3b57dc5a039 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
@@ -183,7 +183,8 @@ template<class StringType>
 Foam::SubStrings<StringType> Foam::stringOps::splitFixed
 (
     const StringType& str,
-    const std::string::size_type width
+    const std::string::size_type width,
+    const std::string::size_type start
 )
 {
     Foam::SubStrings<StringType> lst;
@@ -195,7 +196,7 @@ Foam::SubStrings<StringType> Foam::stringOps::splitFixed
     const auto len = str.size();
     lst.reserve(1 + (len / width));
 
-    for (std::string::size_type pos = 0; pos < len; pos += width)
+    for (std::string::size_type pos = start; pos < len; pos += width)
     {
         const auto end = (pos + width);
 
diff --git a/src/fileFormats/fire/FIRECore.C b/src/fileFormats/fire/FIRECore.C
index 10b15fe7c8288c0151a9b8f965e47f5911315921..02ebc4c3ff03a893da11e190b73f7de2e5267745 100644
--- a/src/fileFormats/fire/FIRECore.C
+++ b/src/fileFormats/fire/FIRECore.C
@@ -40,12 +40,6 @@ Foam::fileFormats::FIRECore::file3dExtensions
 };
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::fileFormats::FIRECore::FIRECore()
-{}
-
-
 // * * * * * * * * * * *  Protected Member Functions * * * * * * * * * * * * //
 
 Foam::label Foam::fileFormats::FIRECore::readPoints
diff --git a/src/fileFormats/fire/FIRECore.H b/src/fileFormats/fire/FIRECore.H
index 96eb73ee5f31669d2b34a0889a52e6e7878dd460..e2c93d405f27a9083a54c57c0cd7c4d8364f4116 100644
--- a/src/fileFormats/fire/FIRECore.H
+++ b/src/fileFormats/fire/FIRECore.H
@@ -108,7 +108,7 @@ protected:
     // Protected Member Functions
 
         //- Construct null
-        FIRECore();
+        FIRECore() = default;
 
 
         //- Read points.
diff --git a/src/fileFormats/nas/NASCore.C b/src/fileFormats/nas/NASCore.C
index 45fe1f30cce6f8ebde6e6336787a9f718dcd167b..59fc99cb51eb3fa4d2b2ff7c95b3663ab1be0a6f 100644
--- a/src/fileFormats/nas/NASCore.C
+++ b/src/fileFormats/nas/NASCore.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -24,11 +24,27 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "NASCore.H"
+#include "IOmanip.H"
+#include "Ostream.H"
 #include "parsing.H"
 
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+const Foam::Enum
+<
+    Foam::fileFormats::NASCore::fieldFormat
+>
+Foam::fileFormats::NASCore::fieldFormatNames
+{
+    { fieldFormat::SHORT, "short" },
+    { fieldFormat::LONG,  "long" },
+    { fieldFormat::FREE,  "free" },
+};
+
+
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
-Foam::scalar Foam::fileFormats::NASCore::readNasScalar(const string& str)
+Foam::scalar Foam::fileFormats::NASCore::readNasScalar(const std::string& str)
 {
     const auto signPos = str.find_last_of("+-");
 
@@ -54,7 +70,7 @@ Foam::scalar Foam::fileFormats::NASCore::readNasScalar(const string& str)
     if
     (
         readScalar(str.substr(0, signPos), value)   // Mantissa
-     && readInt(str.substr(signPos),  exponent)     // Exponent (with sign)
+     && readInt(str.substr(signPos), exponent)      // Exponent (with sign)
     )
     {
         // Note: this does not catch underflow/overflow
@@ -74,10 +90,98 @@ Foam::scalar Foam::fileFormats::NASCore::readNasScalar(const string& str)
 }
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+std::string Foam::fileFormats::NASCore::nextNasField
+(
+    const std::string& str,
+    std::string::size_type& pos,
+    std::string::size_type len
+)
+{
+    const auto beg = pos;
+    const auto end = str.find(',', pos);
+
+    if (end == std::string::npos)
+    {
+        pos = beg + len;    // Continue after field width
+    }
+    else
+    {
+        len = (end - beg);  // Efffective width
+        pos = end + 1;      // Continue after comma
+    }
+
+    return str.substr(beg, len);
+}
+
+
+void Foam::fileFormats::NASCore::setPrecision
+(
+    Ostream& os,
+    const fieldFormat format
+)
+{
+    os.setf(ios_base::scientific);
 
-Foam::fileFormats::NASCore::NASCore()
-{}
+    // Capitalise the E marker
+    os.setf(ios_base::uppercase);
+
+    const label offset = 7;
+
+    label prec = 16 - offset;
+    switch (format)
+    {
+        case fieldFormat::SHORT :
+        {
+            prec = 8 - offset;
+            break;
+        }
+
+        case fieldFormat::LONG :
+        case fieldFormat::FREE :
+        {
+            prec = 16 - offset;
+            break;
+        }
+    }
+
+    os.precision(prec);
+}
+
+
+Foam::Ostream& Foam::fileFormats::NASCore::writeKeyword
+(
+    Ostream& os,
+    const word& keyword,
+    const fieldFormat format
+)
+{
+    os.setf(ios_base::left);
+
+    switch (format)
+    {
+        case fieldFormat::SHORT :
+        {
+            os  << setw(8) << keyword;
+            break;
+        }
+
+        case fieldFormat::LONG :
+        {
+            os  << setw(8) << word(keyword + '*');
+            break;
+        }
+
+        case fieldFormat::FREE :
+        {
+            os  << keyword;
+            break;
+        }
+    }
+
+    os.unsetf(ios_base::left);
+
+    return os;
+}
 
 
 // ************************************************************************* //
diff --git a/src/fileFormats/nas/NASCore.H b/src/fileFormats/nas/NASCore.H
index 41c6f466cc09c59933269faf9de63bc3d02e604d..b57f912335067bb582f782d9cfd1db051b7a32d8 100644
--- a/src/fileFormats/nas/NASCore.H
+++ b/src/fileFormats/nas/NASCore.H
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -37,11 +37,16 @@ SourceFiles
 
 #include "scalar.H"
 #include "string.H"
+#include "Enum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
+
+// Forward declarations
+class Ostream;
+
 namespace fileFormats
 {
 
@@ -53,23 +58,64 @@ class NASCore
 {
 public:
 
-    // Public Member Functions
+        //- File field formats
+        enum fieldFormat
+        {
+            SHORT,      //<! Short format (field width = 8)
+            LONG,       //<! Long format (field width = 16)
+            FREE        //<! Free format (comma-separated fields)
+        };
+
+        //- Selection names for the NASTRAN file field formats
+        static const Enum<fieldFormat> fieldFormatNames;
+
+
+    // Constructors
+
+        //- Construct null
+        NASCore() = default;
+
+
+    // Public Static Member Functions
 
         //- Extract numbers from things like "-2.358-8" (same as "-2.358e-8")
-        static scalar readNasScalar(const string& str);
+        static scalar readNasScalar(const std::string& str);
 
         //- Extract numbers from things like "-2.358-8" (same as "-2.358e-8")
         // \deprecated use readNasScalar instead (deprecated Sep 2017)
-        inline static scalar parseNASCoord(const string& str)
+        inline static scalar parseNASCoord(const std::string& str)
         {
             return readNasScalar(str);
         }
 
+        //- A string::substr() to handle fixed-format and free-format NASTRAN.
+        //  Returns the substr to the next comma (if found) or the given length
+        //
+        //  \param str The string to extract from
+        //  \param pos On input, the position of the first character of the
+        //      substring. On output, advances to the next position to use.
+        //  \param len The fixed-format length to use if a comma is not found.
+        static std::string nextNasField
+        (
+            const std::string& str,
+            std::string::size_type& pos,
+            std::string::size_type len
+        );
+
+
+        //- Set output stream precision and format flags
+        static void setPrecision(Ostream& os, const fieldFormat format);
+
+
+        //- Write initial keyword (eg, 'GRID' or 'GRID*') followed by the
+        //- requisite number of spaces for the field-width
+        static Ostream& writeKeyword
+        (
+            Ostream& os,
+            const word& keyword,
+            const fieldFormat format
+        );
 
-    // Constructors
-
-        //- Construct null
-        NASCore();
 };
 
 
diff --git a/src/fileFormats/starcd/STARCDCore.C b/src/fileFormats/starcd/STARCDCore.C
index e9302bda2372706a7d5d0899ddddbb63346bb733..109b994f92d1db34e6cf165fa2e77c3e7ec3b6ce 100644
--- a/src/fileFormats/starcd/STARCDCore.C
+++ b/src/fileFormats/starcd/STARCDCore.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,6 +27,7 @@ License
 #include "ListOps.H"
 #include "clock.H"
 #include "PackedBoolList.H"
+#include "DynamicList.H"
 #include "StringStream.H"
 #include "OSspecific.H"
 
@@ -85,12 +86,6 @@ Foam::fileFormats::STARCDCore::starToFoamFaceAddr =
 };
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::fileFormats::STARCDCore::STARCDCore()
-{}
-
-
 // * * * * * * * * * * *  Protected Member Functions * * * * * * * * * * * * //
 
 bool Foam::fileFormats::STARCDCore::readHeader
@@ -173,8 +168,8 @@ void Foam::fileFormats::STARCDCore::removeFiles(const fileName& base)
 Foam::label Foam::fileFormats::STARCDCore::readPoints
 (
     IFstream& is,
-    pointField& points,
-    labelList& ids
+    List<point>& points,
+    List<label>& ids
 )
 {
     label maxId = 0;
@@ -219,7 +214,7 @@ Foam::label Foam::fileFormats::STARCDCore::readPoints
 void Foam::fileFormats::STARCDCore::writePoints
 (
     Ostream& os,
-    const pointField& points,
+    const UList<point>& points,
     const scalar scaleFactor
 )
 {
diff --git a/src/fileFormats/starcd/STARCDCore.H b/src/fileFormats/starcd/STARCDCore.H
index 1825a28dfe0d37f0c9bbc8da0bc231efdabfdeb8..c7eb8073a24e58c7003686a61203296cabc27495 100644
--- a/src/fileFormats/starcd/STARCDCore.H
+++ b/src/fileFormats/starcd/STARCDCore.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -37,9 +37,10 @@ SourceFiles
 
 #include "IFstream.H"
 #include "Enum.H"
-#include "pointField.H"
 #include "Map.H"
+#include "point.H"
 #include "FixedList.H"
+#include "List.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -133,13 +134,13 @@ protected:
     // Constructors
 
         //- Construct null
-        STARCDCore();
+        STARCDCore() = default;
 
         //- Read header and check signature PROSTAR_(CELL|VERTEX|BOUNDARY)
-        static bool readHeader(IFstream&, const enum fileHeader);
+        static bool readHeader(IFstream& is, const enum fileHeader header);
 
         //- Write header for fileType (CELL|VERTEX|BOUNDARY)
-        static void writeHeader(Ostream&, const enum fileHeader);
+        static void writeHeader(Ostream& os, const enum fileHeader header);
 
 
 public:
@@ -150,7 +151,7 @@ public:
         static fileName starFileName
         (
             const fileName& baseName,
-            const enum fileExt
+            const enum fileExt ext
         );
 
 
@@ -173,16 +174,16 @@ public:
         // \endverbatim
         static label readPoints
         (
-            IFstream&,
-            pointField&,
-            labelList& ids
+            IFstream& is,
+            List<point>& points,
+            List<label>& ids
         );
 
         //- Write header and points to (.vrt) file, optionally with scaling
         static void writePoints
         (
-            Ostream&,
-            const pointField&,
+            Ostream& os,
+            const UList<point>& points,
             const scalar scaleFactor = 1.0
         );
 
diff --git a/src/fileFormats/stl/STLCore.C b/src/fileFormats/stl/STLCore.C
index 9761fa69a9b24847923660d74b1890639a3f9576..894ac37f80df9332a517f93d80dde3226867fbae 100644
--- a/src/fileFormats/stl/STLCore.C
+++ b/src/fileFormats/stl/STLCore.C
@@ -59,21 +59,20 @@ static bool startsWithSolid(const char header[STLHeaderSize])
 //! \endcond
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::fileFormats::STLCore::STLCore()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::fileFormats::STLCore::isBinaryName
 (
     const fileName& filename,
-    const STLFormat& format
+    const STLFormat format
 )
 {
-    return (format == UNKNOWN ? (filename.ext() == "stlb") : format == BINARY);
+    return
+    (
+        format == STLFormat::UNKNOWN
+      ? (filename.ext() == "stlb")
+      : format == STLFormat::BINARY
+    );
 }
 
 
diff --git a/src/fileFormats/stl/STLCore.H b/src/fileFormats/stl/STLCore.H
index 6e8928d3c1c5908bd5cf5a2cd4a8294fd542dd14..26dba4a4c845ad8de8138d9a8d10df43baa88fd2 100644
--- a/src/fileFormats/stl/STLCore.H
+++ b/src/fileFormats/stl/STLCore.H
@@ -69,11 +69,12 @@ protected:
 
     // Protected Member Functions
 
-        //- Detect 'stlb' extension as binary
+        //- Detect 'stlb' extension as binary when format = UNKNOWN.
+        //  Otherwise test if format == BINARY.
         static bool isBinaryName
         (
             const fileName& filename,
-            const STLFormat& format
+            const STLFormat format
         );
 
 
@@ -98,7 +99,7 @@ protected:
     // Constructors
 
         //- Construct null
-        STLCore();
+        STLCore() = default;
 
 };
 
diff --git a/src/fileFormats/stl/STLReader.C b/src/fileFormats/stl/STLReader.C
index ca7451d886a2ad7726a6b1f8d1a290a371414eaa..070729ae88cde32900ca892b7a910088e835d5d0 100644
--- a/src/fileFormats/stl/STLReader.C
+++ b/src/fileFormats/stl/STLReader.C
@@ -38,7 +38,7 @@ bool Foam::fileFormats::STLReader::readBINARY
 )
 {
     sorted_ = true;
-    format_ = UNKNOWN;
+    format_ = STLFormat::UNKNOWN;
 
     label nTris = 0;
     autoPtr<istream> streamPtr = readBinaryHeader(filename, nTris);
@@ -125,7 +125,7 @@ bool Foam::fileFormats::STLReader::readBINARY
     names_.clear();
     sizes_.transfer(dynSizes);
 
-    format_ = BINARY;
+    format_ = STLFormat::BINARY;
     return true;
 }
 
@@ -133,10 +133,15 @@ bool Foam::fileFormats::STLReader::readBINARY
 bool Foam::fileFormats::STLReader::readFile
 (
     const fileName& filename,
-    const STLFormat& format
+    const STLFormat format
 )
 {
-    if (format == UNKNOWN ? detectBinaryHeader(filename) : format == BINARY)
+    if
+    (
+        format == STLFormat::UNKNOWN
+      ? detectBinaryHeader(filename)
+      : format == STLFormat::BINARY
+    )
     {
         return readBINARY(filename);
     }
@@ -159,17 +164,17 @@ Foam::fileFormats::STLReader::STLReader
     zoneIds_(),
     names_(),
     sizes_(),
-    format_(STLCore::UNKNOWN)
+    format_(STLFormat::UNKNOWN)
 {
     // Auto-detect ASCII/BINARY format
-    readFile(filename, STLCore::UNKNOWN);
+    readFile(filename, STLFormat::UNKNOWN);
 }
 
 
 Foam::fileFormats::STLReader::STLReader
 (
     const fileName& filename,
-    const STLFormat& format
+    const STLFormat format
 )
 :
     sorted_(true),
@@ -177,7 +182,7 @@ Foam::fileFormats::STLReader::STLReader
     zoneIds_(),
     names_(),
     sizes_(),
-    format_(STLCore::UNKNOWN)
+    format_(STLFormat::UNKNOWN)
 {
     // Manually specified ASCII/BINARY format
     readFile(filename, format);
@@ -199,7 +204,7 @@ void Foam::fileFormats::STLReader::clear()
     zoneIds_.clear();
     names_.clear();
     sizes_.clear();
-    format_ = UNKNOWN;
+    format_ = STLFormat::UNKNOWN;
 }
 
 
@@ -215,7 +220,7 @@ Foam::label Foam::fileFormats::STLReader::mergePointsMap
 
     return mergePointsMap
     (
-        (format_ == BINARY ? 10 : 100) * doubleScalarSMALL,
+        (format_ == STLFormat::BINARY ? 10 : 100) * doubleScalarSMALL,
         pointMap
     );
 }
diff --git a/src/fileFormats/stl/STLReader.H b/src/fileFormats/stl/STLReader.H
index e9873aafe74bad823e3c4db840698f82efdfaf7a..663c404da27ecce9cb52bd5335efb578733b2626 100644
--- a/src/fileFormats/stl/STLReader.H
+++ b/src/fileFormats/stl/STLReader.H
@@ -85,7 +85,7 @@ class STLReader
         bool readBINARY(const fileName& filename);
 
         //- Read ASCII or BINARY
-        bool readFile(const fileName& filename, const STLFormat& format);
+        bool readFile(const fileName& filename, const STLFormat format);
 
 
         //- Disallow default bitwise copy construct
@@ -105,7 +105,7 @@ public:
 
         //- Read from file, filling in the information.
         //  Manually selected choice of ASCII/BINARY/UNKNOWN(detect) formats.
-        STLReader(const fileName& filename, const STLFormat& format);
+        STLReader(const fileName& filename, const STLFormat format);
 
 
     //- Destructor
diff --git a/src/fileFormats/stl/STLReaderASCII.L b/src/fileFormats/stl/STLReaderASCII.L
index 5a781d4a56b6979cde2fad4d72683d8371c4f1b4..d742ae34df581ae0363a333955d1c93609445034 100644
--- a/src/fileFormats/stl/STLReaderASCII.L
+++ b/src/fileFormats/stl/STLReaderASCII.L
@@ -411,7 +411,7 @@ bool Foam::fileFormats::STLReader::readASCII
     const fileName& filename
 )
 {
-    format_ = UNKNOWN;
+    format_ = STLFormat::UNKNOWN;
 
     IFstream is(filename);
     if (!is)
@@ -434,7 +434,7 @@ bool Foam::fileFormats::STLReader::readASCII
     names_.transfer(lexer.names());
     sizes_.transfer(lexer.sizes());
 
-    format_ = ASCII;
+    format_ = STLFormat::ASCII;
     return true;
 }
 
diff --git a/src/lumpedPointMotion/lumpedPointState.C b/src/lumpedPointMotion/lumpedPointState.C
index e15e3371c1c91218be8f284f780152221d6d20dd..a84e963fb66ae959cdd619595ee2b011fe2b19be 100644
--- a/src/lumpedPointMotion/lumpedPointState.C
+++ b/src/lumpedPointMotion/lumpedPointState.C
@@ -44,17 +44,21 @@ Foam::lumpedPointState::formatNames
 };
 
 
-// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
 
 //! \cond fileScope
-static Foam::string getLineNoComment(Foam::ISstream& is)
+static Foam::string getLineNoComment
+(
+    Foam::ISstream& is,
+    const char comment = '#'
+)
 {
     Foam::string line;
     do
     {
         is.getLine(line);
     }
-    while ((line.empty() || line[0] == '#') && is.good());
+    while ((line.empty() || line[0] == comment) && is.good());
 
     return line;
 }
diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.C b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.C
index 71d25e518b20a03dd55196f1fb82d6ac750d0484..f05dfc330ced70f303602faa3beb936fabbe8732 100644
--- a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.C
+++ b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.C
@@ -38,15 +38,16 @@ Foam::word Foam::fileFormats::edgeMeshFormatsCore::nativeExt("eMesh");
 
 Foam::string Foam::fileFormats::edgeMeshFormatsCore::getLineNoComment
 (
-    IFstream& is
+    ISstream& is,
+    const char comment
 )
 {
-    string line;
+    Foam::string line;
     do
     {
         is.getLine(line);
     }
-    while ((line.empty() || line[0] == '#') && is.good());
+    while ((line.empty() || line[0] == comment) && is.good());
 
     return line;
 }
@@ -183,16 +184,4 @@ bool Foam::fileFormats::edgeMeshFormatsCore::checkSupport
 }
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::fileFormats::edgeMeshFormatsCore::edgeMeshFormatsCore()
-{}
-
-
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::fileFormats::edgeMeshFormatsCore::~edgeMeshFormatsCore()
-{}
-
-
 // ************************************************************************* //
diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.H b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.H
index fa68510084f56a017d0f7a860b482521e4ef1f82..2a3b5d13660e0bf2ef691e82fdaaa8c9585b5e5b 100644
--- a/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.H
+++ b/src/meshTools/edgeMesh/edgeMeshFormats/edgeMeshFormatsCore.H
@@ -46,7 +46,7 @@ namespace Foam
 
 // Forward declaration of classes
 
-class IFstream;
+class ISstream;
 class Time;
 
 namespace fileFormats
@@ -63,7 +63,7 @@ protected:
     // Protected Member Functions
 
         //- Read non-comment line
-        static string getLineNoComment(IFstream&);
+        static string getLineNoComment(ISstream& is, const char comment='#');
 
 public:
 
@@ -103,11 +103,11 @@ public:
     // Constructors
 
         //- Construct null
-        edgeMeshFormatsCore();
+        edgeMeshFormatsCore() = default;
 
 
     //- Destructor
-    virtual ~edgeMeshFormatsCore();
+    virtual ~edgeMeshFormatsCore() = default;
 
 };
 
diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.C b/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.C
index 761ec70b31750e4e9749d624eef9ce9ea6a1b164..afdc62b0551964e860882371ec88f3624aefa4a9 100644
--- a/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.C
+++ b/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.C
@@ -30,10 +30,7 @@ License
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::fileFormats::NASedgeFormat::NASedgeFormat
-(
-    const fileName& filename
-)
+Foam::fileFormats::NASedgeFormat::NASedgeFormat(const fileName& filename)
 {
     read(filename);
 }
@@ -62,13 +59,13 @@ bool Foam::fileFormats::NASedgeFormat::read
 
     while (is.good())
     {
+        string::size_type linei = 0;  // parsing position within current line
         string line;
         is.getLine(line);
 
-        // Skip empty or comment
         if (line.empty() || line[0] == '$')
         {
-            continue;
+            continue; // Skip empty or comment
         }
 
         // Check if character 72 is continuation
@@ -94,39 +91,38 @@ bool Foam::fileFormats::NASedgeFormat::read
         }
 
 
-        // Read first word
-        IStringStream lineStream(line);
-        word cmd;
-        lineStream >> cmd;
+        // First word (column 0-8)
+        const word cmd(word::validate(nextNasField(line, linei, 8)));
 
         if (cmd == "CBEAM" || cmd == "CROD")
         {
-            edge e;
+            // discard elementId (8-16)
+            (void) nextNasField(line, linei, 8); // 8-16
+            // discard groupId (16-24)
+            (void) nextNasField(line, linei, 8); // 16-24
 
-            // label groupId = readLabel(line.substr(16,8));
-            e[0] = readLabel(line.substr(24,8));
-            e[1] = readLabel(line.substr(32,8));
+            label a = readLabel(nextNasField(line, linei, 8)); // 24-32
+            label b = readLabel(nextNasField(line, linei, 8)); // 32-40
 
-            // discard groupID
-            dynEdges.append(e);
+            dynEdges.append(edge(a,b));
         }
         else if (cmd == "PLOTEL")
         {
-            edge e;
+            // discard elementId (8-16)
+            (void) nextNasField(line, linei, 8); // 8-16
 
-            // label groupId = readLabel(line.substr(16,8));
-            e[0] = readLabel(line.substr(16,8));
-            e[1] = readLabel(line.substr(24,8));
+            label a = readLabel(nextNasField(line, linei, 8)); // 16-24
+            label b = readLabel(nextNasField(line, linei, 8)); // 24-32
 
-            // discard groupID
-            dynEdges.append(e);
+            dynEdges.append(edge(a,b));
         }
         else if (cmd == "GRID")
         {
-            label index = readLabel(line.substr(8,8));
-            scalar x = readNasScalar(line.substr(24, 8));
-            scalar y = readNasScalar(line.substr(32, 8));
-            scalar z = readNasScalar(line.substr(40, 8));
+            label index = readLabel(nextNasField(line, linei, 8)); // 8-16
+            (void) nextNasField(line, linei, 8); // 16-24
+            scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
+            scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
+            scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
 
             pointId.append(index);
             dynPoints.append(point(x, y, z));
@@ -139,10 +135,12 @@ bool Foam::fileFormats::NASedgeFormat::read
             // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
             // *         2.14897901E+02
 
-            label index = readLabel(line.substr(8,16));
-            scalar x = readNasScalar(line.substr(40, 16));
-            scalar y = readNasScalar(line.substr(56, 16));
+            label index = readLabel(nextNasField(line, linei, 16)); // 8-24
+            (void) nextNasField(line, linei, 16); // 24-40
+            scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
+            scalar y = readNasScalar(nextNasField(line, linei, 16)); // 56-72
 
+            linei = 0; // restart at index 0
             is.getLine(line);
             if (line[0] != '*')
             {
@@ -153,7 +151,8 @@ bool Foam::fileFormats::NASedgeFormat::read
                     << "File:" << is.name() << " line:" << is.lineNumber()
                     << exit(FatalError);
             }
-            scalar z = readNasScalar(line.substr(8, 16));
+            (void) nextNasField(line, linei, 8); // 0-8
+            scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
 
             pointId.append(index);
             dynPoints.append(point(x, y, z));
@@ -179,9 +178,8 @@ bool Foam::fileFormats::NASedgeFormat::read
 
     // Pass1: relabel edges
     // ~~~~~~~~~~~~~~~~~~~~
-    forAll(dynEdges, i)
+    for (edge& e : dynEdges)
     {
-        edge& e = dynEdges[i];
         e[0] = mapPointId[e[0]];
         e[1] = mapPointId[e[1]];
 
@@ -191,7 +189,7 @@ bool Foam::fileFormats::NASedgeFormat::read
     pointId.clearStorage();
     mapPointId.clear();
 
-    // not all the points were used, cull them accordingly
+    // Not all the points were used, cull them accordingly
     if (unsigned(points().size()) != usedPoints.count())
     {
         label nUsed = 0;
@@ -215,11 +213,9 @@ bool Foam::fileFormats::NASedgeFormat::read
 
         pts.setSize(nUsed);
 
-        // renumber edge vertices
-        forAll(dynEdges, edgeI)
+        // Renumber edge vertices
+        for (edge& e : dynEdges)
         {
-            edge& e = dynEdges[edgeI];
-
             e[0] = mapPointId[e[0]];
             e[1] = mapPointId[e[1]];
         }
diff --git a/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.H b/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.H
index 03f403f8abf0122091a82af9bdebd93bebd85b28..c82d470acfedfac3489d2b5d1049e46b16165445 100644
--- a/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.H
+++ b/src/meshTools/edgeMesh/edgeMeshFormats/nas/NASedgeFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,6 +27,13 @@ Class
 Description
     Nastran edge reader.
 
+    - Interprets "CBEAM", "CROD" and "PLOTEL" entries as edges.
+    - Handles Nastran short, long formats and comma-separated free format.
+    - Properly handles the Nastran compact floating point notation: \n
+    \verbatim
+        GRID          28        10.20269-.030265-2.358-8
+    \endverbatim
+
 SourceFiles
     NASedgeFormat.C
 
@@ -57,17 +64,17 @@ class NASedgeFormat
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        NASedgeFormat(const NASedgeFormat&);
+        NASedgeFormat(const NASedgeFormat&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const NASedgeFormat&);
+        void operator=(const NASedgeFormat&) = delete;
 
 public:
 
     // Constructors
 
         //- Construct from file name
-        NASedgeFormat(const fileName&);
+        NASedgeFormat(const fileName& filename);
 
 
     // Selectors
@@ -83,14 +90,14 @@ public:
 
 
     //- Destructor
-    virtual ~NASedgeFormat()
-    {}
+    virtual ~NASedgeFormat() = default;
 
 
     // Member Functions
 
         //- Read from a file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
+
 };
 
 
diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C
index 3ecb1836b615653759672f2ee0c2a9e3d0e680cb..ce020e1dd39e37c540bd6026146f876871e09c3a 100644
--- a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C
+++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C
@@ -40,164 +40,84 @@ namespace Foam
     defineSurfaceWriterWriteFields(nastranSurfaceWriter);
 }
 
-
 const Foam::Enum
 <
-    Foam::nastranSurfaceWriter::writeFormat
+    Foam::nastranSurfaceWriter::loadFormat
 >
-Foam::nastranSurfaceWriter::writeFormatNames_
+Foam::nastranSurfaceWriter::loadFormatNames_
 {
-    { writeFormat::wfShort, "short" },
-    { writeFormat::wfLong, "long" },
-    { writeFormat::wfFree, "free" },
-};
-
-
-const Foam::Enum
-<
-    Foam::nastranSurfaceWriter::dataFormat
->
-Foam::nastranSurfaceWriter::dataFormatNames_
-{
-    { dataFormat::dfPLOAD2, "PLOAD2" },
-    { dataFormat::dfPLOAD4, "PLOAD4" },
+    { loadFormat::PLOAD2, "PLOAD2" },
+    { loadFormat::PLOAD4, "PLOAD4" },
 };
 
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-void Foam::nastranSurfaceWriter::formatOS(Ostream& os) const
-{
-    os.setf(ios_base::scientific);
-
-    // Capitalise the E marker
-    os.setf(ios_base::uppercase);
-
-    label prec = 0;
-    label offset = 7;
-    switch (writeFormat_)
-    {
-        case wfShort:
-        {
-            prec = 8 - offset;
-            break;
-        }
-
-        case wfFree:
-        case wfLong:
-        {
-            prec = 16 - offset;
-            break;
-        }
-
-        default:
-        {
-            FatalErrorInFunction
-                << "Unknown writeFormat enumeration" << abort(FatalError);
-        }
-    }
-
-    os.precision(prec);
-}
-
-
 Foam::Ostream& Foam::nastranSurfaceWriter::writeKeyword
 (
     Ostream& os,
     const word& keyword
 ) const
 {
-    os.setf(ios_base::left);
-
-    switch (writeFormat_)
-    {
-        case wfShort:
-        {
-            os  << setw(8) << keyword;
-            break;
-        }
-
-        case wfLong:
-        {
-            os  << setw(8) << word(keyword + '*');
-            break;
-        }
-
-        case wfFree:
-        {
-            os  << keyword;
-            break;
-        }
-    }
-
-    os.unsetf(ios_base::left);
-
-    return os;
+    return fileFormats::NASCore::writeKeyword(os, keyword, writeFormat_);
 }
 
 
 void Foam::nastranSurfaceWriter::writeCoord
 (
     Ostream& os,
-    const point& p,
+    const point& pt,
     const label pointI
 ) const
 {
     // Fixed short/long formats:
     // 1 GRID
     // 2 ID   : point ID - requires starting index of 1
-    // 3 CP   : co-ordinate system ID                (blank)
-    // 4 X1   : point x cp-ordinate
-    // 5 X2   : point x cp-ordinate
-    // 6 X3   : point x cp-ordinate
-    // 7 CD   : co-ordinate system for displacements (blank)
-    // 8 PS   : single point constraints             (blank)
+    // 3 CP   : coordinate system ID                (blank)
+    // 4 X1   : point x coordinate
+    // 5 X2   : point x coordinate
+    // 6 X3   : point x coordinate
+    // 7 CD   : coordinate system for displacements (blank)
+    // 8 PS   : single point constraints            (blank)
     // 9 SEID : super-element ID
 
     writeKeyword(os, "GRID")    << separator_;
 
-    os.setf(ios_base::right);
+    os.setf(std::ios_base::right);
 
     writeValue(os, pointI+1)    << separator_;
     writeValue(os, "")          << separator_;
-    writeValue(os, p.x())       << separator_;
-    writeValue(os, p.y())       << separator_;
+    writeValue(os, pt.x())      << separator_;
+    writeValue(os, pt.y())      << separator_;
 
     switch (writeFormat_)
     {
-        case wfShort:
+        case fieldFormat::SHORT :
         {
-            os  << setw(8) << p.z()
-                << nl;
-            os.unsetf(ios_base::right);
+            os  << setw(8) << pt.z() << nl;
+            os.unsetf(std::ios_base::right);
             break;
         }
 
-        case wfLong:
+        case fieldFormat::LONG :
         {
             os  << nl;
-            os.unsetf(ios_base::right);
+            os.unsetf(std::ios_base::right);
             writeKeyword(os, "");
-            os.setf(ios_base::right);
+            os.setf(std::ios_base::right);
 
-            writeValue(os, p.z())  << nl;
+            writeValue(os, pt.z())  << nl;
             break;
         }
 
-        case wfFree:
+        case fieldFormat::FREE :
         {
-            writeValue(os, p.z())  << nl;
+            writeValue(os, pt.z())  << nl;
             break;
         }
-
-        default:
-        {
-            FatalErrorInFunction
-                << "Unknown writeFormat enumeration" << abort(FatalError);
-        }
     }
 
-    os.unsetf(ios_base::right);
+    os.unsetf(std::ios_base::right);
 }
 
 
@@ -226,23 +146,24 @@ void Foam::nastranSurfaceWriter::writeFace
 
     writeKeyword(os, faceType)   << separator_;
 
-    os.setf(ios_base::right);
+    os.setf(std::ios_base::right);
 
     writeValue(os, nFace)        << separator_;
     writeValue(os, PID);
 
     switch (writeFormat_)
     {
-        case wfShort:
+        case fieldFormat::SHORT :
         {
-            forAll(facePts, i)
+            for (const label pointi : facePts)
             {
-                writeValue(os, facePts[i] + 1);
+                writeValue(os, pointi + 1);
             }
 
             break;
         }
-        case wfLong:
+
+        case fieldFormat::LONG :
         {
             forAll(facePts, i)
             {
@@ -250,33 +171,29 @@ void Foam::nastranSurfaceWriter::writeFace
                 if (i == 1)
                 {
                     os  << nl;
-                    os.unsetf(ios_base::right);
+                    os.unsetf(std::ios_base::right);
                     writeKeyword(os, "");
-                    os.setf(ios_base::right);
+                    os.setf(std::ios_base::right);
                 }
             }
 
             break;
         }
-        case wfFree:
+
+        case fieldFormat::FREE :
         {
-            forAll(facePts, i)
+            for (const label pointi : facePts)
             {
                 os  << separator_;
-                writeValue(os, facePts[i] + 1);
+                writeValue(os, pointi + 1);
             }
 
             break;
         }
-        default:
-        {
-            FatalErrorInFunction
-                << "Unknown writeFormat enumeration" << abort(FatalError);
-        }
     }
 
     os  << nl;
-    os.unsetf(ios_base::right);
+    os.unsetf(std::ios_base::right);
 }
 
 
@@ -375,7 +292,7 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeFooter
 
     // use single material ID
 
-    label MID = 1;
+    const label MID = 1;
 
     writeKeyword(os, "MAT1")    << separator_;
     writeValue(os, MID);
@@ -397,49 +314,48 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeFooter
 Foam::nastranSurfaceWriter::nastranSurfaceWriter()
 :
     surfaceWriter(),
-    writeFormat_(wfShort),
+    writeFormat_(fieldFormat::SHORT),
     fieldMap_(),
-    scale_(1.0)
+    scale_(1.0),
+    separator_()
 {}
 
 
 Foam::nastranSurfaceWriter::nastranSurfaceWriter(const dictionary& options)
 :
     surfaceWriter(),
-    writeFormat_(writeFormat::wfLong),
+    writeFormat_
+    (
+        fileFormats::NASCore::fieldFormatNames.lookupOrDefault
+        (
+            "format",
+            options,
+            fieldFormat::LONG
+        )
+    ),
     fieldMap_(),
-    scale_(options.lookupOrDefault("scale", 1.0)),
-    separator_("")
+    scale_(options.lookupOrDefault<scalar>("scale", 1.0)),
+    separator_()
 {
-    writeFormat_ = writeFormatNames_.lookupOrDefault
-    (
-        "format",
-        options,
-        writeFormat::wfLong
-    );
-
-    if (writeFormat_ == wfFree)
+    if (writeFormat_ == fieldFormat::FREE)
     {
         separator_ = ",";
     }
 
-    List<Pair<word>> fieldSet(options.lookup("fields"));
+    List<Pair<word>> fieldPairs(options.lookup("fields"));
 
-    forAll(fieldSet, i)
+    for (const Pair<word>& item : fieldPairs)
     {
-        dataFormat format = dataFormatNames_[fieldSet[i].second()];
-
-        fieldMap_.insert(fieldSet[i].first(), format);
+        // (field name => load format)
+        fieldMap_.insert
+        (
+            item.first(),
+            loadFormatNames_[item.second()]
+        );
     }
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::nastranSurfaceWriter::~nastranSurfaceWriter()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::fileName Foam::nastranSurfaceWriter::write
@@ -456,7 +372,7 @@ Foam::fileName Foam::nastranSurfaceWriter::write
     }
 
     OFstream os(outputDir/surfaceName + ".nas");
-    formatOS(os);
+    fileFormats::NASCore::setPrecision(os, writeFormat_);
 
     if (verbose)
     {
@@ -472,7 +388,7 @@ Foam::fileName Foam::nastranSurfaceWriter::write
     writeGeometry(os, surf, decomposedFaces);
 
     writeFooter(os, surf)
-        << "ENDDATA" << endl;
+        << "ENDDATA" << nl;
 
     return os.name();
 }
diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H
index 2106dc1b4c5ce134fc2aa623e60675121bbd12f7..0059a3411a53a8d7884e3f359dbd54758836bc4f 100644
--- a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H
+++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -32,16 +32,16 @@ Description
     {
         nastran
         {
-            // From OpenFOAM field name to Nastran field name
+            // From OpenFOAM field name to NASTRAN field name
             fields
             (
-                (pMean PLOAD2)
-                (p     PLOAD4)
+                (pMean  PLOAD2)
+                (p      PLOAD4)
             );
             // Optional scale
-            scale 2.0;
+            scale   2.0;
             // Optional format
-            format free;    //short, long, free
+            format  free;    // short, long, free
         }
     };
     \endverbatim
@@ -56,7 +56,7 @@ SourceFiles
 #define nastranSurfaceWriter_H
 
 #include "surfaceWriter.H"
-#include "Enum.H"
+#include "NASCore.H"
 #include "OFstream.H"
 #include "HashTable.H"
 
@@ -75,17 +75,14 @@ class nastranSurfaceWriter
 {
 public:
 
-    enum writeFormat
-    {
-        wfShort,
-        wfLong,
-        wfFree
-    };
+    //- File field formats
+    using fieldFormat = Foam::fileFormats::NASCore::fieldFormat;
 
-    enum dataFormat
+    //- Output load format
+    enum loadFormat
     {
-        dfPLOAD2,
-        dfPLOAD4
+        PLOAD2,
+        PLOAD4
     };
 
 
@@ -93,14 +90,13 @@ private:
 
     // Private data
 
-        static const Enum<writeFormat> writeFormatNames_;
-        static const Enum<dataFormat> dataFormatNames_;
+        static const Enum<loadFormat> loadFormatNames_;
 
-        //- Write option
-        writeFormat writeFormat_;
+        //- Field format (width and separator)
+        fieldFormat writeFormat_;
 
         //- Mapping from field name to data format enumeration
-        HashTable<dataFormat> fieldMap_;
+        HashTable<loadFormat> fieldMap_;
 
         //- Scale to apply to values (default = 1.0)
         scalar scale_;
@@ -111,14 +107,11 @@ private:
 
     // Private Member Functions
 
-        //- Initialise the output stream format parameters
-        void formatOS(Ostream& os) const;
-
         //- Write a coordinate
         void writeCoord
         (
             Ostream& os,
-            const point& p,
+            const point& pt,
             const label pointI  //!< 0-based Point Id
         ) const;
 
@@ -159,7 +152,7 @@ private:
         Ostream& writeFaceValue
         (
             Ostream& os,
-            const dataFormat& format,
+            const loadFormat format,
             const Type& value,
             const label EID     //!< 1-based Element Id
         ) const;
@@ -195,7 +188,7 @@ public:
 
 
     //- Destructor
-    virtual ~nastranSurfaceWriter();
+    virtual ~nastranSurfaceWriter() = default;
 
 
     // Member Functions
diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C
index 048088791c86cd4529eeef3f5de7ad0cf134e68f..c6619f5aa67a16a1e0b4add828309027d18010c7 100644
--- a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C
+++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -38,17 +38,19 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeValue
 {
     switch (writeFormat_)
     {
-        case wfShort:
+        case fieldFormat::SHORT :
         {
             os  << setw(8) << value;
             break;
         }
-        case wfLong:
+
+        case fieldFormat::LONG :
         {
             os  << setw(16) << value;
             break;
         }
-        case wfFree:
+
+        case fieldFormat::FREE :
         {
             os  << value;
             break;
@@ -63,7 +65,7 @@ template<class Type>
 Foam::Ostream& Foam::nastranSurfaceWriter::writeFaceValue
 (
     Ostream& os,
-    const dataFormat& format,
+    const loadFormat format,
     const Type& value,
     const label EID
 ) const
@@ -87,16 +89,16 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeFaceValue
     Type scaledValue = scale_*value;
 
     // Write keyword
-    writeKeyword(os, dataFormatNames_[format])  << separator_;
+    writeKeyword(os, loadFormatNames_[format])  << separator_;
 
     // Write load set ID
-    os.setf(ios_base::right);
+    os.setf(std::ios_base::right);
 
     writeValue(os, SID) << separator_;
 
     switch (format)
     {
-        case dfPLOAD2:
+        case loadFormat::PLOAD2 :
         {
             if (pTraits<Type>::nComponents == 1)
             {
@@ -105,7 +107,7 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeFaceValue
             else
             {
                 WarningInFunction
-                    << dataFormatNames_[format] << " requires scalar values "
+                    << loadFormatNames_[format] << " requires scalar values "
                     << "and cannot be used for higher rank values"
                     << endl;
 
@@ -116,27 +118,20 @@ Foam::Ostream& Foam::nastranSurfaceWriter::writeFaceValue
             break;
         }
 
-        case dfPLOAD4:
+        case loadFormat::PLOAD4 :
         {
             writeValue(os, EID);
 
-            for (direction dirI = 0; dirI < pTraits<Type>::nComponents; ++dirI)
+            for (direction d = 0; d < pTraits<Type>::nComponents; ++d)
             {
                 os  << separator_;
-                writeValue(os, component(scaledValue, dirI));
+                writeValue(os, component(scaledValue, d));
             }
             break;
         }
-
-        default:
-        {
-            FatalErrorInFunction
-                << "Unhandled enumeration " << dataFormatNames_[format]
-                << exit(FatalError);
-        }
     }
 
-    os.unsetf(ios_base::right);
+    os.unsetf(std::ios_base::right);
 
     os << nl;
 
@@ -167,7 +162,7 @@ Foam::fileName Foam::nastranSurfaceWriter::writeTemplate
         return fileName::null;
     }
 
-    const dataFormat& format(fieldMap_[fieldName]);
+    const loadFormat& format(fieldMap_[fieldName]);
 
     if (!isDir(outputDir/fieldName))
     {
@@ -178,7 +173,7 @@ Foam::fileName Foam::nastranSurfaceWriter::writeTemplate
     const scalar timeValue = 0.0;
 
     OFstream os(outputDir/fieldName/surfaceName + ".nas");
-    formatOS(os);
+    fileFormats::NASCore::setPrecision(os, writeFormat_);
 
     if (verbose)
     {
@@ -199,21 +194,19 @@ Foam::fileName Foam::nastranSurfaceWriter::writeTemplate
         << "$ Field data" << nl
         << "$" << nl;
 
+    label elemId = 0;
+
     if (isNodeValues)
     {
-        label elemId = 0;
-
-        forAll(decomposedFaces, i)
+        for (const DynamicList<face>& dFaces : decomposedFaces)
         {
-            const DynamicList<face>& dFaces = decomposedFaces[i];
-            forAll(dFaces, facei)
+            for (const face& f : dFaces)
             {
                 Type v = Zero;
-                const face& f = dFaces[facei];
 
-                forAll(f, fptI)
+                for (const label verti : f)
                 {
-                    v += values[f[fptI]];
+                    v += values[verti];
                 }
                 v /= f.size();
 
@@ -223,11 +216,8 @@ Foam::fileName Foam::nastranSurfaceWriter::writeTemplate
     }
     else
     {
-        label elemId = 0;
-
-        forAll(decomposedFaces, i)
+        for (const DynamicList<face>& dFaces : decomposedFaces)
         {
-            const DynamicList<face>& dFaces = decomposedFaces[i];
             forAll(dFaces, facei)
             {
                 writeFaceValue(os, format, values[facei], ++elemId);
diff --git a/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.C b/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.C
index 9b4c28c1ed0e5dee6d9908e24347d0b9c00196f8..14a27161e7baf29e67598e1d2ce202dffdf7784f 100644
--- a/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.C
+++ b/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.C
@@ -55,9 +55,8 @@ void Foam::vtkSurfaceWriter::writeGeometry
 
     // Write vertex coords
     os  << "POINTS " << points.size() << " double" << nl;
-    forAll(points, pointi)
+    for (const point& pt : points)
     {
-        const point& pt = points[pointi];
         os  << float(pt.x()) << ' '
             << float(pt.y()) << ' '
             << float(pt.z()) << nl;
@@ -67,22 +66,20 @@ void Foam::vtkSurfaceWriter::writeGeometry
 
     // Write faces
     label nNodes = 0;
-    forAll(faces, facei)
+    for (const face& f : faces)
     {
-        nNodes += faces[facei].size();
+        nNodes += f.size();
     }
 
     os  << "POLYGONS " << faces.size() << ' '
         << faces.size() + nNodes << nl;
 
-    forAll(faces, facei)
+    for (const face& f : faces)
     {
-        const face& f = faces[facei];
-
         os  << f.size();
-        forAll(f, fp)
+        for (const label verti : f)
         {
-            os  << ' ' << f[fp];
+            os  << ' ' << verti;
         }
         os  << nl;
     }
@@ -130,9 +127,8 @@ namespace Foam
     {
         os  << "3 " << values.size() << " float" << nl;
 
-        forAll(values, elemI)
+        for (const vector& v : values)
         {
-            const vector& v = values[elemI];
             os  << float(v[0]) << ' '
                 << float(v[1]) << ' '
                 << float(v[2]) << nl;
@@ -149,9 +145,8 @@ namespace Foam
     {
         os  << "1 " << values.size() << " float" << nl;
 
-        forAll(values, elemI)
+        for (const sphericalTensor& v : values)
         {
-            const sphericalTensor& v = values[elemI];
             os  << float(v[0]) << nl;
         }
     }
@@ -166,9 +161,8 @@ namespace Foam
     {
         os  << "6 " << values.size() << " float" << nl;
 
-        forAll(values, elemI)
+        for (const symmTensor& v : values)
         {
-            const symmTensor& v = values[elemI];
             os  << float(v[0]) << ' ' << float(v[1]) << ' ' << float(v[2])
                 << ' '
                 << float(v[3]) << ' ' << float(v[4]) << ' ' << float(v[5])
@@ -187,9 +181,8 @@ namespace Foam
     {
         os  << "9 " << values.size() << " float" << nl;
 
-        forAll(values, elemI)
+        for (const tensor& v : values)
         {
-            const tensor& v = values[elemI];
             os  << float(v[0]) << ' ' << float(v[1]) << ' ' << float(v[2])
                 << ' '
                 << float(v[3]) << ' ' << float(v[4]) << ' ' << float(v[5])
@@ -211,12 +204,12 @@ Foam::vtkSurfaceWriter::vtkSurfaceWriter()
 {}
 
 
-Foam::vtkSurfaceWriter::vtkSurfaceWriter(const dictionary& dict)
+Foam::vtkSurfaceWriter::vtkSurfaceWriter(const dictionary& options)
 :
     surfaceWriter(),
     writePrecision_
     (
-        dict.lookupOrDefault
+        options.lookupOrDefault
         (
             "writePrecision",
             IOstream::defaultPrecision()
@@ -225,12 +218,6 @@ Foam::vtkSurfaceWriter::vtkSurfaceWriter(const dictionary& dict)
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::vtkSurfaceWriter::~vtkSurfaceWriter()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::fileName Foam::vtkSurfaceWriter::write
@@ -260,7 +247,7 @@ Foam::fileName Foam::vtkSurfaceWriter::write
 }
 
 
-// create write methods
+// Create write methods
 defineSurfaceWriterWriteFields(Foam::vtkSurfaceWriter);
 
 
diff --git a/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.H b/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.H
index 85ab3026e914a09db083f23aa60ad62a33181544..b261f5a301bc60232b9a18a21811b1cf4bea8fab 100644
--- a/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.H
+++ b/src/sampling/sampledSurface/writers/vtk/vtkSurfaceWriter.H
@@ -93,7 +93,7 @@ public:
 
 
     //- Destructor
-    virtual ~vtkSurfaceWriter();
+    virtual ~vtkSurfaceWriter() = default;
 
 
     // Member Functions
diff --git a/src/surfMesh/Make/files b/src/surfMesh/Make/files
index 2bf796be62828de399df11d6bdf636011bf6fca9..23160f43c8fff48dd6a3ac40b97be2e735f6371a 100644
--- a/src/surfMesh/Make/files
+++ b/src/surfMesh/Make/files
@@ -25,6 +25,7 @@ $(surfaceFormats)/ac3d/AC3DsurfaceFormatCore.C
 $(surfaceFormats)/ac3d/AC3DsurfaceFormatRunTime.C
 $(surfaceFormats)/fire/FLMAsurfaceFormatRunTime.C
 $(surfaceFormats)/gts/GTSsurfaceFormatRunTime.C
+$(surfaceFormats)/gts/triSurfaceGTSformat.C
 $(surfaceFormats)/nas/NASsurfaceFormatRunTime.C
 $(surfaceFormats)/obj/OBJsurfaceFormatRunTime.C
 $(surfaceFormats)/obj/OBJstream.C
@@ -33,7 +34,8 @@ $(surfaceFormats)/smesh/SMESHsurfaceFormatRunTime.C
 $(surfaceFormats)/starcd/STARCDsurfaceFormatCore.C
 $(surfaceFormats)/starcd/STARCDsurfaceFormatRunTime.C
 $(surfaceFormats)/stl/STLsurfaceFormatRunTime.C
-$(surfaceFormats)/tri/TRIsurfaceFormatCore.C
+$(surfaceFormats)/stl/triSurfaceSTLformat.C
+$(surfaceFormats)/tri/TRIReader.C
 $(surfaceFormats)/tri/TRIsurfaceFormatRunTime.C
 $(surfaceFormats)/vtk/VTKsurfaceFormatCore.C
 $(surfaceFormats)/vtk/VTKsurfaceFormatRunTime.C
@@ -43,29 +45,12 @@ $(surfaceFormats)/x3d/X3DsurfaceFormatCore.C
 $(surfaceFormats)/x3d/X3DsurfaceFormatRunTime.C
 
 triSurface/triSurface.C
+triSurface/triSurfaceIO.C
 triSurface/triSurfaceAddressing.C
-triSurface/stitchTriangles.C
+triSurface/triSurfaceStitch.C
 
 triSurface/fields/triSurfaceFields.C
 triSurface/patches/geometricSurfacePatch.C
 triSurface/patches/surfacePatch.C
 
-interfaces = triSurface/interfaces
-$(interfaces)/STL/writeSTL.C
-$(interfaces)/STL/readSTL.C
-$(interfaces)/GTS/writeGTS.C
-$(interfaces)/GTS/readGTS.C
-$(interfaces)/OBJ/readOBJ.C
-$(interfaces)/OBJ/writeOBJ.C
-$(interfaces)/SMESH/writeSMESH.C
-$(interfaces)/OFF/readOFF.C
-$(interfaces)/OFF/writeOFF.C
-$(interfaces)/TRI/writeTRI.C
-$(interfaces)/TRI/readTRI.C
-$(interfaces)/AC3D/readAC.C
-$(interfaces)/AC3D/writeAC.C
-$(interfaces)/VTK/readVTK.C
-$(interfaces)/VTK/writeVTK.C
-$(interfaces)/NAS/readNAS.C
-
 LIB = $(FOAM_LIBBIN)/libsurfMesh
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.C b/src/surfMesh/MeshedSurface/MeshedSurface.C
index a2efe775e6a7bec91c8046439efb778e61e2845c..5ff888af9ae8b0740f4a5c573ea2d75641f23f25 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.C
@@ -107,10 +107,11 @@ template<class Face>
 void Foam::MeshedSurface<Face>::write
 (
     const fileName& name,
-    const MeshedSurface<Face>& surf
+    const MeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
-    write(name, name.ext(), surf);
+    write(name, name.ext(), surf, options);
 }
 
 
@@ -119,7 +120,8 @@ void Foam::MeshedSurface<Face>::write
 (
     const fileName& name,
     const word& ext,
-    const MeshedSurface<Face>& surf
+    const MeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
     if (debug)
@@ -136,7 +138,7 @@ void Foam::MeshedSurface<Face>::write
 
         if (delegate.found(ext))
         {
-            MeshedSurfaceProxy<Face>(surf).write(name, ext);
+            MeshedSurfaceProxy<Face>(surf).write(name, ext, options);
         }
         else
         {
@@ -149,7 +151,7 @@ void Foam::MeshedSurface<Face>::write
     }
     else
     {
-        mfIter()(name, surf);
+        mfIter()(name, surf, options);
     }
 }
 
@@ -159,7 +161,8 @@ void Foam::MeshedSurface<Face>::write
 template<class Face>
 Foam::MeshedSurface<Face>::MeshedSurface()
 :
-    ParentType(List<Face>(), pointField())
+    ParentType(List<Face>(), pointField()),
+    zones_()
 {}
 
 
@@ -171,8 +174,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
     const Xfer<surfZoneList>& zoneLst
 )
 :
-    ParentType(List<Face>(), pointField()),
-    zones_()
+    MeshedSurface<Face>()
 {
     reset(pointLst, faceLst, zoneLst);
 }
@@ -187,7 +189,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
     const UList<word>& zoneNames
 )
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     reset(pointLst, faceLst, Xfer<surfZoneList>());
 
@@ -242,7 +244,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
 template<class Face>
 Foam::MeshedSurface<Face>::MeshedSurface(const surfMesh& mesh)
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     // same face type as surfMesh
     MeshedSurface<face> surf
@@ -263,7 +265,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
     const bool useGlobalPoints
 )
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     const polyMesh& mesh = bMesh.mesh();
     const polyPatchList& bPatches = bMesh;
@@ -312,7 +314,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
                 nZone
             );
 
-            nZone++;
+            ++nZone;
             startFacei += p.size();
         }
     }
@@ -332,38 +334,27 @@ Foam::MeshedSurface<Face>::MeshedSurface
 
 
 template<class Face>
-Foam::MeshedSurface<Face>::MeshedSurface
-(
-    const fileName& name,
-    const word& ext
-)
+Foam::MeshedSurface<Face>::MeshedSurface(const fileName& name, const word& ext)
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     read(name, ext);
 }
 
 
 template<class Face>
-Foam::MeshedSurface<Face>::MeshedSurface
-(
-    const fileName& name
-)
+Foam::MeshedSurface<Face>::MeshedSurface(const fileName& name)
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     read(name);
 }
 
 
 template<class Face>
-Foam::MeshedSurface<Face>::MeshedSurface
-(
-    Istream& is
-)
+Foam::MeshedSurface<Face>::MeshedSurface(Istream& is)
 :
-    ParentType(List<Face>(), pointField()),
-    zones_()
+    MeshedSurface<Face>()
 {
     read(is);
 }
@@ -376,7 +367,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
     const word& surfName
 )
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     surfMesh mesh
     (
@@ -407,10 +398,10 @@ Foam::MeshedSurface<Face>::MeshedSurface
 template<class Face>
 Foam::MeshedSurface<Face>::MeshedSurface
 (
-    const Xfer<UnsortedMeshedSurface<Face>>& surf
+    const Xfer<MeshedSurface<Face>>& surf
 )
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     transfer(surf());
 }
@@ -419,16 +410,15 @@ Foam::MeshedSurface<Face>::MeshedSurface
 template<class Face>
 Foam::MeshedSurface<Face>::MeshedSurface
 (
-    const Xfer<MeshedSurface<Face>>& surf
+    const Xfer<UnsortedMeshedSurface<Face>>& surf
 )
 :
-    ParentType(List<Face>(), pointField())
+    MeshedSurface<Face>()
 {
     transfer(surf());
 }
 
 
-
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 template<class Face>
@@ -446,44 +436,43 @@ void Foam::MeshedSurface<Face>::remapFaces
     const labelUList& faceMap
 )
 {
-    // recalculate the zone start/size
-    if (notNull(faceMap) && faceMap.size())
+    if (isNull(faceMap) || faceMap.empty())
     {
-        surfZoneList& zones = storedZones();
+        return;
+    }
 
-        if (zones.size() == 1)
-        {
-            // optimized for single zone case
-            zones[0].size() = faceMap.size();
-        }
-        else if (zones.size())
-        {
-            label newFacei = 0;
-            label origEndI = 0;
-            forAll(zones, zoneI)
-            {
-                surfZone& zone = zones[zoneI];
+    surfZoneList& zones = storedZones();
 
-                // adjust zone start
-                zone.start() = newFacei;
-                origEndI += zone.size();
+    if (zones.size() == 1)
+    {
+        zones[0].size() = faceMap.size();   // Single zone case is trivial
+        return;
+    }
 
-                for (label facei = newFacei; facei < faceMap.size(); ++facei)
-                {
-                    if (faceMap[facei] < origEndI)
-                    {
-                        ++newFacei;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
+    // Recalculate the zone start/size
+    label newFacei = 0;
+    label origEndI = 0;
 
-                // adjust zone size
-                zone.size() = newFacei - zone.start();
+    for (surfZone& zone : zones)
+    {
+        // Adjust zone start
+        zone.start() = newFacei;
+        origEndI += zone.size();
+
+        for (label facei = newFacei; facei < faceMap.size(); ++facei)
+        {
+            if (faceMap[facei] < origEndI)
+            {
+                ++newFacei;
+            }
+            else
+            {
+                break;
             }
         }
+
+        // Adjust zone size
+        zone.size() = newFacei - zone.start();
     }
 }
 
@@ -664,7 +653,7 @@ bool Foam::MeshedSurface<Face>::stitchFaces
                 faceLst[newFacei] = f;
             }
             faceMap[newFacei] = facei;
-            newFacei++;
+            ++newFacei;
         }
         else if (verbose)
         {
@@ -730,7 +719,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
             }
 
             faceMap[facei] = facei;
-            newFacei++;
+            ++newFacei;
         }
         else
         {
@@ -801,7 +790,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
         if (okay)
         {
             faceMap[facei] = facei;
-            newFacei++;
+            ++newFacei;
         }
         else
         {
@@ -834,7 +823,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
                     faceLst[newFacei] = faceLst[facei];
                 }
                 faceMap[newFacei] = facei;
-                newFacei++;
+                ++newFacei;
             }
         }
 
@@ -990,11 +979,11 @@ Foam::label Foam::MeshedSurface<Face>::triangulate
 
             for (label fp = 1; fp < f.size() - 1; ++fp)
             {
-                label fp1 = f.fcIndex(fp);
+                const label fp1 = f.fcIndex(fp);
 
                 newFaces[nTri] = Face{f[0], f[fp], f[fp1]};
                 faceMap[nTri] = facei;
-                nTri++;
+                ++nTri;
             }
         }
     }
@@ -1018,7 +1007,7 @@ Foam::label Foam::MeshedSurface<Face>::triangulate
                     static_cast<labelUList&>(tmpTri[triI])
                 );
                 faceMap[nTri] = facei;
-                nTri++;
+                ++nTri;
             }
         }
     }
@@ -1239,20 +1228,17 @@ Foam::MeshedSurface<Face>::xferZones()
 }
 
 
-// Read from file, determine format from extension
 template<class Face>
 bool Foam::MeshedSurface<Face>::read(const fileName& name)
 {
-    word ext = name.ext();
+    const word ext(name.ext());
     if (ext == "gz")
     {
         fileName unzipName = name.lessExt();
         return read(unzipName, unzipName.ext());
     }
-    else
-    {
-        return read(name, ext);
-    }
+
+    return read(name, ext);
 }
 
 
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.H b/src/surfMesh/MeshedSurface/MeshedSurface.H
index aca6e18647f2e65174f915ea80dee8e77a5e66c9..118bce82907b3c073c75ccebe9f4997b7092a90b 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.H
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -52,19 +52,18 @@ SourceFiles
 #include "pointField.H"
 #include "face.H"
 #include "labelledTri.H"
-
+#include "HashSet.H"
 #include "surfZoneList.H"
 #include "surfaceFormatsCore.H"
 #include "runTimeSelectionTables.H"
 #include "memberFunctionSelectionTables.H"
-#include "HashSet.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
-// Forward declaration of friend functions and operators
+// Forward declarations
 
 class Time;
 class surfMesh;
@@ -124,10 +123,10 @@ private:
     // Private Member functions
 
         //- Read/construct from Istream
-        Istream& read(Istream&);
+        Istream& read(Istream& is);
 
         //- Write to Ostream
-        Ostream& write(Ostream&) const;
+        Ostream& write(Ostream& os) const;
 
 
 protected:
@@ -138,7 +137,7 @@ protected:
         //  Eg, transcribe face to triFace, or face -> labelledTri, including
         //  any addZonesToFaces adjustment.
         //  No general form, only specializations.
-        void transcribe(MeshedSurface<face>&);
+        void transcribe(MeshedSurface<face>& surf);
 
         //- Basic sanity check on zones
         void checkZones();
@@ -195,7 +194,10 @@ public:
         //- Can we write this file format?
         static bool canWriteType(const word& ext, const bool verbose=false);
 
+        //- Known readable file-types
         static wordHashSet readTypes();
+
+        //- Known writable file-types
         static wordHashSet writeTypes();
 
 
@@ -222,10 +224,10 @@ public:
             const UList<word>& zoneNames = UList<word>()
         );
 
-        //- Construct as copy
+        //- Copy construct
         MeshedSurface(const MeshedSurface& surf);
 
-        //- Construct from a UnsortedMeshedSurface
+        //- Copy construct from an UnsortedMeshedSurface
         MeshedSurface(const UnsortedMeshedSurface<Face>& surf);
 
         //- Construct from a boundary mesh with local points/faces
@@ -238,11 +240,11 @@ public:
         //- Construct from a surfMesh
         MeshedSurface(const surfMesh& mesh);
 
-        //- Construct by transferring the contents from a UnsortedMeshedSurface
-        MeshedSurface(const Xfer<UnsortedMeshedSurface<Face>>&);
-
         //- Construct by transferring the contents from a MeshedSurface
-        MeshedSurface(const Xfer<MeshedSurface<Face>>&);
+        MeshedSurface(const Xfer<MeshedSurface<Face>>& surf);
+
+        //- Construct by transferring the contents from a UnsortedMeshedSurface
+        MeshedSurface(const Xfer<UnsortedMeshedSurface<Face>>& surf);
 
         //- Construct from file name (uses extension to determine type)
         MeshedSurface(const fileName& name);
@@ -285,7 +287,7 @@ public:
         );
 
         //- Select constructed from filename (implicit extension)
-        static autoPtr<MeshedSurface> New(const fileName&);
+        static autoPtr<MeshedSurface> New(const fileName& name);
 
 
     //- Destructor
@@ -302,16 +304,18 @@ public:
             fileExtension,
             (
                 const fileName& name,
-                const MeshedSurface<Face>& surf
+                const MeshedSurface<Face>& surf,
+                const dictionary& options
             ),
-            (name, surf)
+            (name, surf, options)
         );
 
         //- Write to file, selecting writer based on its extension
         static void write
         (
             const fileName& name,
-            const MeshedSurface<Face>& surf
+            const MeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write to file, selecting writer based on the given extension
@@ -319,7 +323,8 @@ public:
         (
             const fileName& name,
             const word& ext,
-            const MeshedSurface<Face>& surf
+            const MeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
 
@@ -405,15 +410,15 @@ public:
 
 
             //- Move points
-            virtual void movePoints(const pointField&);
+            virtual void movePoints(const pointField& newPoints);
 
             //- Scale points. A non-positive factor is ignored
-            virtual void scalePoints(const scalar);
+            virtual void scalePoints(const scalar scaleFactor);
 
             //- Reset by transferring contents of the argument and annul it
             virtual void reset
             (
-                const Xfer<MeshedSurface<Face>>&
+                const Xfer<MeshedSurface<Face>>& surf
             );
 
             //- Reset primitive data (points, faces and zones)
@@ -500,10 +505,10 @@ public:
         // Read
 
             //- Read from file. Chooses reader based on explicit extension
-            bool read(const fileName&, const word& ext);
+            bool read(const fileName& name, const word& ext);
 
             //- Read from file. Chooses reader based on detected extension
-            virtual bool read(const fileName&);
+            virtual bool read(const fileName& name);
 
 
         // Write
@@ -511,15 +516,19 @@ public:
             void writeStats(Ostream& os) const;
 
             //- Generic write routine. Chooses writer based on extension.
-            virtual void write(const fileName& name) const
+            virtual void write
+            (
+                const fileName& name,
+                const dictionary& options = dictionary::null
+            ) const
             {
-                write(name, *this);
+                write(name, *this, options);
             }
 
             //- Write to database
             void write
             (
-                const Time&,
+                const Time& t,
                 const word& surfName = word::null
             ) const;
 
diff --git a/src/surfMesh/MeshedSurface/MeshedSurfaceIO.C b/src/surfMesh/MeshedSurface/MeshedSurfaceIO.C
index 296a93db1e20583857ef11b146043ce31da39af1..6757e62c099973627e8f2e9e98526337073563d3 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurfaceIO.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurfaceIO.C
@@ -65,19 +65,18 @@ void Foam::MeshedSurface<Face>::writeStats(Ostream& os) const
     }
     else
     {
-        label nTri = 0;
-        label nQuad = 0;
-        forAll(*this, i)
+        label nTri = 0, nQuad = 0;
+        for (const Face& f : *this)
         {
-            const label n = this->operator[](i).size();
+            const label n = f.size();
 
             if (n == 3)
             {
-                nTri++;
+                ++nTri;
             }
             else if (n == 4)
             {
-                nQuad++;
+                ++nQuad;
             }
         }
 
diff --git a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
index 512746741833dfdcc1e65a5edbe6731bd9d2f650..6a24f38de12f34132039928826a31c113b9ad865 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
@@ -24,6 +24,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "MeshedSurface.H"
+#include "ListOps.H"
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
@@ -74,27 +75,26 @@ void Foam::MeshedSurface<Face>::sortFacesAndStore
 
     if (sorted)
     {
-        // already sorted - simply transfer faces
+        // Already sorted - simply transfer faces
         this->storedFaces().transfer(oldFaces);
-    }
-    else
-    {
-        // unsorted - determine the sorted order:
-        // avoid SortableList since we discard the main list anyhow
-        List<label> faceMap;
-        sortedOrder(zones, faceMap);
         zones.clear();
-
-        // sorted faces
-        List<Face> newFaces(faceMap.size());
-        forAll(faceMap, facei)
-        {
-            // use transfer to recover memory where possible
-            newFaces[facei].transfer(oldFaces[faceMap[facei]]);
-        }
-        this->storedFaces().transfer(newFaces);
+        return;
     }
+
+    // Determine the sorted order:
+    // use sortedOrder directly since we discard the intermediate list anyhow
+    List<label> faceMap;
+    sortedOrder(zones, faceMap);
     zones.clear();
+
+    // Sorted faces
+    List<Face> newFaces(faceMap.size());
+    forAll(faceMap, facei)
+    {
+        // use transfer to recover memory where possible
+        newFaces[facei].transfer(oldFaces[faceMap[facei]]);
+    }
+    this->storedFaces().transfer(newFaces);
 }
 
 
@@ -116,7 +116,7 @@ void Foam::MeshedSurface<Face>::addZones
         if (srfZones[zoneI].size() || !cullEmpty)
         {
             zones[nZone] = surfZone(srfZones[zoneI], nZone);
-            nZone++;
+            ++nZone;
         }
     }
     zones.setSize(nZone);
@@ -148,7 +148,7 @@ void Foam::MeshedSurface<Face>::addZones
                 nZone
             );
             start += sizes[zoneI];
-            nZone++;
+            ++nZone;
         }
     }
     zones.setSize(nZone);
@@ -179,7 +179,7 @@ void Foam::MeshedSurface<Face>::addZones
                 nZone
             );
             start += sizes[zoneI];
-            nZone++;
+            ++nZone;
         }
     }
     zones.setSize(nZone);
diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C
index dd15f9d31fbb646e3ce068894b9b447f224f3b85..b83b2e4cdd317515fa96a5c0495db2a58b658e2e 100644
--- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C
+++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C
@@ -58,10 +58,11 @@ template<class Face>
 void Foam::MeshedSurfaceProxy<Face>::write
 (
     const fileName& name,
-    const MeshedSurfaceProxy& surf
+    const MeshedSurfaceProxy& surf,
+    const dictionary& options
 )
 {
-    write(name, name.ext(), surf);
+    write(name, name.ext(), surf, options);
 }
 
 
@@ -70,7 +71,8 @@ void Foam::MeshedSurfaceProxy<Face>::write
 (
     const fileName& name,
     const word& ext,
-    const MeshedSurfaceProxy& surf
+    const MeshedSurfaceProxy& surf,
+    const dictionary& options
 )
 {
     if (debug)
@@ -89,7 +91,7 @@ void Foam::MeshedSurfaceProxy<Face>::write
             << exit(FatalError);
     }
 
-    mfIter()(name, surf);
+    mfIter()(name, surf, options);
 }
 
 
@@ -180,8 +182,7 @@ void Foam::MeshedSurfaceProxy<Face>::write
 
         if (this->useFaceMap())
         {
-            // this is really a bit annoying (and wasteful) but no other way
-            os  << reorder(this->faceMap(), this->surfFaces());
+            os  << UIndirectList<Face>(this->surfFaces(), this->faceMap());
         }
         else
         {
@@ -226,9 +227,9 @@ template<class Face>
 Foam::MeshedSurfaceProxy<Face>::MeshedSurfaceProxy
 (
     const pointField& pointLst,
-    const List<Face>& faceLst,
-    const List<surfZone>& zoneLst,
-    const List<label>& faceMap
+    const UList<Face>& faceLst,
+    const UList<surfZone>& zoneLst,
+    const labelUList& faceMap
 )
 :
     points_(pointLst),
@@ -238,13 +239,6 @@ Foam::MeshedSurfaceProxy<Face>::MeshedSurfaceProxy
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-template<class Face>
-Foam::MeshedSurfaceProxy<Face>::~MeshedSurfaceProxy()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Face>
@@ -254,17 +248,14 @@ inline Foam::label Foam::MeshedSurfaceProxy<Face>::nTriangles() const
     {
         return this->size();
     }
-    else
-    {
-        label nTri = 0;
-        const List<Face>& faceLst = this->surfFaces();
-        forAll(faceLst, facei)
-        {
-            nTri += faceLst[facei].nTriangles();
-        }
 
-        return nTri;
+    label nTri = 0;
+    for (const Face& f : this->surfFaces())
+    {
+        nTri += f.nTriangles();
     }
+
+    return nTri;
 }
 
 
diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
index 6c0f3582e577fa2ac8bcbfae373f606f95a16148..ae3363984a62d9d1e12e42a2ac4cd273028b2c68 100644
--- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
+++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
@@ -39,12 +39,11 @@ SourceFiles
 
 #include "pointField.H"
 #include "labelledTri.H"
-
+#include "HashSet.H"
 #include "surfZoneList.H"
 #include "surfaceFormatsCore.H"
 #include "runTimeSelectionTables.H"
 #include "memberFunctionSelectionTables.H"
-#include "HashSet.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -64,16 +63,15 @@ class MeshedSurfaceProxy
 :
     public fileFormats::surfaceFormatsCore
 {
-    //- Private data
+    // Private Member Data
 
         const pointField& points_;
 
-        const List<Face>& faces_;
+        const UList<Face>& faces_;
 
-        const List<surfZone>& zones_;
-
-        const List<label>& faceMap_;
+        const UList<surfZone>& zones_;
 
+        const UList<label>& faceMap_;
 
 public:
 
@@ -101,14 +99,14 @@ public:
         MeshedSurfaceProxy
         (
             const pointField& pointLst,
-            const List<Face>& faceLst,
-            const List<surfZone>& zoneLst = List<surfZone>(),
-            const List<label>& faceMap = List<label>()
+            const UList<Face>& faceLst,
+            const UList<surfZone>& zoneLst = List<surfZone>(),
+            const labelUList& faceMap = List<label>()
         );
 
 
     //- Destructor
-    virtual ~MeshedSurfaceProxy();
+    virtual ~MeshedSurfaceProxy() = default;
 
 
     // Member Function Selectors
@@ -121,16 +119,18 @@ public:
             fileExtension,
             (
                 const fileName& name,
-                const MeshedSurfaceProxy<Face>& surf
+                const MeshedSurfaceProxy<Face>& surf,
+                const dictionary& options
             ),
-            (name, surf)
+            (name, surf, options)
         );
 
-        //- Write to file, selected based on its extension
+        //- Write to file, select based on its extension
         static void write
         (
             const fileName& name,
-            const MeshedSurfaceProxy& surf
+            const MeshedSurfaceProxy& surf,
+            const dictionary& options
         );
 
         //- Write to file, selected based on given extension
@@ -138,7 +138,8 @@ public:
         (
             const fileName& name,
             const word& ext,
-            const MeshedSurfaceProxy& surf
+            const MeshedSurfaceProxy& surf,
+            const dictionary& options
         );
 
 
@@ -159,7 +160,7 @@ public:
             }
 
             //- Return const access to the faces
-            inline const List<Face>& surfFaces() const
+            inline const UList<Face>& surfFaces() const
             {
                 return faces_;
             }
@@ -167,13 +168,13 @@ public:
             //- Const access to the surface zones.
             //  If zones are defined, they must be contiguous and cover the
             //  entire surface
-            inline const List<surfZone>& surfZones() const
+            inline const UList<surfZone>& surfZones() const
             {
                 return zones_;
             }
 
             //- Const access to the faceMap, zero-sized when unused
-            inline const List<label>& faceMap() const
+            inline const labelUList& faceMap() const
             {
                 return faceMap_;
             }
@@ -190,16 +191,25 @@ public:
 
         // Write
 
-            //- Generic write routine. Chooses writer based on extension.
-            virtual void write(const fileName& name) const
+            //- Generic write routine. Chooses writer based on its extension.
+            virtual void write
+            (
+                const fileName& name,
+                const dictionary& options = dictionary::null
+            ) const
             {
-                write(name, *this);
+                write(name, *this, options);
             }
 
             //- Generic write routine. Chooses writer based on extension.
-            virtual void write(const fileName& name, const word& ext) const
+            virtual void write
+            (
+                const fileName& name,
+                const word& ext,
+                const dictionary& options = dictionary::null
+            ) const
             {
-                write(name, ext, *this);
+                write(name, ext, *this, options);
             }
 
             //- Write to database
diff --git a/src/surfMesh/ModifiableMeshedSurface/ModifiableMeshedSurface.H b/src/surfMesh/ModifiableMeshedSurface/ModifiableMeshedSurface.H
index 160198dff1faa24f0b110a77677fb0d7787ba805..5489558f20a723d369384a5a5591a3c3f95c241e 100644
--- a/src/surfMesh/ModifiableMeshedSurface/ModifiableMeshedSurface.H
+++ b/src/surfMesh/ModifiableMeshedSurface/ModifiableMeshedSurface.H
@@ -83,8 +83,7 @@ public:
 
 
     //- Destructor
-    virtual ~ModifiableMeshedSurface()
-    {}
+    virtual ~ModifiableMeshedSurface() = default;
 
 
     // Member Functions
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
index 2df9b42fdc3f43245ef282450d57826227aefd0a..543b7c75cecb036230b41295af48c394d9cf5e7a 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
@@ -102,7 +102,21 @@ template<class Face>
 void Foam::UnsortedMeshedSurface<Face>::write
 (
     const fileName& name,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
+)
+{
+    write(name, name.ext(), surf, options);
+}
+
+
+template<class Face>
+void Foam::UnsortedMeshedSurface<Face>::write
+(
+    const fileName& name,
+    const word& ext,
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
     if (debug)
@@ -110,8 +124,6 @@ void Foam::UnsortedMeshedSurface<Face>::write
         InfoInFunction << "Writing to " << name << endl;
     }
 
-    const word ext = name.ext();
-
     auto mfIter = writefileExtensionMemberFunctionTablePtr_->cfind(ext);
 
     if (!mfIter.found())
@@ -121,7 +133,7 @@ void Foam::UnsortedMeshedSurface<Face>::write
 
         if (delegate.found(ext))
         {
-            MeshedSurfaceProxy<Face>(surf).write(name, ext);
+            MeshedSurfaceProxy<Face>(surf).write(name, ext, options);
         }
         else
         {
@@ -134,7 +146,7 @@ void Foam::UnsortedMeshedSurface<Face>::write
     }
     else
     {
-        mfIter()(name, surf);
+        mfIter()(name, surf, options);
     }
 }
 
@@ -230,7 +242,7 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     const Xfer<UnsortedMeshedSurface<Face>>& surf
 )
 :
-    ParentType()
+    UnsortedMeshedSurface<Face>()
 {
     transfer(surf());
 }
@@ -242,7 +254,7 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     const Xfer<MeshedSurface<Face>>& surf
 )
 :
-    ParentType()
+    UnsortedMeshedSurface<Face>()
 {
     transfer(surf());
 }
@@ -255,7 +267,7 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     const word& ext
 )
 :
-    ParentType()
+    UnsortedMeshedSurface<Face>()
 {
     read(name, ext);
 }
@@ -267,7 +279,7 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     const fileName& name
 )
 :
-    ParentType()
+    UnsortedMeshedSurface<Face>()
 {
     read(name);
 }
@@ -279,9 +291,7 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     Istream& is
 )
 :
-    ParentType(),
-    zoneIds_(),
-    zoneToc_()
+    UnsortedMeshedSurface<Face>()
 {
     read(is);
 }
@@ -294,20 +304,13 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
     const word& surfName
 )
 :
-    ParentType()
+    UnsortedMeshedSurface<Face>()
 {
     MeshedSurface<Face> surf(t, surfName);
     transfer(surf);
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-template<class Face>
-Foam::UnsortedMeshedSurface<Face>::~UnsortedMeshedSurface()
-{}
-
-
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
 template<class Face>
@@ -410,27 +413,28 @@ void Foam::UnsortedMeshedSurface<Face>::remapFaces
 )
 {
     // re-assign the zone Ids
-    if (notNull(faceMap) && faceMap.size())
+    if (isNull(faceMap) || faceMap.empty())
     {
-        if (zoneToc_.empty())
-        {
-            setOneZone();
-        }
-        else if (zoneToc_.size() == 1)
-        {
-            // optimized for single-zone case
-            zoneIds_ = 0;
-        }
-        else
-        {
-            List<label> newZones(faceMap.size());
+        return;
+    }
 
-            forAll(faceMap, facei)
-            {
-                newZones[facei] = zoneIds_[faceMap[facei]];
-            }
-            zoneIds_.transfer(newZones);
+    if (zoneToc_.empty())
+    {
+        setOneZone();
+    }
+    else if (zoneToc_.size() == 1)
+    {
+        zoneIds_ = 0;  // Optimized for single-zone case
+    }
+    else
+    {
+        List<label> newZones(faceMap.size());
+
+        forAll(faceMap, facei)
+        {
+            newZones[facei] = zoneIds_[faceMap[facei]];
         }
+        zoneIds_.transfer(newZones);
     }
 }
 
@@ -732,16 +736,14 @@ Foam::UnsortedMeshedSurface<Face>::xferZoneIds()
 template<class Face>
 bool Foam::UnsortedMeshedSurface<Face>::read(const fileName& name)
 {
-    word ext = name.ext();
+    const word ext(name.ext());
     if (ext == "gz")
     {
         fileName unzipName = name.lessExt();
         return read(unzipName, unzipName.ext());
     }
-    else
-    {
-        return read(name, ext);
-    }
+
+    return read(name, ext);
 }
 
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
index e038e927114816dbb7b35a0e572501c9f60aedb1..013417ac6af544d091631fdfc407b9b1637d134b 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -50,9 +50,9 @@ SourceFiles
 #include "surfZoneIdentifierList.H"
 #include "surfZoneList.H"
 #include "surfaceFormatsCore.H"
+#include "HashSet.H"
 #include "runTimeSelectionTables.H"
 #include "memberFunctionSelectionTables.H"
-#include "HashSet.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -163,7 +163,10 @@ public:
         //- Can we write this file format?
         static bool canWriteType(const word& ext, const bool verbose=false);
 
+        //- Known readable file-types
         static wordHashSet readTypes();
+
+        //- Known writable file-types
         static wordHashSet writeTypes();
 
 
@@ -240,16 +243,16 @@ public:
         //- Select constructed from filename (explicit extension)
         static autoPtr<UnsortedMeshedSurface> New
         (
-            const fileName&,
+            const fileName& name,
             const word& ext
         );
 
         //- Select constructed from filename (implicit extension)
-        static autoPtr<UnsortedMeshedSurface> New(const fileName&);
+        static autoPtr<UnsortedMeshedSurface> New(const fileName& name);
 
 
     //- Destructor
-    virtual ~UnsortedMeshedSurface();
+    virtual ~UnsortedMeshedSurface() = default;
 
 
     // Member Function Selectors
@@ -262,16 +265,27 @@ public:
             fileExtension,
             (
                 const fileName& name,
-                const UnsortedMeshedSurface<Face>& surf
+                const UnsortedMeshedSurface<Face>& surf,
+                const dictionary& options
             ),
-            (name, surf)
+            (name, surf, options)
         );
 
-        //- Write to file
+        //- Write to file, select based on its extension
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& name,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
+        );
+
+        //- Write to file, selected based on given extension
+        static void write
+        (
+            const fileName& name,
+            const word& ext,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options
         );
 
 
@@ -381,16 +395,20 @@ public:
 
         // Write
 
-            //- Generic write routine. Chooses writer based on extension.
-            virtual void write(const fileName& name) const
+            //- Generic write routine. Chooses writer based on its extension.
+            virtual void write
+            (
+                const fileName& name,
+                const dictionary& options = dictionary::null
+            ) const
             {
-                write(name, *this);
+                write(name, *this, options);
             }
 
             //- Write to database
             void write
             (
-                const Time&,
+                const Time& t,
                 const word& surfName = word::null
             ) const;
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurfaceNew.C b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurfaceNew.C
index 89861883503eace0c1ee6a6e08140aa74743e618..34b17c66a30a6bb37bc28f3dcb9d7bbf914b331b 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurfaceNew.C
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurfaceNew.C
@@ -30,7 +30,11 @@ License
 
 template<class Face>
 Foam::autoPtr<Foam::UnsortedMeshedSurface<Face>>
-Foam::UnsortedMeshedSurface<Face>::New(const fileName& name, const word& ext)
+Foam::UnsortedMeshedSurface<Face>::New
+(
+    const fileName& name,
+    const word& ext
+)
 {
     if (debug)
     {
diff --git a/src/surfMesh/mergedSurf/mergedSurf.C b/src/surfMesh/mergedSurf/mergedSurf.C
index d5c5f3dc8e8ab835ae861c899e0da54ca7c8419a..48cf9e217536563cb869532366f1648d8fbcd235 100644
--- a/src/surfMesh/mergedSurf/mergedSurf.C
+++ b/src/surfMesh/mergedSurf/mergedSurf.C
@@ -50,12 +50,6 @@ Foam::mergedSurf::mergedSurf
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::mergedSurf::~mergedSurf()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::mergedSurf::use()
diff --git a/src/surfMesh/mergedSurf/mergedSurf.H b/src/surfMesh/mergedSurf/mergedSurf.H
index dae03660ee95fcf6797b986d75a6e2f989d71387..b4d63a0ba9bb6b4e9fe1031788818b9c578092da 100644
--- a/src/surfMesh/mergedSurf/mergedSurf.H
+++ b/src/surfMesh/mergedSurf/mergedSurf.H
@@ -72,7 +72,7 @@ public:
 
 
     //- Destructor
-    virtual ~mergedSurf();
+    virtual ~mergedSurf() = default;
 
 
     // Access Member Functions
diff --git a/src/surfMesh/meshedSurf/meshedSurf.H b/src/surfMesh/meshedSurf/meshedSurf.H
index 0d7281be04c55c37a83d5a1749bb9019f469c508..6a08bf99ffa71ee60580f4c53ff8b38e473cb510 100644
--- a/src/surfMesh/meshedSurf/meshedSurf.H
+++ b/src/surfMesh/meshedSurf/meshedSurf.H
@@ -34,7 +34,7 @@ Description
 
 #include "pointField.H"
 #include "faceList.H"
-#include "ListOps.H"
+#include "labelList.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -52,13 +52,11 @@ public:
     // Constructors
 
         //- Construct null
-        meshedSurf()
-        {}
+        meshedSurf() = default;
 
 
     //- Destructor
-    virtual ~meshedSurf()
-    {}
+    virtual ~meshedSurf() = default;
 
 
     // Access Member Functions
diff --git a/src/surfMesh/meshedSurf/meshedSurfRef.H b/src/surfMesh/meshedSurf/meshedSurfRef.H
index 8390795fb69b2cf86ecb85377a534210ff281cfc..a69cf87c0fa1a6d286b4123fe5fab2bf9f3d1042 100644
--- a/src/surfMesh/meshedSurf/meshedSurfRef.H
+++ b/src/surfMesh/meshedSurf/meshedSurfRef.H
@@ -33,7 +33,6 @@ Description
 #define meshedSurfRef_H
 
 #include "meshedSurf.H"
-#include "labelList.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -63,8 +62,6 @@ class meshedSurfRef
 
 public:
 
-    // Public Member Functions
-
     // Constructors
 
         //- Construct from components
@@ -82,8 +79,7 @@ public:
 
 
     //- Destructor
-    virtual ~meshedSurfRef()
-    {}
+    virtual ~meshedSurfRef() = default;
 
 
     // Access Member Functions
diff --git a/src/surfMesh/surfMesh/surfMesh.C b/src/surfMesh/surfMesh/surfMesh.C
index f1ed76a7eb69f55bc7f1cf20412f46b2c558775f..b06052a3a78520524638bff4d388c3cd9af4ad82 100644
--- a/src/surfMesh/surfMesh/surfMesh.C
+++ b/src/surfMesh/surfMesh/surfMesh.C
@@ -424,9 +424,9 @@ void Foam::surfMesh::addZones
 {
     surfZoneList& zones = Allocator::storedIOZones();
 
-    forAll(zones, zoneI)
+    forAll(zones, zonei)
     {
-        zones[zoneI] = surfZone(srfZones[zoneI], zoneI);
+        zones[zonei] = surfZone(srfZones[zonei], zonei);
     }
 
     if (validate)
@@ -452,20 +452,29 @@ void Foam::surfMesh::removeFiles() const
 }
 
 
-void Foam::surfMesh::write(const fileName& name, const surfMesh& surf)
+void Foam::surfMesh::write
+(
+    const fileName& name,
+    const dictionary& options
+) const
 {
-    MeshedSurfaceProxy<face>
-    (
-        surf.points(),
-        surf.faces(),
-        surf.surfZones()
-    ).write(name);
+    write(name, name.ext(), options);
 }
 
 
-void Foam::surfMesh::write(const fileName& name)
+void Foam::surfMesh::write
+(
+    const fileName& name,
+    const word& ext,
+    const dictionary& options
+) const
 {
-    write(name, *this);
+    MeshedSurfaceProxy<face>
+    (
+        this->points(),
+        this->faces(),
+        this->surfZones()
+    ).write(name, ext, options);
 }
 
 
diff --git a/src/surfMesh/surfMesh/surfMesh.H b/src/surfMesh/surfMesh/surfMesh.H
index 4dbe151bd071162c89bcc965f3474edf461b2fd9..5933d9450fce462986e209d512c866d14ae3d921 100644
--- a/src/surfMesh/surfMesh/surfMesh.H
+++ b/src/surfMesh/surfMesh/surfMesh.H
@@ -69,7 +69,7 @@ public:
 
         //- Enumeration defining the state of the mesh after a read update.
         //  Used for post-processing applications, where the mesh
-        //  needs to update based on the files written in time directores
+        //  needs to update based on the files written in time directories
         enum readUpdateState
         {
             UNCHANGED,
@@ -157,7 +157,7 @@ public:
         //- Construct from IOobject, with alternative surface name
         explicit surfMesh
         (
-            const IOobject&,
+            const IOobject& io,
             const word& surfName = word::null
         );
 
@@ -165,16 +165,16 @@ public:
         //  surfZones are added using addZones() member function
         surfMesh
         (
-            const IOobject&,
-            const Xfer<pointField>&,
-            const Xfer<faceList>&,
+            const IOobject& io,
+            const Xfer<pointField>& pointLst,
+            const Xfer<faceList>& faceLst,
             const word& surfName = word::null
         );
 
         //- Construct copy/move from MeshedSurface
         surfMesh
         (
-            const IOobject&,
+            const IOobject& io,
             const Xfer<MeshedSurface<face>>& surf,
             const word& surfName = word::null
         );
@@ -192,7 +192,7 @@ public:
             fileName meshDir() const;
 
             //- Return the current instance directory for points
-            //  Used in the consruction of geometric mesh data dependent
+            //  Used in the construction of geometric mesh data dependent
             //  on points
             const fileName& pointsInstance() const;
 
@@ -262,7 +262,7 @@ public:
             //- Add surface zones
             void addZones
             (
-                const List<surfZone>&,
+                const surfZoneList& srfZones,
                 const bool validate = true
             );
 
@@ -294,7 +294,7 @@ public:
 
 
             //- Transfer the contents of the argument and annul the argument
-            void transfer(MeshedSurface<face>&);
+            void transfer(MeshedSurface<face>& surf);
 
 
       // Writing
@@ -311,11 +311,23 @@ public:
             const bool valid
         ) const;
 
-        //- Write to file
-        static void write(const fileName&, const surfMesh&);
 
-        //- Write to file
-        void write(const fileName&);
+        //- Write to file, choosing writer based on its extension.
+        //  Uses MeshedSurfaceProxy for writing.
+        void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const;
+
+        //- Write to file, choosing writer given extension.
+        //  Uses MeshedSurfaceProxy for writing.
+        void write
+        (
+            const fileName& name,
+            const word& ext,
+            const dictionary& options = dictionary::null
+        ) const;
 
 
       // Storage management
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
index 2340b819c0f2d429f77eb2788f16c2f2bedb07de..299e9a5333ddca126930a8774f1e2d8198bcecb0 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
@@ -62,29 +62,32 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
 
     is.getLine(line);
 
-    string version = line.substr(4);
-
-    if (version != "b")
+    // Verify version
     {
-        WarningInFunction
-            << "When reading AC3D file " << filename
-            << " read header " << line << " with version "
-            << version << endl
-            << "Only tested reading with version 'b'."
-            << " This might give problems" << endl;
+        const string version = line.substr(4);
+
+        if (version != "b")
+        {
+            WarningInFunction
+                << "When reading AC3D file " << filename
+                << " read header " << line << " with version "
+                << version << endl
+                << "Only tested reading with version 'b'."
+                << " This might give problems" << endl;
+        }
     }
 
 
-    if (!cueTo(is, "OBJECT", args) || (args != "world"))
+    if (!cueTo(is, "OBJECT", args) || args != "world")
     {
         FatalErrorInFunction
             << "Cannot find \"OBJECT world\" in file " << filename
             << exit(FatalError);
     }
 
-    // # of kids is the # of zones
+    // Number of kids is the number of zones
     args = cueToOrDie(is, "kids");
-    label nZones = parse<int>(args);
+    const label nZones = parse<int>(args);
 
     // Start of vertices for object/zones
     label vertexOffset = 0;
@@ -170,11 +173,11 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
             }
             else if (cmd == "numsurf")
             {
-                label nFaces = parse<int>(args);
+                const label nFaces = parse<int>(args);
 
                 for (label facei = 0; facei < nFaces; ++facei)
                 {
-                    static string errorMsg =
+                    const string errorMsg =
                         string(" while reading face ")
                             + Foam::name(facei) + " on zone "
                             + Foam::name(zoneI)
@@ -184,13 +187,13 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
                     cueToOrDie(is, "mat", errorMsg);
                     args = cueToOrDie(is, "refs", errorMsg);
 
-                    label nVert = parse<int>(args);
+                    const label nVert = parse<int>(args);
 
                     List<label> verts(nVert);
                     forAll(verts, vertI)
                     {
                         is.getLine(line);
-                        verts[vertI] = parse<int>(line) + vertexOffset;
+                        verts[vertI] = vertexOffset + parse<int>(line);
                     }
 
                     const labelUList& f = static_cast<const labelUList&>(verts);
@@ -221,7 +224,7 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
             else if (cmd == "kids")
             {
                 // 'kids' denotes the end of the current zone.
-                label nKids = parse<int>(args);
+                const label nKids = parse<int>(args);
 
                 if (nKids != 0)
                 {
@@ -275,26 +278,22 @@ static void writeZone
 
     os << "numvert " << patch.nPoints() << nl;
 
-    forAll(patch.localPoints(), pti)
+    for (const point& pt : patch.localPoints())
     {
-        const point& pt = patch.localPoints()[pti];
-
         os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
 
     os << "numsurf " << patch.size() << nl;
 
-    forAll(patch.localFaces(), facei)
+    for (const Face& f : patch.localFaces())
     {
-        const Face& f = patch.localFaces()[facei];
-
         os  << "SURF 0x20" << nl          // polygon
             << "mat " << zoneI << nl
             << "refs " << f.size() << nl;
 
-        forAll(f, fp)
+        for (const label verti : f)
         {
-            os << f[fp] << " 0 0" << nl;
+            os << verti << " 0 0" << nl;
         }
     }
 
@@ -306,13 +305,14 @@ template<class Face>
 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
     const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
+    const UList<Face>& faceLst = surf.surfFaces();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().size()
       ? surf.surfZones()
@@ -342,10 +342,9 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
         return;
     }
 
-    forAll(zones, zoneI)
+    label zoneIndex = 0;
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
-
         if (useFaceMap)
         {
             SubList<label> zoneMap(surf.faceMap(), zone.size(), zone.start());
@@ -355,7 +354,7 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
                 pointLst
             );
 
-            writeZone(os, patch, zone.name(), zoneI);
+            writeZone(os, patch, zone.name(), zoneIndex);
         }
         else
         {
@@ -365,8 +364,10 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
                 pointLst
             );
 
-            writeZone(os, patch, zone.name(), zoneI);
+            writeZone(os, patch, zone.name(), zoneIndex);
         }
+
+        ++zoneIndex;
     }
 }
 
@@ -375,7 +376,8 @@ template<class Face>
 void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary&
 )
 {
     OFstream os(filename);
@@ -404,10 +406,10 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
     }
 
     writeHeader(os, zoneLst);
-    forAll(zoneLst, zoneI)
-    {
-        const surfZone& zone = zoneLst[zoneI];
 
+    label zoneIndex = 0;
+    for (const surfZone& zone : zoneLst)
+    {
         SubList<label> zoneMap(faceMap, zone.size(), zone.start());
         PrimitivePatch<Face, UIndirectList, const pointField&> patch
         (
@@ -415,7 +417,9 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
             surf.points()
         );
 
-        writeZone(os, patch, zone.name(), zoneI);
+        writeZone(os, patch, zone.name(), zoneIndex);
+
+        ++zoneIndex;
     }
 }
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
index 177c2deb41e81f05bf5fedaf51c1f1e3059f912e..1617d8c3de07999775a372bfa80861c343bd0d27 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,7 +25,7 @@ Class
     Foam::fileFormats::AC3DsurfaceFormat
 
 Description
-    Provide a means of reading/writing AC3D format.
+    Read/write AC3D format.
 
     http://www.inivis.com/ac3d/man/ac3dfileformat.html
 
@@ -55,7 +55,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class AC3DsurfaceFormat Declaration
+               Class fileFormats::AC3DsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -78,49 +78,45 @@ public:
     // Constructors
 
         //- Construct from file name
-        AC3DsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new AC3DsurfaceFormat<Face>(name)
-            );
-        }
+        AC3DsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~AC3DsurfaceFormat()
-    {}
+    virtual ~AC3DsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface, the output is always sorted by zones.
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
index 61081d176ed08bf278a075395862a8d1b12e23c4..8c8571f14587fc59587010192c55ef995a699fd8 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
@@ -28,6 +28,22 @@ License
 #include "IFstream.H"
 #include "StringStream.H"
 
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+// Define 8 standard colours as r,g,b components
+static float colourMap[] =
+{
+    1, 1, 1,
+    1, 0, 0,
+    0, 1, 0,
+    0, 0, 1,
+    1, 1, 0,
+    0, 1, 1,
+    1, 0, 1,
+    0.5, 0.5, 1
+};
+
+
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
 bool Foam::fileFormats::AC3DsurfaceFormatCore::readCmd
@@ -42,9 +58,9 @@ bool Foam::fileFormats::AC3DsurfaceFormatCore::readCmd
         string line;
         is.getLine(line);
 
-        string::size_type space = line.find(' ');
+        const auto space = line.find(' ');
 
-        if (space != string::npos)
+        if (space && space != string::npos)
         {
             cmd  = line.substr(0, space);
             args = line.substr(space+1);
@@ -52,12 +68,11 @@ bool Foam::fileFormats::AC3DsurfaceFormatCore::readCmd
             return true;
         }
     }
+
     return false;
 }
 
 
-// Read up to line starting with cmd. Sets args to rest of line.
-// Returns true if found, false if stream is not good anymore.
 bool Foam::fileFormats::AC3DsurfaceFormatCore::cueTo
 (
     IFstream& is,
@@ -70,23 +85,20 @@ bool Foam::fileFormats::AC3DsurfaceFormatCore::cueTo
         string line;
         is.getLine(line);
 
-        string::size_type space = line.find(' ');
+        const auto space = line.find(' ');
 
-        if (space != string::npos)
+        if (space && space != string::npos && cmd == line.substr(0, space))
         {
-            if (line.substr(0, space) == cmd)
-            {
-                args = line.substr(space+1);
+            args = line.substr(space+1);
 
-                return true;
-            }
+            return true;
         }
     }
+
     return false;
 }
 
 
-// Similar to cueTo(), but throws error if cmd not found
 Foam::string Foam::fileFormats::AC3DsurfaceFormatCore::cueToOrDie
 (
     IFstream& is,
@@ -110,35 +122,22 @@ Foam::string Foam::fileFormats::AC3DsurfaceFormatCore::cueToOrDie
 void Foam::fileFormats::AC3DsurfaceFormatCore::writeHeader
 (
     Ostream& os,
-    const UList<surfZone>& zoneLst
+    const UList<surfZone>& zones
 )
 {
     // Write with zones as separate objects under "world" object.
     // Header is taken over from sample file.
     // Defines separate materials for all zones. Recycle colours.
 
-    // Define 8 standard colours as r,g,b components
-    static scalar colourMap[] =
-    {
-        1, 1, 1,
-        1, 0, 0,
-        0, 1, 0,
-        0, 0, 1,
-        1, 1, 0,
-        0, 1, 1,
-        1, 0, 1,
-        0.5, 0.5, 1
-    };
-
     // Write header. Define materials.
     os  << "AC3Db" << nl;
 
-    forAll(zoneLst, zoneI)
+    forAll(zones, zonei)
     {
-        label colourI = zoneI % 8;
-        label colourCompI = 3 * colourI;
+        const label colourI = zonei % 8;
+        const label colourCompI = 3 * colourI;
 
-        os  << "MATERIAL \"" << zoneLst[zoneI].name() << "Mat\" rgb "
+        os  << "MATERIAL \"" << zones[zonei].name() << "Mat\" rgb "
             << colourMap[colourCompI] << ' ' << colourMap[colourCompI+1]
             << ' ' << colourMap[colourCompI+2]
             << "  amb 0.2 0.2 0.2  emis 0 0 0  spec 0.5 0.5 0.5  shi 10"
@@ -147,7 +146,7 @@ void Foam::fileFormats::AC3DsurfaceFormatCore::writeHeader
     }
 
     os  << "OBJECT world" << nl
-        << "kids " << zoneLst.size() << endl;
+        << "kids " << zones.size() << endl;
 }
 
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
index 6054cb804fccee553e48de60635def2222b140b6..b2d54c704c165602d0c375f676ce89639ef805a7 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
@@ -36,8 +36,7 @@ SourceFiles
 #define AC3DsurfaceFormatCore_H
 
 #include "Fstream.H"
-#include "Ostream.H"
-#include "MeshedSurface.H"
+#include "surfZone.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -47,27 +46,32 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                    Class AC3DsurfaceFormatCore Declaration
+             Class fileFormats::AC3DsurfaceFormatCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class AC3DsurfaceFormatCore
 {
 protected:
 
-    // Protected Member Functions
+    // Protected Static Member Functions
 
         //- Read a type via IStringStream
         template<class Type>
-        static Type parse(const string&);
+        static Type parse(const string& str);
 
         //- Read cmd, args from IFstream
-        static bool readCmd(IFstream&, string& cmd, string& args);
-
-        //- Cue up to cmd, reading args
+        //  The cmd is the content up to the first space, args is the balance
+        //  of the line (after the space).
+        //  \return if the command was read
+        static bool readCmd(IFstream& is, string& cmd, string& args);
+
+        //- Read up to a line starting with cmd. Sets args to rest of line.
+        //
+        //  \return true if found, false if stream is not good anymore.
         static bool cueTo(IFstream&, const string& cmd, string& args);
 
-        //- Cue up to cmd, reading args or exit with a FatalError
-        //  returns the command args
+        //- Like cueTo(), but FatalError if not found.
+        //  \return the command args on success
         static string cueToOrDie
         (
             IFstream&,
@@ -75,8 +79,8 @@ protected:
             const string& errorMsg=string::null
         );
 
-        //- Write header with materials
-        static void writeHeader(Ostream&, const UList<surfZone>&);
+        //- Write header with materials for each zone
+        static void writeHeader(Ostream& os, const UList<surfZone>& zones);
 };
 
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCoreTemplates.C b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCoreTemplates.C
index d55d89e8a3040d4bd4f7392435f37d082fc41044..0e91d4efa54b587fa5acd8cdedcabdb49feafbce 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCoreTemplates.C
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCoreTemplates.C
@@ -29,12 +29,13 @@ License
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 template<class Type>
-Type Foam::fileFormats::AC3DsurfaceFormatCore::parse(const string& s)
+Type Foam::fileFormats::AC3DsurfaceFormatCore::parse(const string& str)
 {
-    IStringStream ss(s);
+    IStringStream is(str);
 
     Type t;
-    ss >> t;
+    is >> t;
+
     return t;
 }
 
diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
index 43eecf8ae56259b5f9f79194d880ee70f424f1f3..b834b4ae5f10f4c861743c5e76583915551cf56a 100644
--- a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -34,7 +34,7 @@ inline static void newline(Foam::OSstream& os)
 {
     if (os.format() == Foam::IOstream::ASCII)
     {
-        os  << Foam::endl;
+        os  << '\n';
     }
 }
 
@@ -61,9 +61,9 @@ inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeShell
         if (f.size() == 3 || f.size() == 4)
         {
             putFireLabel(os, f.size());
-            forAll(f, fp)
+            for (const label verti : f)
             {
-                putFireLabel(os, f[fp]);
+                putFireLabel(os, verti);
             }
         }
         else
@@ -72,7 +72,7 @@ inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeShell
             // better triangulation should have been done before
             for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
             {
-                label fp2 = f.fcIndex(fp1);
+                const label fp2 = f.fcIndex(fp1);
 
                 putFireLabel(os, 3);
                 putFireLabel(os, f[0]);
@@ -87,9 +87,9 @@ inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeShell
         if (f.size() == 3 || f.size() == 4)
         {
             os  << ' ' << f.size();
-            forAll(f, fp)
+            for (const label verti : f)
             {
-                os  << ' ' << f[fp];
+                os  << ' ' << verti;
             }
             os  << nl;
         }
@@ -97,7 +97,7 @@ inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeShell
         {
             for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
             {
-                label fp2 = f.fcIndex(fp1);
+                const label fp2 = f.fcIndex(fp1);
                 os  << ' ' << 3 << ' '
                     << f[0] << ' ' << f[fp1] << ' ' << f[fp2]
                     << nl;
@@ -164,9 +164,9 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
             << exit(FatalError);
     }
 
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst = surf.surfFaces();
+    const UList<label>& faceMap = surf.faceMap();
 
     // for no zones, suppress the group name
     const List<surfZone>& zones =
@@ -222,10 +222,10 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
     putFireLabel(os, pointLst.size());
     newline(os);
 
-    forAll(pointLst, ptI)
+    for (const point& pt : pointLst)
     {
         // scaling is normally 1
-        putFirePoint(os, pointLst[ptI]);
+        putFirePoint(os, pt);
     }
     newline(os); // readability
 
@@ -236,20 +236,20 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
         newline(os);
 
         label faceIndex = 0;
-        forAll(zones, zoneI)
+        for (const surfZone& zone : zones)
         {
-            const surfZone& zone = zones[zoneI];
+            const label nLocalFaces = zone.size();
 
             if (useFaceMap)
             {
-                forAll(zone, localFaceI)
+                for (label i=0; i<nLocalFaces; ++i)
                 {
                     writeShell(os, faceLst[faceMap[faceIndex++]]);
                 }
             }
             else
             {
-                forAll(zone, localFaceI)
+                for (label i=0; i<nLocalFaces; ++i)
                 {
                     writeShell(os, faceLst[faceIndex++]);
                 }
@@ -266,20 +266,20 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
         newline(os);
 
         label faceIndex = 0;
-        forAll(zones, zoneI)
+        for (const surfZone& zone : zones)
         {
-            const surfZone& zone = zones[zoneI];
+            const label nLocalFaces = zone.size();
 
             if (useFaceMap)
             {
-                forAll(zone, localFaceI)
+                for (label i=0; i<nLocalFaces; ++i)
                 {
                     writeType(os, faceLst[faceMap[faceIndex++]]);
                 }
             }
             else
             {
-                forAll(zone, localFaceI)
+                for (label i=0; i<nLocalFaces; ++i)
                 {
                     writeType(os, faceLst[faceIndex++]);
                 }
@@ -316,9 +316,9 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
 template<class Face>
 void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
 (
+    bool compress,
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf,
-    bool compress
+    const MeshedSurfaceProxy<Face>& surf
 )
 {
     autoPtr<OFstream> osPtr
@@ -361,10 +361,11 @@ template<class Face>
 void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    write(filename, surf, false);
+    write(false, filename, surf);
 }
 
 
@@ -372,10 +373,11 @@ template<class Face>
 void Foam::fileFormats::FLMAZsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    FLMAsurfaceFormat<Face>::write(filename, surf, true);
+    FLMAsurfaceFormat<Face>::write(true, filename, surf);
 }
 
 
diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H
index 1af5a3f3972ac8aa1493013dde6dfb28829af47f..d4acfc6b7f8935b73c064b8fc7b938e8f61a2f0c 100644
--- a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -47,7 +47,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class FLMAsurfaceFormat Declaration
+               Class fileFormats::FLMAsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -58,8 +58,8 @@ class FLMAsurfaceFormat
 {
     // Private Member Functions
 
-        static inline void writeShell(OSstream&, const Face&);
-        static inline void writeType(OSstream&, const Face&);
+        static inline void writeShell(OSstream& os, const Face& f);
+        static inline void writeType(OSstream& os, const Face& f);
 
         //- Disallow default bitwise copy construct
         FLMAsurfaceFormat(const FLMAsurfaceFormat<Face>&) = delete;
@@ -75,17 +75,17 @@ protected:
         //- Write surface mesh components by proxy
         static void write
         (
-            OSstream&,
-            const MeshedSurfaceProxy<Face>&
+            OSstream& os,
+            const MeshedSurfaceProxy<Face>& surf
         );
 
 
         //- Write surface mesh components by proxy with/without compression
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&,
-            bool compress
+            bool compress,
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf
         );
 
 
@@ -94,28 +94,34 @@ public:
     // Constructors
 
         //- Construct null
-        FLMAsurfaceFormat()
-        {}
+        FLMAsurfaceFormat() = default;
 
 
     //- Destructor
-    virtual ~FLMAsurfaceFormat()
-    {}
+    virtual ~FLMAsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Write flma file
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 
 };
@@ -144,28 +150,34 @@ public:
     // Constructors
 
         //- Construct null
-        FLMAZsurfaceFormat()
-        {}
+        FLMAZsurfaceFormat() = default;
 
 
     //- Destructor
-    virtual ~FLMAZsurfaceFormat()
-    {}
+    virtual ~FLMAZsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Write flmaz file
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 
 };
diff --git a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.C b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.C
index e0cbfe401c3d04bd946976dba9c7ea6cf88f19dc..352babafbb5adcffe8f5639c57bd7e912eec49db 100644
--- a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.C
@@ -30,6 +30,40 @@ License
 #include "StringStream.H"
 #include "faceTraits.H"
 
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Face>
+bool Foam::fileFormats::GTSsurfaceFormat<Face>::checkIfTriangulated
+(
+    const UList<Face>& faceLst
+)
+{
+    label nNonTris = 0;
+
+    if (!faceTraits<Face>::isTri())
+    {
+        for (const auto& f : faceLst)
+        {
+            if (f.size() != 3)
+            {
+                ++nNonTris;
+            }
+        }
+    }
+
+    if (nNonTris)
+    {
+        FatalErrorInFunction
+            << "Surface has " << nNonTris << "/" << faceLst.size()
+            << " non-triangulated faces - not writing!" << endl;
+    }
+
+    return nNonTris == 0;
+}
+
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Face>
@@ -96,7 +130,7 @@ bool Foam::fileFormats::GTSsurfaceFormat<Face>::read
         pointLst[pointi] = point(x, y, z);
     }
 
-    // Read edges (Foam indexing)
+    // Read edges (OpenFOAM indexing)
     edgeList edges(nEdges);
     forAll(edges, edgei)
     {
@@ -159,10 +193,10 @@ bool Foam::fileFormats::GTSsurfaceFormat<Face>::read
                 << exit(FatalError);
         }
 
-        label e0Far = e0.otherVertex(common01);
-        label e1Far = e1.otherVertex(common01);
+        const label e0Far = e0.otherVertex(common01);
+        const label e1Far = e1.otherVertex(common01);
 
-        label common12 = e1.commonVertex(e2);
+        const label common12 = e1.commonVertex(e2);
         if (common12 == -1)
         {
             FatalErrorInFunction
@@ -172,7 +206,7 @@ bool Foam::fileFormats::GTSsurfaceFormat<Face>::read
                 << "    edge2:" << e2
                 << exit(FatalError);
         }
-        label e2Far = e2.otherVertex(common12);
+        const label e2Far = e2.otherVertex(common12);
 
         // Does edge2 sit between edge1 and 0?
         if (common12 != e1Far || e2Far != e0Far)
@@ -212,41 +246,21 @@ template<class Face>
 void Foam::fileFormats::GTSsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurface<Face>& surf
+    const MeshedSurface<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>& faceLst  = surf.surfFaces();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>& faceLst  = surf.surfFaces();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().size()
       ? surf.surfZones()
       : surfaceFormatsCore::oneZone(faceLst)
     );
 
-    // check if output triangulation would be required
-    // It is too annoying to triangulate on-the-fly
-    // just issue a warning and get out
-    if (!faceTraits<Face>::isTri())
-    {
-        label nNonTris = 0;
-        forAll(faceLst, facei)
-        {
-            if (faceLst[facei].size() != 3)
-            {
-                ++nNonTris;
-            }
-        }
-
-        if (nNonTris)
-        {
-            FatalErrorInFunction
-                << "Surface has " << nNonTris << "/" << faceLst.size()
-                << " non-triangulated faces - not writing!" << endl;
-            return;
-        }
-    }
+    checkIfTriangulated(faceLst);
 
     OFstream os(filename);
     if (!os.good())
@@ -270,14 +284,12 @@ void Foam::fileFormats::GTSsurfaceFormat<Face>::write
 
     os  << "# nPoints  nEdges  nTriangles" << nl
         << pointLst.size() << ' ' << surf.nEdges() << ' '
-        << surf.size() << endl;
+        << surf.size() << nl;
 
 
     // Write vertex coords
-    forAll(pointLst, pointi)
+    for (const point& pt : pointLst)
     {
-        const point& pt = pointLst[pointi];
-
         os  << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
 
@@ -287,29 +299,32 @@ void Foam::fileFormats::GTSsurfaceFormat<Face>::write
     const edgeList& es = surf.edges();
     const labelList& meshPts = surf.meshPoints();
 
-    forAll(es, edgei)
+    for (const edge& e : es)
     {
-        os  << meshPts[es[edgei].start()] + 1 << ' '
-            << meshPts[es[edgei].end()] + 1 << endl;
+        os  << meshPts[e.start()] + 1 << ' '
+            << meshPts[e.end()] + 1 << nl;
     }
 
     // Write faces in terms of edges.
     const labelListList& faceEs = surf.faceEdges();
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    label zoneIndex = 0;
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
-        forAll(zone, localFacei)
+        for (label i=0; i<nLocalFaces; ++i)
         {
             const labelList& fEdges = faceEs[faceIndex++];
 
             os  << fEdges[0] + 1 << ' '
                 << fEdges[1] + 1 << ' '
                 << fEdges[2] + 1 << ' '
-                << zoneI << endl;
+                << zoneIndex << nl;
         }
+
+        ++zoneIndex;
     }
 }
 
@@ -318,36 +333,16 @@ template<class Face>
 void Foam::fileFormats::GTSsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst   = surf.points();
-    const List<Face>& faceLst    = surf.surfFaces();
-    const List<label>& zoneIds   = surf.zoneIds();
-    const List<surfZoneIdentifier>& zoneToc = surf.zoneToc();
-
-    // check if output triangulation would be required
-    // It is too annoying to triangulate on-the-fly
-    // just issue a warning and get out
-    if (!faceTraits<Face>::isTri())
-    {
-        label nNonTris = 0;
-        forAll(faceLst, facei)
-        {
-            if (faceLst[facei].size() != 3)
-            {
-                ++nNonTris;
-            }
-        }
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>& faceLst = surf.surfFaces();
+    const UList<label>& zoneIds = surf.zoneIds();
+    const UList<surfZoneIdentifier>& zoneToc = surf.zoneToc();
 
-        if (nNonTris)
-        {
-            FatalErrorInFunction
-                << "Surface has " << nNonTris << "/" << faceLst.size()
-                << " non-triangulated faces - not writing!" << endl;
-            return;
-        }
-    }
+    checkIfTriangulated(faceLst);
 
     OFstream os(filename);
     if (!os.good())
@@ -367,20 +362,18 @@ void Foam::fileFormats::GTSsurfaceFormat<Face>::write
         os  << "#     " << zoneI << "    "
             << zoneToc[zoneI].name() << nl;
     }
-    os  << "#" << endl;
+    os  << "#" << nl;
 
 
     os  << "# nPoints  nEdges  nTriangles" << nl
         << pointLst.size() << ' ' << surf.nEdges() << ' '
-        << surf.size() << endl;
+        << surf.size() << nl;
 
 
     // Write vertex coords
-    forAll(pointLst, pointi)
+    for (const point& pt : pointLst)
     {
-        os  << pointLst[pointi].x() << ' '
-            << pointLst[pointi].y() << ' '
-            << pointLst[pointi].z() << endl;
+        os  << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
 
 
@@ -389,13 +382,12 @@ void Foam::fileFormats::GTSsurfaceFormat<Face>::write
     const edgeList& es = surf.edges();
     const labelList& meshPts = surf.meshPoints();
 
-    forAll(es, edgeI)
+    for (const edge& e : es)
     {
-        os  << meshPts[es[edgeI].start()] + 1 << ' '
-            << meshPts[es[edgeI].end()] + 1 << endl;
+        os  << meshPts[e.start()] + 1 << ' '
+            << meshPts[e.end()] + 1 << nl;
     }
 
-
     // Write faces in terms of edges.
     const labelListList& faceEs = surf.faceEdges();
 
@@ -406,7 +398,7 @@ void Foam::fileFormats::GTSsurfaceFormat<Face>::write
         os  << fEdges[0] + 1 << ' '
             << fEdges[1] + 1 << ' '
             << fEdges[2] + 1 << ' '
-            << zoneIds[facei] << endl;
+            << zoneIds[facei] << nl;
     }
 }
 
diff --git a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
index c39c005af511fd384220acdb7485c7f2bf120a36..701278432b0f4fbfcb76c035af591e6352fe1ee4 100644
--- a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,7 +25,8 @@ Class
     Foam::fileFormats::GTSsurfaceFormat
 
 Description
-    Provide a means of reading/writing GTS format.
+    Read/write GTS format.
+
     The output is never sorted by zone and is only written if it consists
     entirely of triangles.
 
@@ -49,7 +50,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class GTSsurfaceFormat Declaration
+                Class fileFormats::GTSsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -59,6 +60,10 @@ class GTSsurfaceFormat
 {
     // Private Member Functions
 
+        //- Check and raise FatalError if output is not triangulated
+        //  Triangulatinng on-the-fly is otherwise too annoying
+        static bool checkIfTriangulated(const UList<Face>& faceLst);
+
         //- Disallow default bitwise copy construct
         GTSsurfaceFormat(const GTSsurfaceFormat<Face>&) = delete;
 
@@ -71,49 +76,45 @@ public:
     // Constructors
 
         //- Construct from file name
-        GTSsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<UnsortedMeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<UnsortedMeshedSurface<Face>>
-            (
-                new GTSsurfaceFormat<Face>(name)
-            );
-        }
+        GTSsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~GTSsurfaceFormat()
-    {}
+    virtual ~GTSsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write MeshedSurface
         static void write
         (
-            const fileName&,
-            const MeshedSurface<Face>&
+            const fileName& filename,
+            const MeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface, the output remains unsorted
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, *this);
+            write(name, *this, options);
         }
 };
 
diff --git a/src/surfMesh/triSurface/interfaces/GTS/writeGTS.C b/src/surfMesh/surfaceFormats/gts/triSurfaceGTSformat.C
similarity index 69%
rename from src/surfMesh/triSurface/interfaces/GTS/writeGTS.C
rename to src/surfMesh/surfaceFormats/gts/triSurfaceGTSformat.C
index d2d70282f2070579b11efd5867516f0266180b17..01bc0d2a0d14ff5ff4de659b37cfe449c38fed15 100644
--- a/src/surfMesh/triSurface/interfaces/GTS/writeGTS.C
+++ b/src/surfMesh/surfaceFormats/gts/triSurfaceGTSformat.C
@@ -24,45 +24,48 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "triSurface.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
+#include "OFstream.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-void triSurface::writeGTS(const bool writeSorted, Ostream& os) const
+void Foam::triSurface::writeGTS
+(
+    const fileName& filename,
+    const bool sort
+) const
 {
+    OFstream os(filename);
+    if (!os.good())
+    {
+        FatalErrorInFunction
+            << "Cannot open file for writing " << filename
+            << exit(FatalError);
+    }
+
     // Write header
     os  << "# GTS file" << endl
         << "# Regions:" << endl;
 
     labelList faceMap;
-
     surfacePatchList patches(calcPatches(faceMap));
 
     // Print patch names as comment
     forAll(patches, patchi)
     {
         os  << "#     " << patchi << "    "
-            << patches[patchi].name() << endl;
+            << patches[patchi].name() << nl;
     }
-    os  << "#" << endl;
-
+    os  << "#" << nl;
 
-    const pointField& ps = points();
+    const pointField& pts = points();
 
-    os  << "# nPoints  nEdges  nTriangles" << endl
-        << ps.size() << ' ' << nEdges() << ' ' << size() << endl;
+    os  << "# nPoints  nEdges  nTriangles" << nl
+        << pts.size() << ' ' << nEdges() << ' ' << size() << nl;
 
     // Write vertex coords
-
-    forAll(ps, pointi)
+    for (const point& pt : pts)
     {
-        os  << ps[pointi].x() << ' '
-            << ps[pointi].y() << ' '
-            << ps[pointi].z() << endl;
+        os  << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
 
     // Write edges.
@@ -70,26 +73,23 @@ void triSurface::writeGTS(const bool writeSorted, Ostream& os) const
     const edgeList& es = edges();
     const labelList& meshPts = meshPoints();
 
-    forAll(es, edgei)
+    for (const edge& e : es)
     {
-        os  << meshPts[es[edgei].start()] + 1 << ' '
-            << meshPts[es[edgei].end()] + 1 << endl;
+        os  << meshPts[e.start()] + 1 << ' '
+            << meshPts[e.end()] + 1 << nl;
     }
 
     // Write faces in terms of edges.
     const labelListList& faceEs = faceEdges();
 
-    if (writeSorted)
+    if (sort)
     {
         label faceIndex = 0;
-        forAll(patches, patchi)
+        for (const surfacePatch& p : patches)
         {
-            for
-            (
-                label patchFacei = 0;
-                patchFacei < patches[patchi].size();
-                patchFacei++
-            )
+            const label nLocalFaces = p.size();
+
+            for (label i = 0; i<nLocalFaces; ++i)
             {
                 const label facei = faceMap[faceIndex++];
 
@@ -98,7 +98,7 @@ void triSurface::writeGTS(const bool writeSorted, Ostream& os) const
                 os  << fEdges[0] + 1 << ' '
                     << fEdges[1] + 1 << ' '
                     << fEdges[2] + 1 << ' '
-                    << (*this)[facei].region() << endl;
+                    << (*this)[facei].region() << nl;
             }
         }
     }
@@ -111,14 +111,10 @@ void triSurface::writeGTS(const bool writeSorted, Ostream& os) const
             os  << fEdges[0] + 1 << ' '
                 << fEdges[1] + 1 << ' '
                 << fEdges[2] + 1 << ' '
-                << (*this)[facei].region() << endl;
+                << (*this)[facei].region() << nl;
         }
     }
 }
 
 
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
 // ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
index a7ec90fc4d5b7e36681ec05c9afced9492d066ae..03e66e3c75f8d55db3b8e7732a9d041a5bf8a09e 100644
--- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
@@ -25,9 +25,62 @@ License
 
 #include "NASsurfaceFormat.H"
 #include "IFstream.H"
-#include "StringStream.H"
+#include "IOmanip.H"
 #include "faceTraits.H"
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Face>
+inline Foam::label Foam::fileFormats::NASsurfaceFormat<Face>::writeShell
+(
+    Ostream& os,
+    const Face& f,
+    const label groupId,
+    label elementId
+)
+{
+    const label n = f.size();
+
+    if (n == 3)
+    {
+        os  << "CTRIA3" << ','
+            << ++elementId << ','
+            << (groupId + 1) << ','
+            << (f[0] + 1) << ','
+            << (f[1] + 1) << ','
+            << (f[2] + 1) << nl;
+    }
+    else if (n == 4)
+    {
+        os  << "CTRIA3" << ','
+            << ++elementId << ','
+            << (groupId + 1) << ','
+            << (f[0] + 1) << ','
+            << (f[1] + 1) << ','
+            << (f[2] + 1) << ','
+            << (f[3] + 1) << nl;
+    }
+    else
+    {
+        // simple triangulation about f[0].
+        // better triangulation should have been done before
+        for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
+        {
+            const label fp2 = f.fcIndex(fp1);
+
+            os  << "CTRIA3" << ','
+                << ++elementId << ','
+                << (groupId + 1) << ','
+                << (f[0] + 1) << ','
+                << (f[fp1] + 1) << ','
+                << (f[fp2] + 1) << nl;
+        }
+    }
+
+    return elementId;
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Face>
@@ -64,7 +117,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
     DynamicList<Face>   dynFaces;
     DynamicList<label>  dynZones;
     DynamicList<label>  dynSizes;
-    Map<label>          lookup;
+    Map<label>          zoneLookup;
 
     // assume the types are not intermixed
     // leave faces that didn't have a group in 0
@@ -86,10 +139,13 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 
     while (is.good())
     {
+        string::size_type linei = 0;  // parsing position within current line
         string line;
         is.getLine(line);
 
         // ANSA extension
+        // line 1: $ANSA_NAME;<int>;<word>;
+        // line 2: $partName
         if (line.startsWith("$ANSA_NAME"))
         {
             const auto sem0 = line.find(';', 0);
@@ -98,9 +154,9 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 
             if
             (
-                sem0 != string::npos
-             && sem1 != string::npos
-             && sem2 != string::npos
+                sem0 != std::string::npos
+             && sem1 != std::string::npos
+             && sem2 != std::string::npos
             )
             {
                 ansaId = readLabel(line.substr(sem0+1, sem1-sem0-1));
@@ -108,7 +164,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 
                 string rawName;
                 is.getLine(rawName);
-                rawName.removeEnd("\r");
+                rawName.removeEnd("\r");  // Possible CR-NL
                 ansaName = word::validate(rawName.substr(1));
 
                 // Info<< "ANSA tag for NastranID:" << ansaId
@@ -118,26 +174,22 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
         }
 
 
-        // Hypermesh extension
+        // HYPERMESH extension
         // $HMNAME COMP                   1"partName"
         if (line.startsWith("$HMNAME COMP") && line.find('"') != string::npos)
         {
             label groupId = readLabel(line.substr(16, 16));
-            IStringStream lineStream(line.substr(32));
 
-            string rawName;
-            lineStream >> rawName;
+            // word::validate automatically removes quotes too
+            const word groupName = word::validate(line.substr(32));
 
-            const word groupName = word::validate(rawName);
             nameLookup.insert(groupId, groupName);
             // Info<< "group " << groupId << " => " << groupName << endl;
         }
 
-
-        // Skip empty or comment
         if (line.empty() || line[0] == '$')
         {
-            continue;
+            continue; // Skip empty or comment
         }
 
         // Check if character 72 is continuation
@@ -162,22 +214,20 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
             }
         }
 
-
-        // Read first word
-        IStringStream lineStream(line);
-        word cmd;
-        lineStream >> cmd;
+        // First word (column 0-8)
+        const word cmd(word::validate(nextNasField(line, linei, 8)));
 
         if (cmd == "CTRIA3")
         {
-            label groupId = readLabel(line.substr(16,8));
-            label a = readLabel(line.substr(24,8));
-            label b = readLabel(line.substr(32,8));
-            label c = readLabel(line.substr(40,8));
-
-            // Convert groupID into zoneId
-            Map<label>::const_iterator fnd = lookup.find(groupId);
-            if (fnd != lookup.end())
+            (void) nextNasField(line, linei, 8); // 8-16
+            label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
+            label a = readLabel(nextNasField(line, linei, 8)); // 24-32
+            label b = readLabel(nextNasField(line, linei, 8)); // 32-40
+            label c = readLabel(nextNasField(line, linei, 8)); // 40-48
+
+            // Convert groupId into zoneId
+            const auto fnd = zoneLookup.cfind(groupId);
+            if (fnd.found())
             {
                 if (zoneI != fnd())
                 {
@@ -189,7 +239,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
             else
             {
                 zoneI = dynSizes.size();
-                lookup.insert(groupId, zoneI);
+                zoneLookup.insert(groupId, zoneI);
                 dynSizes.append(0);
                 // Info<< "zone" << zoneI << " => group " << groupId <<endl;
             }
@@ -200,15 +250,16 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
         }
         else if (cmd == "CQUAD4")
         {
-            label groupId = readLabel(line.substr(16,8));
-            label a = readLabel(line.substr(24,8));
-            label b = readLabel(line.substr(32,8));
-            label c = readLabel(line.substr(40,8));
-            label d = readLabel(line.substr(48,8));
+            (void) nextNasField(line, linei, 8); // 8-16
+            label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
+            label a = readLabel(nextNasField(line, linei, 8)); // 24-32
+            label b = readLabel(nextNasField(line, linei, 8)); // 32-40
+            label c = readLabel(nextNasField(line, linei, 8)); // 40-48
+            label d = readLabel(nextNasField(line, linei, 8)); // 48-56
 
             // Convert groupID into zoneId
-            Map<label>::const_iterator fnd = lookup.find(groupId);
-            if (fnd != lookup.end())
+            const auto fnd = zoneLookup.cfind(groupId);
+            if (fnd.found())
             {
                 if (zoneI != fnd())
                 {
@@ -220,7 +271,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
             else
             {
                 zoneI = dynSizes.size();
-                lookup.insert(groupId, zoneI);
+                zoneLookup.insert(groupId, zoneI);
                 dynSizes.append(0);
                 // Info<< "zone" << zoneI << " => group " << groupId <<endl;
             }
@@ -242,10 +293,11 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
         }
         else if (cmd == "GRID")
         {
-            label index = readLabel(line.substr(8,8));
-            scalar x = readNasScalar(line.substr(24, 8));
-            scalar y = readNasScalar(line.substr(32, 8));
-            scalar z = readNasScalar(line.substr(40, 8));
+            label index = readLabel(nextNasField(line, linei, 8)); // 8-16
+            (void) nextNasField(line, linei, 8); // 16-24
+            scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
+            scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
+            scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
 
             pointId.append(index);
             dynPoints.append(point(x, y, z));
@@ -258,10 +310,12 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
             // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
             // *         2.14897901E+02
 
-            label index = readLabel(line.substr(8,16));
-            scalar x = readNasScalar(line.substr(40, 16));
-            scalar y = readNasScalar(line.substr(56, 16));
+            label index = readLabel(nextNasField(line, linei, 16)); // 8-24
+            (void) nextNasField(line, linei, 16); // 24-40
+            scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
+            scalar y = readNasScalar(nextNasField(line, linei, 16)); // 56-72
 
+            linei = 0; // restart at index 0
             is.getLine(line);
             if (line[0] != '*')
             {
@@ -272,20 +326,21 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
                     << "File:" << is.name() << " line:" << is.lineNumber()
                     << exit(FatalError);
             }
-            scalar z = readNasScalar(line.substr(8, 16));
+            (void) nextNasField(line, linei, 8); // 0-8
+            scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
 
             pointId.append(index);
             dynPoints.append(point(x, y, z));
         }
         else if (cmd == "PSHELL")
         {
-            // pshell type for zone names with the Ansa extension
-            label groupId = readLabel(line.substr(8,8));
-
+            // Read shell type since group gives patchnames (ANSA extension)
+            label groupId = readLabel(nextNasField(line, linei, 8)); // 8-16
             if (groupId == ansaId && ansaType == "PSHELL")
             {
-                nameLookup.insert(ansaId, ansaName);
-                // Info<< "group " << groupId << " => " << ansaName << endl;
+                const word groupName = word::validate(ansaName);
+                nameLookup.insert(groupId, groupName);
+                // Info<< "group " << groupId << " => " << groupName << endl;
             }
         }
         else if (unhandledCmd.insert(cmd))
@@ -315,9 +370,8 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 
     // Relabel faces
     // ~~~~~~~~~~~~~
-    forAll(dynFaces, i)
+    for (Face& f : dynFaces)
     {
-        Face& f = dynFaces[i];
         forAll(f, fp)
         {
             f[fp] = mapPointId[f[fp]];
@@ -329,19 +383,19 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 
     // create default zone names, or from ANSA/Hypermesh information
     List<word> names(dynSizes.size());
-    forAllConstIter(Map<label>, lookup, iter)
+    forAllConstIters(zoneLookup, iter)
     {
-        const label zoneI  = iter();
-        const label groupI = iter.key();
+        const label groupId = iter.key();
+        const label zoneId  = iter.object();
 
-        Map<word>::const_iterator fnd = nameLookup.find(groupI);
-        if (fnd != nameLookup.end())
+        const auto fnd = nameLookup.cfind(groupId);
+        if (fnd.found())
         {
-            names[zoneI] = fnd();
+            names[zoneId] = fnd();
         }
         else
         {
-            names[zoneI] = word("zone") + ::Foam::name(zoneI);
+            names[zoneId] = word("zone") + ::Foam::name(zoneId);
         }
     }
 
@@ -353,4 +407,94 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
 }
 
 
+template<class Face>
+void Foam::fileFormats::NASsurfaceFormat<Face>::write
+(
+    const fileName& filename,
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
+)
+{
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst  = surf.surfFaces();
+    const UList<label>& faceMap  = surf.faceMap();
+
+    // for no zones, suppress the group name
+    const UList<surfZone>& zones =
+    (
+        surf.surfZones().empty()
+      ? surfaceFormatsCore::oneZone(faceLst, "")
+      : surf.surfZones()
+    );
+
+    const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
+
+    OFstream os(filename);
+    if (!os.good())
+    {
+        FatalErrorInFunction
+            << "Cannot open file for writing " << filename
+            << exit(FatalError);
+    }
+
+    // For simplicity, use fieldFormat::FREE throughout
+    fileFormats::NASCore::setPrecision(os, fieldFormat::FREE);
+
+    os  << "CEND" << nl
+        << "TITLE = " << os.name().nameLessExt() << nl;
+
+    // Print zone names as comment
+    forAll(zones, zonei)
+    {
+        // HYPERMESH extension
+        os  << "$HMNAME COMP" << setw(20) << (zonei+1)
+            << '"' << zones[zonei].name() << '"' << nl;
+    }
+
+    // Write vertex coords with 1-based point Id
+    os  << "$ GRID POINTS" << nl
+        << "BEGIN BULK" << nl;
+
+    label pointId = 0;
+    for (const point& pt : pointLst)
+    {
+        os  << "GRID" << ','
+            << ++pointId << ','
+            << 0 << ','  // global coordinate system
+            << pt.x() << ',' << pt.y() << ',' << pt.z() << nl;
+    }
+
+    os << "$ ELEMENTS" << nl;
+
+    label faceIndex = 0;
+    label zoneIndex = 0;
+    label elementId = 0;
+    for (const surfZone& zone : zones)
+    {
+        const label nLocalFaces = zone.size();
+
+        if (useFaceMap)
+        {
+            for (label i=0; i<nLocalFaces; ++i)
+            {
+                const Face& f = faceLst[faceMap[faceIndex++]];
+                elementId = writeShell(os, f, zoneIndex, elementId);
+            }
+        }
+        else
+        {
+            for (label i=0; i<nLocalFaces; ++i)
+            {
+                const Face& f = faceLst[faceIndex++];
+                elementId = writeShell(os, f, zoneIndex, elementId);
+            }
+        }
+
+        ++zoneIndex;
+    }
+
+    os << "ENDDATA" << nl;
+}
+
+
 // ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
index d6b0ed0852bfefde27081808249b5335f7383d0a..69c9240ed3651c31d3daeef843825d3caf28d150 100644
--- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -29,7 +29,7 @@ Description
 
     - Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions
       to obtain zone names.
-    - Handles Nastran short and long formats, but not free format.
+    - Handles Nastran short, long formats and comma-separated free format.
     - Properly handles the Nastran compact floating point notation: \n
     \verbatim
         GRID          28        10.20269-.030265-2.358-8
@@ -56,7 +56,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class NASsurfaceFormat Declaration
+                Class fileFormats::NASsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -67,6 +67,15 @@ class NASsurfaceFormat
 {
     // Private Member Functions
 
+        //- Output CTRIA3 or CQUAD4
+        inline static label writeShell
+        (
+            Ostream& os,
+            const Face& f,
+            const label groupId,
+            label elementId
+        );
+
         //- Disallow default bitwise copy construct
         NASsurfaceFormat(const NASsurfaceFormat<Face>&) = delete;
 
@@ -79,30 +88,38 @@ public:
     // Constructors
 
         //- Construct from file name
-        NASsurfaceFormat(const fileName&);
+        NASsurfaceFormat(const fileName& filename);
 
 
-    // Selectors
+    //- Destructor
+    virtual ~NASsurfaceFormat() = default;
 
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new NASsurfaceFormat<Face>(name)
-            );
-        }
 
+    // Static Member Functions
 
-    //- Destructor
-    virtual ~NASsurfaceFormat()
-    {}
+        //- Write surface mesh components by proxy
+        static void write
+        (
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
+        );
 
 
     // Member Functions
 
         //- Read from a file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
+
+        //- Write object file
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
+        {
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
+        }
 };
 
 
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatRunTime.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatRunTime.C
index 572a9aa9827c703a29851875d660b5b56a3d1dbd..6f77db8c67428fb673fc59fc50500255e6037f89 100644
--- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatRunTime.C
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatRunTime.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -87,6 +87,36 @@ addNamedTemplatedToRunTimeSelectionTable
     nas
 );
 
+
+// write MeshedSurfaceProxy
+addNamedTemplatedToMemberFunctionSelectionTable
+(
+    MeshedSurfaceProxy,
+    NASsurfaceFormat,
+    face,
+    write,
+    fileExtension,
+    nas
+);
+addNamedTemplatedToMemberFunctionSelectionTable
+(
+    MeshedSurfaceProxy,
+    NASsurfaceFormat,
+    triFace,
+    write,
+    fileExtension,
+    nas
+);
+addNamedTemplatedToMemberFunctionSelectionTable
+(
+    MeshedSurfaceProxy,
+    NASsurfaceFormat,
+    labelledTri,
+    write,
+    fileExtension,
+    nas
+);
+
 }
 }
 
diff --git a/src/surfMesh/surfaceFormats/obj/OBJstream.C b/src/surfMesh/surfaceFormats/obj/OBJstream.C
index 2056c51d5a8a1b8df0203fee9e86065b2bde8dcb..0dab63d16cbb14b4d8e46ae991457e742d0b2a58 100644
--- a/src/surfMesh/surfaceFormats/obj/OBJstream.C
+++ b/src/surfMesh/surfaceFormats/obj/OBJstream.C
@@ -72,12 +72,6 @@ Foam::OBJstream::OBJstream
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::OBJstream::~OBJstream()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::Ostream& Foam::OBJstream::write(const char c)
diff --git a/src/surfMesh/surfaceFormats/obj/OBJstream.H b/src/surfMesh/surfaceFormats/obj/OBJstream.H
index e5cf4227a89734bb8a9ed1b418f4467008de3a3f..c19310938a5af488ff643e68c9e4313a816aa31b 100644
--- a/src/surfMesh/surfaceFormats/obj/OBJstream.H
+++ b/src/surfMesh/surfaceFormats/obj/OBJstream.H
@@ -87,10 +87,10 @@ public:
 
 
     //- Destructor
-    ~OBJstream();
+    ~OBJstream() = default;
 
 
-    // Member functions
+    // Member Functions
 
         // Access
 
diff --git a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C
index 57376d2eaf2534a59b803bd087d71c9f1717a441..77128da7cae93b575ca3cadc634ae72c718dffb3 100644
--- a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C
@@ -146,7 +146,7 @@ bool Foam::fileFormats::OBJsurfaceFormat<Face>::read
                 }
                 else
                 {
-                    vertexSpec = line.substr(startNum, line.size() - startNum);
+                    vertexSpec = line.substr(startNum);
                 }
 
                 string::size_type slashPos = vertexSpec.find('/');
@@ -176,7 +176,7 @@ bool Foam::fileFormats::OBJsurfaceFormat<Face>::read
                 // points may be incomplete
                 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
                 {
-                    label fp2 = f.fcIndex(fp1);
+                    const label fp2 = f.fcIndex(fp1);
 
                     dynFaces.append(Face{f[0], f[fp1], f[fp2]});
                     dynZones.append(zoneI);
@@ -208,15 +208,16 @@ template<class Face>
 void Foam::fileFormats::OBJsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst  = surf.surfFaces();
+    const UList<label>& faceMap  = surf.faceMap();
 
     // for no zones, suppress the group name
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst, "")
@@ -242,41 +243,39 @@ void Foam::fileFormats::OBJsurfaceFormat<Face>::write
         << "# zones  : " << zones.size() << nl;
 
     // Print zone names as comment
-    forAll(zones, zoneI)
+    forAll(zones, zonei)
     {
-        os  << "#   " << zoneI << "  " << zones[zoneI].name()
-            << "  (nFaces: " << zones[zoneI].size() << ")" << nl;
+        os  << "#   " << zonei << "  " << zones[zonei].name()
+            << "  (nFaces: " << zones[zonei].size() << ")" << nl;
     }
 
     os  << nl
         << "# <points count=\"" << pointLst.size() << "\">" << nl;
 
     // Write vertex coords
-    forAll(pointLst, ptI)
+    for (const point& pt : pointLst)
     {
-        const point& pt = pointLst[ptI];
-
         os  << "v " << pt.x() << ' '  << pt.y() << ' '  << pt.z() << nl;
     }
 
     os  << "# </points>" << nl
         << nl
-        << "# <faces count=\"" << faceLst.size() << "\">" << endl;
+        << "# <faces count=\"" << faceLst.size() << "\">" << nl;
 
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
-
         if (zone.name().size())
         {
-            os << "g " << zone.name() << endl;
+            os << "g " << zone.name() << nl;
         }
 
+        const label nLocalFaces = zone.size();
+
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
 
@@ -285,12 +284,12 @@ void Foam::fileFormats::OBJsurfaceFormat<Face>::write
                 {
                     os << ' ' << f[fp] + 1;
                 }
-                os << endl;
+                os << nl;
             }
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
 
@@ -299,11 +298,11 @@ void Foam::fileFormats::OBJsurfaceFormat<Face>::write
                 {
                     os << ' ' << f[fp] + 1;
                 }
-                os << endl;
+                os << nl;
             }
         }
     }
-    os << "# </faces>" << endl;
+    os << "# </faces>" << nl;
 }
 
 
diff --git a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.H b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.H
index dc472070371934b3ae70a4f259a8507607fb4fd9..61529c4fdd065247f57d219bbe83653f0e710d08 100644
--- a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,7 +25,7 @@ Class
     Foam::fileFormats::OBJsurfaceFormat
 
 Description
-    Provide a means of reading/writing Alias/Wavefront OBJ format.
+    Read/write Alias/Wavefront OBJ format.
 
     Does not handle negative face indices.
 
@@ -49,7 +49,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class OBJsurfaceFormat Declaration
+                Class fileFormats::OBJsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -71,42 +71,37 @@ public:
     // Constructors
 
         //- Construct from file name
-        OBJsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new OBJsurfaceFormat<Face>(name)
-            );
-        }
+        OBJsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~OBJsurfaceFormat()
-    {}
+    virtual ~OBJsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object file
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.C b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.C
index e666faab460accf3e5c9c87ad9a41492fc6afbe4..48fbed1d43b348f4ebacc73e794be73a6eca3e04 100644
--- a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.C
@@ -143,13 +143,14 @@ template<class Face>
 void Foam::fileFormats::OFFsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
-    const List<surfZone>& zoneLst = surf.surfZones();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst  = surf.surfFaces();
+    const UList<label>& faceMap  = surf.faceMap();
+    const UList<surfZone>& zoneLst = surf.surfZones();
 
     OFstream os(filename);
     if (!os.good())
@@ -197,16 +198,18 @@ void Foam::fileFormats::OFFsurfaceFormat<Face>::write
     {
         os << "# <zone name=\"" << zoneLst[zoneI].name() << "\">" << endl;
 
+        const label nLocalFaces = zoneLst[zoneI].size();
+
         if (surf.useFaceMap())
         {
-            forAll(zoneLst[zoneI], localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
 
                 os << f.size();
-                forAll(f, fp)
+                for (const label verti : f)
                 {
-                    os << ' ' << f[fp];
+                    os << ' ' << verti;
                 }
 
                 // add optional zone information
@@ -215,14 +218,14 @@ void Foam::fileFormats::OFFsurfaceFormat<Face>::write
         }
         else
         {
-            forAll(zoneLst[zoneI], localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
 
                 os << f.size();
-                forAll(f, fp)
+                for (const label verti : f)
                 {
-                    os << ' ' << f[fp];
+                    os << ' ' << verti;
                 }
 
                 // add optional zone information
diff --git a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
index 654da0c93edc45a4d665cfb32bdd84fb87bb4b78..bfff7e1b15d588d631e00979ff617c0475049019 100644
--- a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,8 +25,7 @@ Class
     Foam::fileFormats::OFFsurfaceFormat
 
 Description
-    Provide a means of reading/writing Geomview OFF polyList format.
-
+    Read/write Geomview OFF polyList format.
 
 See also
     The <a href="http://www.geoview.org">Geoview</a>
@@ -57,7 +56,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class OFFsurfaceFormat Declaration
+                Class fileFormats::OFFsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -79,42 +78,37 @@ public:
     // Constructors
 
         //- Construct from file name
-        OFFsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new OFFsurfaceFormat(name)
-            );
-        }
+        OFFsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~OFFsurfaceFormat()
-    {}
+    virtual ~OFFsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.C b/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.C
index 01640aa5ec87665adb28c1b2dcfedada0ab91b1e..5f54451022eea533e2e53b29f38bee8ffc02c762 100644
--- a/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,27 +27,21 @@ License
 #include "clock.H"
 #include "OFstream.H"
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-template<class Face>
-Foam::fileFormats::SMESHsurfaceFormat<Face>::SMESHsurfaceFormat()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Face>
 void Foam::fileFormats::SMESHsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst  = surf.surfFaces();
+    const UList<label>& faceMap  = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst)
@@ -71,11 +65,11 @@ void Foam::fileFormats::SMESHsurfaceFormat<Face>::write
         << pointLst.size() << " 3" << nl;    // 3: dimensions
 
     // Write vertex coords
-    forAll(pointLst, ptI)
+    forAll(pointLst, pti)
     {
-        const point& pt = pointLst[ptI];
+        const point& pt = pointLst[pti];
 
-        os  << ptI << ' ' << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
+        os  << pti << ' ' << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
     os  << "# </points>" << nl
         << nl
@@ -85,38 +79,41 @@ void Foam::fileFormats::SMESHsurfaceFormat<Face>::write
 
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    label zoneIndex = 0;
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
 
                 os << f.size();
-                forAll(f, fp)
+                for (const label verti : f)
                 {
-                    os << ' ' << f[fp];
+                    os << ' ' << verti;
                 }
-                os << ' ' << zoneI << endl;
+                os << ' ' << zoneIndex << nl;
             }
         }
         else
         {
-            forAll(zones[zoneI], localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
 
                 os << f.size();
-                forAll(f, fp)
+                for (const label verti : f)
                 {
-                    os << ' ' << f[fp];
+                    os << ' ' << verti;
                 }
-                os << ' ' << zoneI << endl;
+                os << ' ' << zoneIndex << nl;
             }
         }
+
+        ++zoneIndex;
     }
 
     // write tail
diff --git a/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.H b/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.H
index 0a4e315f3ebcdc09382b889e6f6db3d3a4ed9740..18b40854b32dc4f42381601a3b86e36395451e9a 100644
--- a/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/smesh/SMESHsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,7 +25,7 @@ Class
     Foam::fileFormats::SMESHsurfaceFormat
 
 Description
-    Provide a means of writing tetgen SMESH format.
+    Write tetgen SMESH format.
 
     Tetgen http://tetgen.berlios.de
 
@@ -53,7 +53,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                     Class SMESHsurfaceFormat Declaration
+               Class fileFormats::SMESHsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -75,27 +75,34 @@ public:
     // Constructors
 
         //- Construct null
-        SMESHsurfaceFormat();
+        SMESHsurfaceFormat() = default;
 
 
     //- Destructor
-    virtual ~SMESHsurfaceFormat()
-    {}
+    virtual ~SMESHsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C
index 36e3f2b0a0bc6abe4831c5a4df54aa3f4cb8e7d5..b9f3f92afaabd0c24ee6ca9514567feba7373679 100644
--- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C
@@ -47,16 +47,16 @@ inline void Foam::fileFormats::STARCDsurfaceFormat<Face>::writeShell
     // primitives have <= 8 vertices, but prevent overrun anyhow
     // indent following lines for ease of reading
     label count = 0;
-    forAll(f, fp)
+    for (const label verti : f)
     {
         if ((count % 8) == 0)
         {
             os  << nl << "  " << cellId;
         }
-        os  << ' ' << f[fp] + 1;
-        count++;
+        os  << ' ' << verti + 1;
+        ++count;
     }
-    os  << endl;
+    os  << nl;
 }
 
 
@@ -160,8 +160,8 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read
         if (typeId == starcdShellType)
         {
             // Convert groupID into zoneID
-            Map<label>::const_iterator fnd = lookup.find(cellTableId);
-            if (fnd != lookup.end())
+            const auto fnd = lookup.cfind(cellTableId);
+            if (fnd.found())
             {
                 if (zoneI != fnd())
                 {
@@ -175,20 +175,19 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read
                 zoneI = dynSizes.size();
                 lookup.insert(cellTableId, zoneI);
 
-                Map<word>::const_iterator tableNameIter =
-                    cellTableLookup.find(cellTableId);
+                const auto tableNameIter = cellTableLookup.cfind(cellTableId);
 
-                if (tableNameIter == cellTableLookup.end())
+                if (tableNameIter.found())
+                {
+                    dynNames.append(tableNameIter());
+                }
+                else
                 {
                     dynNames.append
                     (
                         word("cellTable_") + ::Foam::name(cellTableId)
                     );
                 }
-                else
-                {
-                    dynNames.append(tableNameIter());
-                }
 
                 dynSizes.append(0);
             }
@@ -203,10 +202,10 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read
                 label nTri = 0;
                 f.triangles(this->points(), nTri, trias);
 
-                forAll(trias, facei)
+                for (const face& tri : trias)
                 {
                     // a triangular 'face', convert to 'triFace' etc
-                    dynFaces.append(Face(trias[facei]));
+                    dynFaces.append(Face(tri));
                     dynZones.append(zoneI);
                     dynSizes[zoneI]++;
                 }
@@ -234,14 +233,15 @@ template<class Face>
 void Foam::fileFormats::STARCDsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&  faceLst  = surf.surfFaces();
+    const UList<label>& faceMap  = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst)
@@ -250,7 +250,6 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write
 
     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
 
-
     fileName baseName = filename.lessExt();
 
     writePoints
@@ -265,10 +264,11 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write
     forAll(zones, zoneI)
     {
         const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
                 writeShell(os, f, faceIndex, zoneI + 1);
@@ -276,7 +276,7 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
                 writeShell(os, f, faceIndex, zoneI + 1);
@@ -284,7 +284,7 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write
         }
     }
 
-    // write simple .inp file
+    // Write simple .inp file
     writeCase
     (
         OFstream(starFileName(baseName, STARCDCore::INP_FILE))(),
diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H
index d10bb1db6ebc0b302f1d939926e4191bd135076f..c8a1f99543ac41f8a1fbb308253989bea6f73f31 100644
--- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H
@@ -54,7 +54,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                     Class STARCDsurfaceFormat Declaration
+              Class fileFormats::STARCDsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -67,8 +67,8 @@ class STARCDsurfaceFormat
 
         static inline void writeShell
         (
-            Ostream&,
-            const Face&,
+            Ostream& os,
+            const Face& f,
             const label cellId,
             const label cellTableId
         );
@@ -85,42 +85,37 @@ public:
     // Constructors
 
         //- Construct from file name
-        STARCDsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new STARCDsurfaceFormat<Face>(name)
-            );
-        }
+        STARCDsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~STARCDsurfaceFormat()
-    {}
+    virtual ~STARCDsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C
index b6b87fc6a27cfffbf5c67003c7e56442200237aa..b55e86ea1f4e65d42dab9da6fde1115f60ac124a 100644
--- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C
@@ -37,7 +37,7 @@ License
 Foam::Map<Foam::word>
 Foam::fileFormats::STARCDsurfaceFormatCore::readInpCellTable
 (
-    IFstream& is
+    ISstream& is
 )
 {
     Map<word> lookup;
@@ -80,7 +80,7 @@ Foam::fileFormats::STARCDsurfaceFormatCore::readInpCellTable
 void Foam::fileFormats::STARCDsurfaceFormatCore::writeCase
 (
     Ostream& os,
-    const pointField& pointLst,
+    const UList<point>& pts,
     const label nFaces,
     const UList<surfZone>& zoneLst
 )
@@ -88,7 +88,7 @@ void Foam::fileFormats::STARCDsurfaceFormatCore::writeCase
     const word caseName = os.name().nameLessExt();
 
     os  << "! STAR-CD file written " << clock::dateTime().c_str() << nl
-        << "! " << pointLst.size() << " points, " << nFaces << " faces" << nl
+        << "! " << pts.size() << " points, " << nFaces << " faces" << nl
         << "! case " << caseName << nl
         << "! ------------------------------" << nl;
 
diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.H
index 970ff3929ec2a15889015194d923f5532b94da01..4a10e925da83f014effb68cb399baf233e98fa14 100644
--- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.H
@@ -48,7 +48,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                   Class STARCDsurfaceFormatCore Declaration
+            Class fileFormats::STARCDsurfaceFormatCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class STARCDsurfaceFormatCore
@@ -57,16 +57,16 @@ class STARCDsurfaceFormatCore
 {
 protected:
 
-    // Protected Member Functions
+    // Protected Static Member Functions
 
-    static Map<word> readInpCellTable(IFstream&);
+    static Map<word> readInpCellTable(ISstream& is);
 
     static void writeCase
     (
-        Ostream&,
-        const pointField&,
+        Ostream& os,
+        const UList<point>& pts,
         const label nFaces,
-        const UList<surfZone>&
+        const UList<surfZone>& zoneLst
     );
 };
 
diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
index a1ba96c0cc33bf00b7da67ac71d2a856a07176c1..64ad423df8943295bfa99b8dd5e50621af089145 100644
--- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
@@ -25,6 +25,7 @@ License
 
 #include "STLsurfaceFormat.H"
 #include "triPointRef.H"
+#include "ListOps.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -32,22 +33,18 @@ template<class Face>
 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
 (
     Ostream& os,
-    const pointField& pointLst,
+    const UList<point>& pts,
     const Face& f
 )
 {
     // calculate the normal ourselves, for flexibility and speed
-    vector norm = triPointRef
-    (
-        pointLst[f[0]],
-        pointLst[f[1]],
-        pointLst[f[2]]
-    ).normal();
+    vector norm = triPointRef(pts[f[0]], pts[f[1]], pts[f[2]]).normal();
     norm /= mag(norm) + VSMALL;
 
     // simple triangulation about f[0].
     // better triangulation should have been done before
-    const point& p0 = pointLst[f[0]];
+    const point& p0 = pts[f[0]];
+
     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
     {
         const label fp2 = f.fcIndex(fp1);
@@ -58,8 +55,8 @@ inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
             os,
             norm,
             p0,
-            pointLst[f[fp1]],
-            pointLst[f[fp2]]
+            pts[f[fp1]],
+            pts[f[fp2]]
         );
     }
 }
@@ -69,23 +66,19 @@ template<class Face>
 inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
 (
     ostream& os,
-    const pointField& pointLst,
+    const UList<point>& pts,
     const Face& f,
     const label zoneI
 )
 {
     // calculate the normal ourselves, for flexibility and speed
-    vector norm = triPointRef
-    (
-        pointLst[f[0]],
-        pointLst[f[1]],
-        pointLst[f[2]]
-    ).normal();
+    vector norm = triPointRef(pts[f[0]], pts[f[1]], pts[f[2]]).normal();
     norm /= mag(norm) + VSMALL;
 
     // simple triangulation about f[0].
     // better triangulation should have been done before
-    const point& p0 = pointLst[f[0]];
+    const point& p0 = pts[f[0]];
+
     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
     {
         const label fp2 = f.fcIndex(fp1);
@@ -95,8 +88,8 @@ inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
         (
             norm,
             p0,
-            pointLst[f[fp1]],
-            pointLst[f[fp2]],
+            pts[f[fp1]],
+            pts[f[fp2]],
             zoneI
         ).write(os);
     }
@@ -148,7 +141,7 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
     List<label> sizes(reader.sizes().xfer());
     List<label> zoneIds(reader.zoneIds().xfer());
 
-    // generate the (sorted) faces
+    // Generate the (sorted) faces
     List<Face> faceLst(zoneIds.size());
 
     if (reader.sorted())
@@ -167,12 +160,12 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
     }
     else
     {
-        // Unsorted - determine the sorted order:
-        // avoid SortableList since we discard the main list anyhow
-        List<label> faceMap;
+        // Determine the sorted order:
+        // use sortedOrder directly (the intermediate list is discared anyhow)
+        labelList faceMap;
         sortedOrder(zoneIds, faceMap);
 
-        // generate sorted faces
+        // Generate sorted faces
         forAll(faceMap, facei)
         {
             const label startPt = 3*faceMap[facei];
@@ -186,7 +179,7 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
     }
     zoneIds.clear();
 
-    // transfer:
+    // Transfer:
     this->storedFaces().transfer(faceLst);
 
     if (names.size())
@@ -218,11 +211,11 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
             << exit(FatalError);
     }
 
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst)
@@ -232,24 +225,22 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
     const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    for (const surfZone& zone : zones)
     {
-        // Print all faces belonging to this zone
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         os << "solid " << zone.name() << nl;
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
-                const label facei = faceMap[faceIndex++];
-                writeShell(os, pointLst, faceLst[facei]);
+                writeShell(os, pointLst, faceLst[faceMap[faceIndex++]]);
             }
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 writeShell(os, pointLst, faceLst[faceIndex++]);
             }
@@ -274,11 +265,11 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
             << exit(FatalError);
     }
 
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().size() > 1
       ? surf.surfZones()
@@ -292,36 +283,29 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
     STLCore::writeBinaryHeader(os, nTris);
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    label zoneIndex = 0;
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
-                writeShell
-                (
-                    os,
-                    pointLst,
-                    faceLst[faceMap[faceIndex++]],
-                    zoneI
-                );
+                const Face& f = faceLst[faceMap[faceIndex++]];
+                writeShell(os, pointLst, f, zoneIndex);
             }
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
-                writeShell
-                (
-                    os,
-                    pointLst,
-                    faceLst[faceIndex++],
-                    zoneI
-                );
+                const Face& f = faceLst[faceIndex++];
+                writeShell(os, pointLst, f, zoneIndex);
             }
         }
+
+        ++zoneIndex;
     }
 }
 
@@ -342,35 +326,35 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeAscii
     }
 
     const pointField& pointLst = surf.points();
-    const List<Face>& faceLst  = surf.surfFaces();
+    const UList<Face>& faceLst = surf.surfFaces();
 
-    // a single zone - we can skip sorting
+    // A single zone - we can skip sorting
     if (surf.zoneToc().size() == 1)
     {
         os << "solid " << surf.zoneToc()[0].name() << nl;
-        forAll(faceLst, facei)
+        for (const Face& f : faceLst)
         {
-            writeShell(os, pointLst, faceLst[facei]);
+            writeShell(os, pointLst, f);
         }
-        os << "endsolid " << surf.zoneToc()[0].name() << endl;
+        os << "endsolid " << surf.zoneToc()[0].name() << nl;
+    }
+    else
+    {
+        labelList faceMap;
+        List<surfZone> zoneLst = surf.sortedZones(faceMap);
+
+        writeAscii
+        (
+            filename,
+            MeshedSurfaceProxy<Face>
+            (
+                pointLst,
+                faceLst,
+                zoneLst,
+                faceMap
+            )
+        );
     }
-   else
-   {
-       labelList faceMap;
-       List<surfZone> zoneLst = surf.sortedZones(faceMap);
-
-       writeAscii
-       (
-           filename,
-           MeshedSurfaceProxy<Face>
-           (
-               pointLst,
-               faceLst,
-               zoneLst,
-               faceMap
-           )
-       );
-   }
 }
 
 
@@ -389,15 +373,15 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary
             << exit(FatalError);
     }
 
-    const pointField&  pointLst = surf.points();
-    const List<Face>&  faceLst  = surf.surfFaces();
-    const List<label>& zoneIds  = surf.zoneIds();
+    const pointField& pointLst = surf.points();
+    const UList<Face>& faceLst = surf.surfFaces();
+    const UList<label>& zoneIds = surf.zoneIds();
 
     // Write the STL header
     unsigned int nTris = surf.nTriangles();
     STLCore::writeBinaryHeader(os, nTris);
 
-    // always write unsorted
+    // Always write unsorted
     forAll(faceLst, facei)
     {
         writeShell
@@ -415,11 +399,21 @@ template<class Face>
 void Foam::fileFormats::STLsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
 )
 {
-    // Auto-detect ASCII/BINARY extension
-    write(filename, surf, STLCore::UNKNOWN);
+    // Detect "stlb" extension
+    bool useBinary = STLCore::isBinaryName(filename, STLCore::UNKNOWN);
+
+    if (useBinary)
+    {
+        writeBinary(filename, surf);
+    }
+    else
+    {
+        writeAscii(filename, surf);
+    }
 }
 
 
@@ -428,7 +422,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write
 (
     const fileName& filename,
     const MeshedSurfaceProxy<Face>& surf,
-    const STLFormat& format
+    const STLFormat format
 )
 {
     if (STLCore::isBinaryName(filename, format))
@@ -446,11 +440,21 @@ template<class Face>
 void Foam::fileFormats::STLsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
-    // Auto-detect ASCII/BINARY extension
-    write(filename, surf, STLCore::UNKNOWN);
+    // Detect "stlb" extension
+    bool useBinary = STLCore::isBinaryName(filename, STLCore::UNKNOWN);
+
+    if (useBinary)
+    {
+        writeBinary(filename, surf);
+    }
+    else
+    {
+        writeAscii(filename, surf);
+    }
 }
 
 
@@ -459,7 +463,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write
 (
     const fileName& filename,
     const UnsortedMeshedSurface<Face>& surf,
-    const STLFormat& format
+    const STLFormat format
 )
 {
     if (STLCore::isBinaryName(filename, format))
diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H
index 754ea005d92077276a7f84ef3a8526637db7621e..eb30aebac9311cea31bde93bd98a8111ee822eef 100644
--- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -53,7 +53,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                     Class STLsurfaceFormat Declaration
+                Class fileFormats::STLsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -67,17 +67,17 @@ class STLsurfaceFormat
         //- Write Face (ASCII)
         static inline void writeShell
         (
-            Ostream&,
-            const pointField&,
-            const Face&
+            Ostream& os,
+            const UList<point>& pts,
+            const Face& f
         );
 
         //- Write Face (BINARY)
         static inline void writeShell
         (
-            ostream&,
-            const pointField&,
-            const Face&,
+            ostream& os,
+            const UList<point>& pts,
+            const Face& f,
             const label zoneI
         );
 
@@ -94,97 +94,94 @@ public:
     // Constructors
 
         //- Construct from file name
-        STLsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new STLsurfaceFormat<Face>(name)
-            );
-        }
+        STLsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~STLsurfaceFormat()
-    {}
+    virtual ~STLsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy (as ASCII)
         static void writeAscii
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf
         );
 
         //- Write surface mesh components by proxy (as BINARY)
         static void writeBinary
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf
         );
 
-        //- Write surface mesh components by proxy
-        //  as ASCII or BINARY, depending on the extension
-        static void write
+        //- Write UnsortedMeshedSurface (as ASCII) sorted by zone
+        static void writeAscii
+        (
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf
+        );
+
+        //- Write UnsortedMeshedSurface (as BINARY) unsorted by zone
+        static void writeBinary
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf
         );
 
         //- Write surface mesh components by proxy
         //  as ASCII or BINARY or dependent on the extension
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&,
-            const STLFormat&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const STLFormat format
         );
 
-        //- Write UnsortedMeshedSurface (as ASCII) sorted by zone
-        static void writeAscii
+        //- Write UnsortedMeshedSurface
+        //  as ASCII or BINARY or dependent on the extension
+        static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf,
+            const STLFormat format
         );
 
-        //- Write UnsortedMeshedSurface (as BINARY) unsorted by zone
-        static void writeBinary
-        (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
-        );
 
-        //- Write UnsortedMeshedSurface
+        //- Write surface mesh components by proxy
         //  as ASCII or BINARY, depending on the extension
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface
-        //  as ASCII or BINARY or dependent on the extension
+        //  as ASCII or BINARY, depending on the extension
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&,
-            const STLFormat&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/triSurface/interfaces/STL/writeSTL.C b/src/surfMesh/surfaceFormats/stl/triSurfaceSTLformat.C
similarity index 50%
rename from src/surfMesh/triSurface/interfaces/STL/writeSTL.C
rename to src/surfMesh/surfaceFormats/stl/triSurfaceSTLformat.C
index fc8c2d0b94e60cf4a691f9703a20141e1f48f650..db7a9346e55f9eb225fb9f2dba68974288fa482f 100644
--- a/src/surfMesh/triSurface/interfaces/STL/writeSTL.C
+++ b/src/surfMesh/surfaceFormats/stl/triSurfaceSTLformat.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -23,10 +23,10 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "triSurface.H"
 #include "STLCore.H"
-#include "primitivePatch.H"
-
+#include "STLReader.H"
+#include "Fstream.H"
+#include "triSurface.H"
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
@@ -42,13 +42,86 @@ struct triSurfaceSTLCore
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const
+bool Foam::triSurface::readSTL(const fileName& filename, bool forceBinary)
 {
-    labelList faceMap;
+    // Read in the values
+    fileFormats::STLReader reader
+    (
+        filename,
+        (
+            forceBinary
+          ? fileFormats::STLCore::BINARY
+          : fileFormats::STLCore::UNKNOWN
+        )
+    );
+
+    // Get the map for stitched surface points, with merge tolerance depending
+    // on the input format
+    labelList pointMap;
+    const label nUniquePoints = reader.mergePointsMap(pointMap);
+
+    const auto& readpts = reader.points();
+    const labelList& zoneIds = reader.zoneIds();
+
+    pointField& pointLst = storedPoints();
+    List<Face>& faceLst  = storedFaces();
+
+    // Sizing
+    pointLst.setSize(nUniquePoints);
+    faceLst.setSize(zoneIds.size());
+
+    // Assign points
+    forAll(readpts, pointi)
+    {
+        pointLst[pointMap[pointi]] = readpts[pointi];
+    }
+
+    // Assign triangles
+    label pointi = 0;
+    forAll(faceLst, i)
+    {
+        Face& f = faceLst[i];
 
+        f[0] = pointMap[pointi++];
+        f[1] = pointMap[pointi++];
+        f[2] = pointMap[pointi++];
+        f.region() = zoneIds[i];
+    }
+
+    // Set patch name/index.
+    if (reader.stlFormat() == fileFormats::STLCore::ASCII)
+    {
+        const List<word>& names = reader.names();
+
+        patches_.setSize(names.size());
+        forAll(patches_, patchi)
+        {
+            patches_[patchi] = geometricSurfacePatch(names[patchi], patchi);
+        }
+    }
+
+    return true;
+}
+
+
+void Foam::triSurface::writeSTLASCII
+(
+    const fileName& filename,
+    const bool sort
+) const
+{
+    OFstream os(filename);
+    if (!os.good())
+    {
+        FatalErrorInFunction
+            << "Cannot open file for writing " << filename
+            << exit(FatalError);
+    }
+
+    labelList faceMap;
     surfacePatchList patches(calcPatches(faceMap));
 
-    if (writeSorted)
+    if (sort)
     {
         label faceIndex = 0;
         forAll(patches, patchi)
@@ -62,7 +135,7 @@ void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const
             (
                 label patchFacei = 0;
                 patchFacei < patch.size();
-                patchFacei++
+                ++patchFacei
             )
             {
                 const label facei = faceMap[faceIndex++];
@@ -81,58 +154,60 @@ void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const
 
             os  << "endsolid " << patch.name() << endl;
         }
+
+        return;
     }
-    else
+
+    // Get patch (=compact region) per face
+    labelList patchIDs(size());
+    forAll(patches, patchi)
     {
-        // Get patch (=compact region) per face
-        labelList patchIDs(size());
-        forAll(patches, patchi)
-        {
-            label facei = patches[patchi].start();
+        label facei = patches[patchi].start();
 
-            forAll(patches[patchi], i)
-            {
-                patchIDs[faceMap[facei++]] = patchi;
-            }
+        forAll(patches[patchi], i)
+        {
+            patchIDs[faceMap[facei++]] = patchi;
         }
+    }
 
-        label currentPatchi = -1;
-        forAll(*this, facei)
+    label currentPatchi = -1;
+    forAll(*this, facei)
+    {
+        if (currentPatchi != patchIDs[facei])
         {
-            if (currentPatchi != patchIDs[facei])
+            if (currentPatchi != -1)
             {
-                if (currentPatchi != -1)
-                {
-                    // Close previous solid
-                    os  << "endsolid " << patches[currentPatchi].name() << nl;
-                }
-                currentPatchi = patchIDs[facei];
-                os  << "solid " << patches[currentPatchi].name() << nl;
+                // Close previous solid
+                os  << "endsolid " << patches[currentPatchi].name() << nl;
             }
+            currentPatchi = patchIDs[facei];
+            os  << "solid " << patches[currentPatchi].name() << nl;
+        }
 
-            const labelledTri& f = (*this)[facei];
+        const labelledTri& f = (*this)[facei];
 
-            // Write ASCII
-            STLtriangle::write
-            (
-                os,
-                faceNormals()[facei],
-                points()[f[0]],
-                points()[f[1]],
-                points()[f[2]]
-            );
-        }
+        // Write ASCII
+        STLtriangle::write
+        (
+            os,
+            faceNormals()[facei],
+            points()[f[0]],
+            points()[f[1]],
+            points()[f[2]]
+        );
+    }
 
-        if (currentPatchi != -1)
-        {
-            os  << "endsolid " << patches[currentPatchi].name() << nl;
-        }
+    if (currentPatchi != -1)
+    {
+        os  << "endsolid " << patches[currentPatchi].name() << nl;
     }
 }
 
 
-void Foam::triSurface::writeSTLBINARY(std::ostream& os) const
+void Foam::triSurface::writeSTLBINARY(const fileName& filename) const
 {
+    std::ofstream os(filename, std::ios::binary);
+
     // Write the STL header
     triSurfaceSTLCore::writeBinaryHeader(os, this->size());
 
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
index f6e2118bbd7d51c40d2b5a9b88478d5121c94c3c..e5f4b63fedf85b63d087fb14700f237dd0c6e111 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
@@ -34,19 +34,21 @@ License
 
 Foam::word Foam::fileFormats::surfaceFormatsCore::nativeExt("ofs");
 
+
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 Foam::string Foam::fileFormats::surfaceFormatsCore::getLineNoComment
 (
-    IFstream& is
+    ISstream& is,
+    const char comment
 )
 {
-    string line;
+    Foam::string line;
     do
     {
         is.getLine(line);
     }
-    while ((line.empty() || line[0] == '#') && is.good());
+    while ((line.empty() || line[0] == comment) && is.good());
 
     return line;
 }
@@ -168,23 +170,12 @@ bool Foam::fileFormats::surfaceFormatsCore::checkSupport
     {
         Info<<"Unknown file extension for " << functionName
             << " : " << ext << nl
-            << "Valid types: " << flatOutput(available.sortedToc()) << endl;
+            << "Valid types: " << flatOutput(available.sortedToc()) << nl
+            << endl;
     }
 
     return false;
 }
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::fileFormats::surfaceFormatsCore::surfaceFormatsCore()
-{}
-
-
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::fileFormats::surfaceFormatsCore::~surfaceFormatsCore()
-{}
-
-
 // ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
index fe35c5b4b053d8d1bc00449b6a9dfd7fe7a6e8af..9ea6b6a5f224b5aca686cf02db4bb8cac6ce7a33 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
@@ -55,15 +55,19 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                     Class surfaceFormatsCore Declaration
+               Class fileFormats::surfaceFormatsCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class surfaceFormatsCore
 {
 protected:
 
+        //- Read non-empty and non-comment line
+        static string getLineNoComment(ISstream& is, const char comment='#');
+
+
         //- Return a surfZone list with a single entry, the size of which
-        //  corresponds to that of the container
+        //- corresponds to that of the container
         template<class Container>
         static List<surfZone> oneZone
         (
@@ -74,10 +78,6 @@ protected:
             return List<surfZone>(1, surfZone(name, container.size(), 0, 0));
         }
 
-        //- Read non-comment line
-        static string getLineNoComment(IFstream&);
-
-
 public:
 
     // Static Data
@@ -125,11 +125,11 @@ public:
     // Constructors
 
         //- Construct null
-        surfaceFormatsCore();
+        surfaceFormatsCore() = default;
 
 
     //- Destructor
-    virtual ~surfaceFormatsCore();
+    virtual ~surfaceFormatsCore() = default;
 
 };
 
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/tri/TRIReader.C
similarity index 71%
rename from src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C
rename to src/surfMesh/surfaceFormats/tri/TRIReader.C
index 2c66572be93dd0ad26864c6c94f54a010314b7dc..e1eb1e90a705efa6a62e529ed381b55e40d7041a 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/tri/TRIReader.C
@@ -23,41 +23,36 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-#include "TRIsurfaceFormat.H"
+#include "TRIReader.H"
+#include "surfaceFormatsCore.H"
 #include "IFstream.H"
 #include "IOmanip.H"
 #include "StringStream.H"
 #include "mergePoints.H"
 #include "Map.H"
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
 
-Foam::fileFormats::TRIsurfaceFormatCore::TRIsurfaceFormatCore
+static Foam::string getLineNoComment
 (
-    const fileName& filename
+    Foam::ISstream& is,
+    const char comment='#'
 )
-:
-    sorted_(true),
-    points_(0),
-    zoneIds_(0),
-    sizes_(0)
 {
-    read(filename);
-}
-
-
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+    Foam::string line;
+    do
+    {
+        is.getLine(line);
+    }
+    while ((line.empty() || line[0] == comment) && is.good());
 
-Foam::fileFormats::TRIsurfaceFormatCore::~TRIsurfaceFormatCore()
-{}
+    return line;
+}
 
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-bool Foam::fileFormats::TRIsurfaceFormatCore::read
-(
-    const fileName& filename
-)
+bool Foam::fileFormats::TRIReader::readFile(const fileName& filename)
 {
     this->clear();
     sorted_ = true;
@@ -74,6 +69,7 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
     // the rest of the reader resembles the STL binary reader
     DynamicList<STLpoint> dynPoints;
     DynamicList<label> dynZones;
+    DynamicList<word>  dynNames;
     DynamicList<label> dynSizes;
     HashTable<label>   lookup;
 
@@ -84,13 +80,14 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
 
     while (is.good())
     {
-        string line = this->getLineNoComment(is);
+        string line = getLineNoComment(is);
+
+        if (line.empty())
+        {
+            break;
+        }
 
-        // Handle continuations?
-        // if (line.removeEnd("\\"))
-        // {
-        //     line += this->getLineNoComment(is);
-        // }
+        // Do not handle continuations
 
         IStringStream lineStream(line);
 
@@ -133,21 +130,23 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
         const word rawName(lineStream);
         const word name("zone" + rawName.substr(1));
 
-        HashTable<label>::const_iterator fnd = lookup.cfind(name);
-        if (fnd.found())
+        const auto iter = lookup.cfind(name);
+        if (iter.found())
         {
-            if (zoneI != fnd())
+            if (zoneI != iter.object())
             {
-                // group appeared out of order
-                sorted_ = false;
+                sorted_ = false; // Group appeared out of order
+                zoneI = iter.object();
             }
-            zoneI = fnd();
         }
         else
         {
             zoneI = dynSizes.size();
-            lookup.insert(name, zoneI);
-            dynSizes.append(0);
+            if (lookup.insert(name, zoneI))
+            {
+                dynNames.append(name);
+                dynSizes.append(0);
+            }
         }
 
         dynZones.append(zoneI);
@@ -156,44 +155,68 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
 
     // skip empty groups
     label nZone = 0;
-    forAll(dynSizes, zoneI)
+    forAll(dynSizes, zonei)
     {
-        if (dynSizes[zoneI])
+        if (dynSizes[zonei])
         {
-            if (nZone != zoneI)
+            if (nZone != zonei)
             {
-                dynSizes[nZone] = dynSizes[zoneI];
+                dynNames[nZone] = dynNames[zonei];
+                dynSizes[nZone] = dynSizes[zonei];
             }
-            nZone++;
+            ++nZone;
         }
     }
+
     // truncate addressed size
+    dynNames.setCapacity(nZone);
     dynSizes.setCapacity(nZone);
 
     // transfer to normal lists
     points_.transfer(dynPoints);
     zoneIds_.transfer(dynZones);
+    names_.transfer(dynNames);
     sizes_.transfer(dynSizes);
 
     return true;
 }
 
 
-void Foam::fileFormats::TRIsurfaceFormatCore::clear()
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileFormats::TRIReader::TRIReader
+(
+    const fileName& filename
+)
+:
+    sorted_(true),
+    points_(),
+    zoneIds_(),
+    names_(),
+    sizes_()
+{
+    readFile(filename);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::fileFormats::TRIReader::clear()
 {
     sorted_ = true;
     points_.clear();
     zoneIds_.clear();
+    names_.clear();
     sizes_.clear();
 }
 
 
-Foam::label Foam::fileFormats::TRIsurfaceFormatCore::mergePointsMap
+Foam::label Foam::fileFormats::TRIReader::mergePointsMap
 (
     labelList& pointMap
 ) const
 {
-    // Use merge tolerance as per STL ascii
+    // Use merge tolerance as per STL ASCII
     return mergePointsMap
     (
         100 * doubleScalarSMALL,
@@ -202,7 +225,7 @@ Foam::label Foam::fileFormats::TRIsurfaceFormatCore::mergePointsMap
 }
 
 
-Foam::label Foam::fileFormats::TRIsurfaceFormatCore::mergePointsMap
+Foam::label Foam::fileFormats::TRIReader::mergePointsMap
 (
     const scalar mergeTol,
     labelList& pointMap
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/tri/TRIReader.H
similarity index 78%
rename from src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H
rename to src/surfMesh/surfaceFormats/tri/TRIReader.H
index 5d4b76fd6e0d122fb238e2433fca22430043a90f..00c117f58c78360aa9aad33756df485223c55796 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/tri/TRIReader.H
@@ -22,21 +22,27 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::fileFormats::TRIsurfaceFormatCore
+    Foam::fileFormats::TRIReader
 
 Description
-    Internal class used by the TRIsurfaceFormat
+    TRI (triangle) file reader.
+
+    For TRI format (eg, AC3D).
+    Each input line has 9 floats (3 points, each 3 floats) followed by hex
+    colour. The colour is used to build regions numbered from 0 upwards.
+
+    Reading and stitching similar to the STLReader.
 
 SourceFiles
-    TRIsurfaceFormatCore.C
+    TRIReader.C
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef TRIsurfaceFormatCore_H
-#define TRIsurfaceFormatCore_H
+#ifndef TRIReader_H
+#define TRIReader_H
 
-#include "surfaceFormatsCore.H"
 #include "STLpoint.H"
+#include "labelList.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -46,12 +52,10 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                    Class TRIsurfaceFormatCore Declaration
+                   Class fileFormats::TRIReader Declaration
 \*---------------------------------------------------------------------------*/
 
-class TRIsurfaceFormatCore
-:
-    public surfaceFormatsCore
+class TRIReader
 {
     // Private Data
 
@@ -63,19 +67,22 @@ class TRIsurfaceFormatCore
         //- The zones associated with the faces
         List<label> zoneIds_;
 
+        //- The zone names, in the order of their first appearance
+        List<word> names_;
+
         //- The solid count, in the order of their first appearance
         List<label> sizes_;
 
 
     // Private Member Functions
 
+        bool readFile(const fileName& filename);
+
         //- Disallow default bitwise copy construct
-        TRIsurfaceFormatCore(const TRIsurfaceFormatCore&) = delete;
+        TRIReader(const TRIReader&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const TRIsurfaceFormatCore&) = delete;
-
-        bool read(const fileName&);
+        TRIReader& operator=(const TRIReader&) = delete;
 
 
 public:
@@ -83,11 +90,11 @@ public:
     // Constructors
 
         //- Read from file, filling in the information
-        TRIsurfaceFormatCore(const fileName& filename);
+        TRIReader(const fileName& filename);
 
 
     //- Destructor
-    ~TRIsurfaceFormatCore();
+    ~TRIReader() = default;
 
 
     // Member Functions
@@ -123,6 +130,12 @@ public:
             return zoneIds_;
         }
 
+        //- The list of solid names in the order of their first appearance
+        inline List<word>& names()
+        {
+            return names_;
+        }
+
         //- The list of zone sizes in the order of their first appearance
         inline List<label>& sizes()
         {
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
index b36c5fd321d6c668069709f0b5493a47dc3ca15c..898adcb833e1baa4fbe2b91522613b0c65884390 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
@@ -24,7 +24,9 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "TRIsurfaceFormat.H"
+#include "TRIReader.H"
 #include "OFstream.H"
+#include "ListOps.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -32,20 +34,20 @@ template<class Face>
 inline void Foam::fileFormats::TRIsurfaceFormat<Face>::writeShell
 (
     Ostream& os,
-    const pointField& pointLst,
+    const UList<point>& pts,
     const Face& f,
     const label zoneI
 )
 {
     // simple triangulation about f[0].
     // better triangulation should have been done before
-    const point& p0 = pointLst[f[0]];
+    const point& p0 = pts[f[0]];
     for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
     {
-        label fp2 = f.fcIndex(fp1);
+        const label fp2 = f.fcIndex(fp1);
 
-        const point& p1 = pointLst[f[fp1]];
-        const point& p2 = pointLst[f[fp2]];
+        const point& p1 = pts[f[fp1]];
+        const point& p2 = pts[f[fp2]];
 
         os  << p0.x() << ' ' << p0.y() << ' ' << p0.z() << ' '
             << p1.x() << ' ' << p1.y() << ' ' << p1.z() << ' '
@@ -79,7 +81,7 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
     this->clear();
 
     // Read in the values
-    TRIsurfaceFormatCore reader(filename);
+    TRIReader reader(filename);
 
     // Get the map for stitched surface points
     labelList pointMap;
@@ -99,7 +101,7 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
     List<label> sizes(reader.sizes().xfer());
     List<label> zoneIds(reader.zoneIds().xfer());
 
-    // generate the (sorted) faces
+    // Generate the (sorted) faces
     List<Face> faceLst(zoneIds.size());
 
     if (reader.sorted())
@@ -118,12 +120,12 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
     }
     else
     {
-        // Unsorted - determine the sorted order:
-        // avoid SortableList since we discard the main list anyhow
-        List<label> faceMap;
+        // Determine the sorted order:
+        // use sortedOrder directly (the intermediate list is discared anyhow)
+        labelList faceMap;
         sortedOrder(zoneIds, faceMap);
 
-        // generate sorted faces
+        // Generate sorted faces
         forAll(faceMap, facei)
         {
             const label startPt = 3*faceMap[facei];
@@ -137,7 +139,7 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
     }
     zoneIds.clear();
 
-    // transfer:
+    // Transfer:
     this->storedFaces().transfer(faceLst);
 
     this->addZones(sizes);
@@ -151,14 +153,15 @@ template<class Face>
 void Foam::fileFormats::TRIsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst)
@@ -176,26 +179,29 @@ void Foam::fileFormats::TRIsurfaceFormat<Face>::write
     }
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    label zoneIndex = 0;
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
-                writeShell(os, pointLst, f, zoneI);
+                writeShell(os, pointLst, f, zoneIndex);
             }
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
-                writeShell(os, pointLst, f, zoneI);
+                writeShell(os, pointLst, f, zoneIndex);
             }
         }
+
+        ++zoneIndex;
     }
 }
 
@@ -204,11 +210,12 @@ template<class Face>
 void Foam::fileFormats::TRIsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>& faceLst  = surf.surfFaces();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
 
     OFstream os(filename);
     if (!os.good())
@@ -218,11 +225,10 @@ void Foam::fileFormats::TRIsurfaceFormat<Face>::write
             << exit(FatalError);
     }
 
-
-    // a single zone needs no sorting
+    // A single zone needs no sorting
     if (surf.zoneToc().size() == 1)
     {
-        const List<label>& zoneIds  = surf.zoneIds();
+        const UList<label>& zoneIds = surf.zoneIds();
 
         forAll(faceLst, facei)
         {
@@ -235,13 +241,18 @@ void Foam::fileFormats::TRIsurfaceFormat<Face>::write
         List<surfZone> zoneLst = surf.sortedZones(faceMap);
 
         label faceIndex = 0;
-        forAll(zoneLst, zoneI)
+        label zoneIndex = 0;
+        for (const surfZone& zone : zoneLst)
         {
-            forAll(zoneLst[zoneI], localFacei)
+            const label nLocalFaces = zone.size();
+
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
-                writeShell(os, pointLst, f, zoneI);
+                writeShell(os, pointLst, f, zoneIndex);
             }
+
+            ++zoneIndex;
         }
     }
 }
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.H b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.H
index b4b914800a519c110b3b39e40655fd9ea2b0452f..93159041343374fa37b110c5c041149a377be246 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.H
@@ -39,7 +39,6 @@ SourceFiles
 #ifndef TRIsurfaceFormat_H
 #define TRIsurfaceFormat_H
 
-#include "TRIsurfaceFormatCore.H"
 #include "MeshedSurface.H"
 #include "MeshedSurfaceProxy.H"
 #include "UnsortedMeshedSurface.H"
@@ -52,7 +51,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class TRIsurfaceFormat Declaration
+                Class fileFormats::TRIsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -64,9 +63,9 @@ class TRIsurfaceFormat
 
         static inline void writeShell
         (
-            Ostream&,
-            const pointField&,
-            const Face&,
+            Ostream& os,
+            const UList<point>& pts,
+            const Face& f,
             const label zoneI
         );
 
@@ -82,50 +81,46 @@ public:
     // Constructors
 
         //- Construct from file name
-        TRIsurfaceFormat(const fileName&);
-
-
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new TRIsurfaceFormat<Face>(name)
-            );
-        }
+        TRIsurfaceFormat(const fileName& filename);
 
 
     //- Destructor
-    virtual ~TRIsurfaceFormat()
-    {}
+    virtual ~TRIsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface,
         //  by default the output is not sorted by zones
         static void write
         (
-            const fileName&,
-            const UnsortedMeshedSurface<Face>&
+            const fileName& filename,
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
-        virtual bool read(const fileName&);
+        virtual bool read(const fileName& filename);
 
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
index 94e60511d0addcdcf45304a927ef5b0e9e495bc0..f75920ae9a127b16120cdad941d8235212a1d6db 100644
--- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
@@ -53,7 +53,7 @@ void Foam::fileFormats::VTKsurfaceFormat<Face>::writePolys
 {
     // connectivity count without additional storage (done internally)
     label nConnectivity = 0;
-    for (const auto& f : faces)
+    for (const Face& f : faces)
     {
         nConnectivity += f.size();
     }
@@ -109,7 +109,7 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
             << exit(FatalError);
     }
 
-    // assume that the groups are not intermixed
+    // Assume groups are not intermixed
     bool sorted = true;
 
 
@@ -187,9 +187,9 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
     label nTri = 0;
     if (faceTraits<Face>::isTri())
     {
-        forAll(faces, facei)
+        for (const face& f : faces)
         {
-            nTri += faces[facei].nTriangles();
+            nTri += f.nTriangles();
         }
     }
 
@@ -214,9 +214,9 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
 
         // Count
         labelList zoneSizes(nZones, 0);
-        forAll(dynZones, triI)
+        for (const label zonei : dynZones)
         {
-            zoneSizes[dynZones[triI]]++;
+            zoneSizes[zonei]++;
         }
 
         this->sortFacesAndStore(dynFaces.xfer(), dynZones.xfer(), sorted);
@@ -227,17 +227,16 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
     else
     {
         DynamicList<Face> dynFaces(faces.size());
-        forAll(faces, facei)
+        for (const face& f : faces)
         {
-            const face& f = faces[facei];
             dynFaces.append(Face(f));
         }
 
         // Count
         labelList zoneSizes(nZones, 0);
-        forAll(zones, facei)
+        for (const label zonei : zones)
         {
-            zoneSizes[zones[facei]]++;
+            zoneSizes[zonei]++;
         }
 
         this->sortFacesAndStore(dynFaces.xfer(), zones.xfer(), sorted);
@@ -258,14 +257,15 @@ template<class Face>
 void Foam::fileFormats::VTKsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst)
@@ -285,7 +285,7 @@ void Foam::fileFormats::VTKsurfaceFormat<Face>::write
     {
         // connectivity count without additional storage (done internally)
         label nConnectivity = 0;
-        for (const auto& f : faceLst)
+        for (const Face& f : faceLst)
         {
             nConnectivity += f.size();
         }
@@ -329,7 +329,8 @@ template<class Face>
 void Foam::fileFormats::VTKsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
     std::ofstream os(filename);
diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.H b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.H
index 9a73aceeb5adae70feb2e8e98a6f59e3a1c353a0..932a40a3f1d058f7b2f62aa674df40b8ffa37097 100644
--- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.H
@@ -25,7 +25,8 @@ Class
     Foam::fileFormats::VTKsurfaceFormat
 
 Description
-    Provide a means of reading/writing VTK legacy format.
+    Read/write VTK legacy format (ASCII) for surfaces.
+
     The output is never sorted by zone.
 
 SourceFiles
@@ -49,7 +50,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                     Class VTKsurfaceFormat Declaration
+                Class fileFormats::VTKsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -83,48 +84,42 @@ public:
         VTKsurfaceFormat(const fileName& filename);
 
 
-    // Selectors
-
-        //- Read file and return surface
-        static autoPtr<MeshedSurface<Face>> New(const fileName& name)
-        {
-            return autoPtr<MeshedSurface<Face>>
-            (
-                new VTKsurfaceFormat<Face>(name)
-            );
-        }
-
-
     //- Destructor
-    virtual ~VTKsurfaceFormat()
-    {}
+    virtual ~VTKsurfaceFormat() = default;
 
 
-    // Member Functions
-
-      // Write
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
             const fileName& filename,
-            const MeshedSurfaceProxy<Face>& surf
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface, the output remains unsorted
         static void write
         (
             const fileName& fileName,
-            const UnsortedMeshedSurface<Face>& surf
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Read from file
         virtual bool read(const fileName& filename);
 
         //- Write object file
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C
index fe58168e5b23ffeb2eebb7e5c8e551fb9c905249..a73985d804caf63689e8db168cf3b7c65d0e2793 100644
--- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.C
@@ -32,7 +32,7 @@ License
 void Foam::fileFormats::VTKsurfaceFormatCore::writeHeader
 (
     vtk::formatter& format,
-    const pointField& pts
+    const UList<point>& pts
 )
 {
     vtk::legacy::fileHeader
diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.H
index 8b09942f87777ac28a80b2ed31d53df8c9bffd11..5f04c8e64aa43ac2b9ea51f1320d29ac3dd33637 100644
--- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormatCore.H
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,8 +35,9 @@ SourceFiles
 #ifndef VTKsurfaceFormatCore_H
 #define VTKsurfaceFormatCore_H
 
-#include "MeshedSurface.H"
 #include "foamVtkFormatter.H"
+#include "point.H"
+#include "surfZone.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -46,20 +47,20 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                    Class VTKsurfaceFormatCore Declaration
+              Class fileFormats::VTKsurfaceFormatCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class VTKsurfaceFormatCore
 {
 protected:
 
-    // Protected Member Functions
+    // Protected Static Member Functions
 
         //- Write header information with points
         static void writeHeader
         (
             vtk::formatter& format,
-            const pointField& pts
+            const UList<point>& pts
         );
 
         //- Write regions (zones) information as CellData
diff --git a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.C b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.C
index 976672331381abe0392d8a63fc0b14b21e41c079..bf3d09911a3c913d90f41754d9f75f7efc388c57 100644
--- a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.C
@@ -66,7 +66,7 @@ void Foam::fileFormats::VTPsurfaceFormat<Face>::writePolys
 
         format.writeSize(payLoad * sizeof(label));
 
-        for (const Face& f : faces)
+        for (const auto& f : faces)
         {
             vtk::writeList(format, f);
         }
@@ -104,25 +104,19 @@ void Foam::fileFormats::VTPsurfaceFormat<Face>::writePolys
 }
 
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-template<class Face>
-Foam::fileFormats::VTPsurfaceFormat<Face>::VTPsurfaceFormat()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Face>
 void Foam::fileFormats::VTPsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary& options
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
     const List<surfZone>& zones =
     (
@@ -226,7 +220,8 @@ template<class Face>
 void Foam::fileFormats::VTPsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const UnsortedMeshedSurface<Face>& surf
+    const UnsortedMeshedSurface<Face>& surf,
+    const dictionary& options
 )
 {
     std::ofstream os(filename, std::ios::binary);
@@ -234,7 +229,7 @@ void Foam::fileFormats::VTPsurfaceFormat<Face>::write
     autoPtr<vtk::formatter> format =
         vtk::newFormatter(os, fmtType);
 
-    const List<Face>& faceLst = surf.surfFaces();
+    const UList<Face>& faceLst = surf.surfFaces();
 
     writeHeader(format(), surf.points(), faceLst.size());
 
diff --git a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.H b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.H
index ebc35eca0843a45c3592aa3e8451c1eed791f1b3..de8fbe4cc005e2611312f71644c948d05851f9e5 100644
--- a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormat.H
@@ -25,7 +25,8 @@ Class
     Foam::fileFormats::VTPsurfaceFormat
 
 Description
-    Provide a means of writing VTP (xml) format.
+    Write surfaces in VTP (xml) format.
+
     The output is never sorted by zone.
 
 SourceFiles
@@ -49,7 +50,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class VTPsurfaceFormat Declaration
+                Class fileFormats::VTPsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -80,36 +81,42 @@ public:
     // Constructors
 
         //- Construct null
-        VTPsurfaceFormat();
+        VTPsurfaceFormat() = default;
 
 
     //- Destructor
-    virtual ~VTPsurfaceFormat()
-    {}
-
+    virtual ~VTPsurfaceFormat() = default;
 
-    // Member Functions
 
-      // Write
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
             const fileName& filename,
-            const MeshedSurfaceProxy<Face>& surf
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
         //- Write UnsortedMeshedSurface, the output remains unsorted
         static void write
         (
             const fileName& filename,
-            const UnsortedMeshedSurface<Face>& surf
+            const UnsortedMeshedSurface<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
+
+    // Member Functions
+
         //- Write object file
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 };
 
diff --git a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.C
index 947b77d32fee41426770527263b7af7e13cfc91d..3bb9323e70a795958b7d87f5e524a7a3a4388c4f 100644
--- a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.C
@@ -32,7 +32,7 @@ License
 void Foam::fileFormats::VTPsurfaceFormatCore::writeHeader
 (
     vtk::formatter& format,
-    const pointField& pts,
+    const UList<point>& pts,
     const label nFaces
 )
 {
@@ -142,7 +142,6 @@ void Foam::fileFormats::VTPsurfaceFormatCore::writeCellData
     format.endDataArray();
 
     format.endTag(vtk::fileTag::CELL_DATA);
-
 }
 
 
diff --git a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.H
index 4b4a3ad85de4446b97d4a442ffaf63d5f9d48e0c..69393e6684cda39e44e452428534740b8dfd275c 100644
--- a/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/vtp/VTPsurfaceFormatCore.H
@@ -35,8 +35,9 @@ SourceFiles
 #ifndef VTPsurfaceFormatCore_H
 #define VTPsurfaceFormatCore_H
 
-#include "MeshedSurface.H"
 #include "foamVtkFormatter.H"
+#include "point.H"
+#include "surfZone.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -46,27 +47,26 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                    Class VTPsurfaceFormatCore Declaration
+              Class fileFormats::VTPsurfaceFormatCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class VTPsurfaceFormatCore
 {
 protected:
 
-    // Protected Member Functions
+    // Protected Static Member Functions
 
-        //- Write file header information with points
+        //- Write header information with points
         static void writeHeader
         (
             vtk::formatter& format,
-            const pointField& pts,
+            const UList<point>& pts,
             const label nFaces
         );
 
-        //- Write file footer
+        //- Write footer
         static void writeFooter(vtk::formatter& format);
 
-
         //- Write regions (zones) information as CellData
         static void writeCellData
         (
diff --git a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.C b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.C
index a9c63ccf4114f26f2019e1c27e6c2469a28765a1..fc02e1a085e2506d7dbf759bbe2af8f072aa3caf 100644
--- a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.C
@@ -26,28 +26,22 @@ License
 #include "X3DsurfaceFormat.H"
 #include "OFstream.H"
 
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-template<class Face>
-Foam::fileFormats::X3DsurfaceFormat<Face>::X3DsurfaceFormat()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Face>
 void Foam::fileFormats::X3DsurfaceFormat<Face>::write
 (
     const fileName& filename,
-    const MeshedSurfaceProxy<Face>& surf
+    const MeshedSurfaceProxy<Face>& surf,
+    const dictionary&
 )
 {
-    const pointField& pointLst = surf.points();
-    const List<Face>&  faceLst = surf.surfFaces();
-    const List<label>& faceMap = surf.faceMap();
+    const UList<point>& pointLst = surf.points();
+    const UList<Face>&   faceLst = surf.surfFaces();
+    const UList<label>&  faceMap = surf.faceMap();
 
     // for no zones, suppress the group name
-    const List<surfZone>& zones =
+    const UList<surfZone>& zones =
     (
         surf.surfZones().empty()
       ? surfaceFormatsCore::oneZone(faceLst, word::null)
@@ -80,13 +74,13 @@ void Foam::fileFormats::X3DsurfaceFormat<Face>::write
         "  <IndexedFaceSet coordIndex='\n";
 
     label faceIndex = 0;
-    forAll(zones, zoneI)
+    for (const surfZone& zone : zones)
     {
-        const surfZone& zone = zones[zoneI];
+        const label nLocalFaces = zone.size();
 
         if (useFaceMap)
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceMap[faceIndex++]];
 
@@ -99,7 +93,7 @@ void Foam::fileFormats::X3DsurfaceFormat<Face>::write
         }
         else
         {
-            forAll(zone, localFacei)
+            for (label i=0; i<nLocalFaces; ++i)
             {
                 const Face& f = faceLst[faceIndex++];
 
@@ -116,11 +110,8 @@ void Foam::fileFormats::X3DsurfaceFormat<Face>::write
         "' >\n"
         "    <Coordinate point='\n";
 
-    // Write vertex coords
-    forAll(pointLst, ptI)
+    for (const point& pt : pointLst)
     {
-        const point& pt = pointLst[ptI];
-
         os  << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
     }
 
@@ -130,7 +121,6 @@ void Foam::fileFormats::X3DsurfaceFormat<Face>::write
         "  </Shape>\n"
         " </Group>\n"
         "</X3D>\n";
-
 }
 
 
diff --git a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.H b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.H
index 20caa634202d114ad3d5403c5e7238f365c5b74c..8cb11eec441e9e38bdac34e5334fa83466081849 100644
--- a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormat.H
@@ -48,7 +48,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class X3DsurfaceFormat Declaration
+                Class fileFormats::X3DsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
@@ -70,28 +70,34 @@ public:
     // Constructors
 
         //- Construct null
-        X3DsurfaceFormat();
+        X3DsurfaceFormat() = default;
 
 
     //- Destructor
-    virtual ~X3DsurfaceFormat()
-    {}
+    virtual ~X3DsurfaceFormat() = default;
 
 
-    // Member Functions
+    // Static Member Functions
 
         //- Write surface mesh components by proxy
         static void write
         (
-            const fileName&,
-            const MeshedSurfaceProxy<Face>&
+            const fileName& filename,
+            const MeshedSurfaceProxy<Face>& surf,
+            const dictionary& options = dictionary::null
         );
 
 
+    // Member Functions
+
         //- Write object
-        virtual void write(const fileName& name) const
+        virtual void write
+        (
+            const fileName& name,
+            const dictionary& options = dictionary::null
+        ) const
         {
-            write(name, MeshedSurfaceProxy<Face>(*this));
+            write(name, MeshedSurfaceProxy<Face>(*this), options);
         }
 
 };
diff --git a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormatCore.H
index 751d91e2b25d5c3549f08a68c4aec8c55bf347a8..2102decfa0566c0d2384c2eedea7bbf38a19fead 100644
--- a/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/x3d/X3DsurfaceFormatCore.H
@@ -35,7 +35,6 @@ SourceFiles
 #ifndef X3DsurfaceFormatCore_H
 #define X3DsurfaceFormatCore_H
 
-#include "MeshedSurface.H"
 #include "Ostream.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -46,7 +45,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                    Class X3DsurfaceFormatCore Declaration
+              Class fileFormats::X3DsurfaceFormatCore Declaration
 \*---------------------------------------------------------------------------*/
 
 class X3DsurfaceFormatCore
@@ -55,10 +54,10 @@ protected:
     // Protected Member Functions
 
     //- Write file header
-    static void writeHeader(Ostream&);
+    static void writeHeader(Ostream& os);
 
     //- Write appearance node
-    static void writeAppearance(Ostream&);
+    static void writeAppearance(Ostream& os);
 
 };
 
diff --git a/src/surfMesh/surfaceRegistry/surfaceRegistry.C b/src/surfMesh/surfaceRegistry/surfaceRegistry.C
index 227481d7efadf9367d2e4b84c1901088fb71f593..49de22257f538be4fbf6550657a3035e1260ecbb 100644
--- a/src/surfMesh/surfaceRegistry/surfaceRegistry.C
+++ b/src/surfMesh/surfaceRegistry/surfaceRegistry.C
@@ -30,11 +30,11 @@ License
 
 namespace Foam
 {
-defineTypeNameAndDebug(surfaceRegistry, 0);
+    defineTypeNameAndDebug(surfaceRegistry, 0);
 }
 
-
 const Foam::word Foam::surfaceRegistry::prefix("surfaces");
+
 Foam::word Foam::surfaceRegistry::defaultName("default");
 
 
@@ -61,10 +61,4 @@ Foam::surfaceRegistry::surfaceRegistry
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::surfaceRegistry::~surfaceRegistry()
-{}
-
-
 // ************************************************************************* //
diff --git a/src/surfMesh/surfaceRegistry/surfaceRegistry.H b/src/surfMesh/surfaceRegistry/surfaceRegistry.H
index dd50c91244c0433279ecb6f3b6b7cbbab3eb16d7..f412f1d03cfff1514ae62820955170c3f37e0927 100644
--- a/src/surfMesh/surfaceRegistry/surfaceRegistry.H
+++ b/src/surfMesh/surfaceRegistry/surfaceRegistry.H
@@ -57,7 +57,7 @@ class surfaceRegistry
         surfaceRegistry(const surfaceRegistry&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const surfaceRegistry&) = delete;
+        surfaceRegistry& operator=(const surfaceRegistry&) = delete;
 
 
 public:
@@ -77,13 +77,14 @@ public:
         //- Construct for the given objectRegistry and named surface
         surfaceRegistry
         (
-            const objectRegistry&,
+            const objectRegistry& obr,
             const word& surfName = word::null
         );
 
 
     //- Destructor
-    virtual ~surfaceRegistry();
+    virtual ~surfaceRegistry() = default;
+
 };
 
 
diff --git a/src/surfMesh/triSurface/interfaces/AC3D/readAC.C b/src/surfMesh/triSurface/interfaces/AC3D/readAC.C
deleted file mode 100644
index a58f754113609f17baab3579a9fd78cff5c98086..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/AC3D/readAC.C
+++ /dev/null
@@ -1,349 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-Description
-    Reader for .ac files generated by AC3D.
-
-    See http://www.ac3d.org/ac3d/man/ac3dfileformat.html
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IFstream.H"
-#include "StringStream.H"
-#include "transform.H"
-#include "tensor.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-static label parseInt(const string& str)
-{
-    IStringStream intStream(str);
-
-    label a;
-
-    intStream >> a;
-
-    return a;
-}
-
-
-static bool readCmd(IFstream& ACfile, string& cmd, string& args)
-{
-    if (ACfile.good())
-    {
-        string line;
-        ACfile.getLine(line);
-
-        string::size_type space = line.find(' ');
-
-        if (space != string::npos)
-        {
-            cmd  = line.substr(0, space);
-            args = line.substr(space+1);
-
-            return true;
-        }
-    }
-    return false;
-}
-
-
-// Read up to line starting with cmd. Sets args to rest of line.
-// Returns true if found, false if stream is not good anymore.
-static bool readUpto
-(
-    const string& cmd,
-    IFstream& ACfile,
-    string& args
-)
-{
-    while (ACfile.good())
-    {
-        string line;
-        ACfile.getLine(line);
-
-        string::size_type space = line.find(' ');
-
-        if (space != string::npos && line.substr(0, space) == cmd)
-        {
-            args = line.substr(space+1);
-            return true;
-        }
-    }
-    return false;
-}
-
-
-// Likewise but throws error if cmd not found
-static void readUpto
-(
-    const string& cmd,
-    IFstream& ACfile,
-    string& args,
-    const string errorMsg
-)
-{
-    if (!readUpto(cmd, ACfile, args))
-    {
-        FatalErrorInFunction
-            << "Cannot find command " << cmd
-            << errorMsg << exit(FatalError);
-    }
-}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool triSurface::readAC(const fileName& ACfileName)
-{
-    IFstream ACfile(ACfileName);
-
-    if (!ACfile.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << ACfileName
-            << exit(FatalError);
-    }
-
-    string line;
-    ACfile.getLine(line);
-
-    string version = line.substr(4);
-
-    if (version != "b")
-    {
-        WarningInFunction
-            << "When reading AC3D file " << ACfileName
-            << " read header " << line << " with version " << version
-            << endl << "Only tested reading with version 'b'."
-            << " This might give problems" << endl;
-    }
-
-    string cmd;
-
-    string args;
-
-    if (!readUpto("OBJECT", ACfile, args) || (args != "world"))
-    {
-        FatalErrorInFunction
-            << "Cannot find \"OBJECT world\" in file " << ACfileName
-            << exit(FatalError);
-    }
-
-    // Number of kids = patches
-
-    readUpto("kids", ACfile, args, "");
-
-    label nPatches = parseInt(args);
-
-    // Storage for patches and unmerged points and faces
-
-    DynamicList<point> points;
-    DynamicList<labelledTri> faces;
-    geometricSurfacePatchList patches(nPatches);
-
-
-    // Start of vertices for object/patch
-    label patchStartVert = 0;
-
-    for (label patchi = 0; patchi < nPatches; patchi++)
-    {
-        readUpto
-        (
-            "OBJECT",
-            ACfile,
-            args,
-            " while reading patch " + Foam::name(patchi)
-        );
-
-        // Object global values
-        string patchName = string("patch") + Foam::name(patchi);
-        label nVerts = 0;
-        tensor rot(I);
-        vector loc(0, 0, 0);
-
-        // Read all info for current patch
-        while (ACfile.good())
-        {
-            // Read line and get first word. If end of file break since
-            // patch should always end with 'kids' command ?not sure.
-            if (!readCmd(ACfile, cmd, args))
-            {
-                FatalErrorInFunction
-                    << "Did not read up to \"kids 0\" while reading patch "
-                    << patchi << " from file " << ACfileName
-                    << exit(FatalError);
-            }
-
-            if (cmd == "name")
-            {
-                IStringStream nameStream(args);
-
-                nameStream >> patchName;
-            }
-            else if (cmd == "rot")
-            {
-                // rot %f %f %f  %f %f %f  %f %f %f
-                IStringStream lineStream(args);
-
-                lineStream
-                    >> rot.xx() >> rot.xy() >> rot.xz()
-                    >> rot.yx() >> rot.yy() >> rot.yz()
-                    >> rot.zx() >> rot.zy() >> rot.zz();
-
-                WarningInFunction
-                    << "rot (rotation tensor) command not implemented"
-                    << "Line:" << cmd << ' ' << args << endl
-                    << "while reading patch " << patchi << endl;
-            }
-            else if (cmd == "loc")
-            {
-                IStringStream lineStream(args);
-
-                lineStream >> loc.x() >> loc.y() >> loc.z();
-            }
-            else if (cmd == "numvert")
-            {
-                nVerts = parseInt(args);
-
-                for (label vertI = 0; vertI < nVerts; vertI++)
-                {
-                    ACfile.getLine(line);
-
-                    IStringStream lineStream(line);
-
-                    point pt;
-
-                    lineStream >> pt.x() >> pt.y() >> pt.z();
-
-                    // Offset with current translation vector
-                    points.append(pt+loc);
-                }
-            }
-            else if (cmd == "numsurf")
-            {
-                label nTris = parseInt(args);
-
-                for (label triI = 0; triI < nTris; triI++)
-                {
-                    static string errorMsg =
-                        string(" while reading face ")
-                      + name(triI) + " on patch " + name(patchi)
-                      + " from file " + ACfileName;
-
-                    readUpto("SURF", ACfile, args, errorMsg);
-                    readUpto("mat", ACfile, args, errorMsg);
-                    readUpto("refs", ACfile, args, errorMsg);
-
-                    label size = parseInt(args);
-
-                    if (size != 3)
-                    {
-                        FatalErrorInFunction
-                            << "Can only read surfaces with 3 vertices."
-                            << endl
-                            << "Detected " << size << " when reading triangle "
-                            << triI << " of patch " << patchi
-                            << exit(FatalError);
-                    }
-
-                    ACfile.getLine(line);
-
-                    label v0 = parseInt(line);
-
-                    ACfile.getLine(line);
-
-                    label v1 = parseInt(line);
-
-                    ACfile.getLine(line);
-
-                    label v2 = parseInt(line);
-
-                    faces.append
-                    (
-                        labelledTri
-                        (
-                            v0 + patchStartVert,
-                            v1 + patchStartVert,
-                            v2 + patchStartVert,
-                            patchi
-                        )
-                    );
-                }
-
-                // Done the current patch. Increment the offset vertices are
-                // stored at
-                patchStartVert += nVerts;
-            }
-            else if (cmd == "kids")
-            {
-                // 'kids' denotes the end of the current patch.
-
-                label nKids = parseInt(args);
-
-                if (nKids != 0)
-                {
-                    FatalErrorInFunction
-                        << "Can only read objects without kids."
-                        << " Encountered " << nKids << " kids when"
-                        << " reading patch " << patchi
-                        << exit(FatalError);
-                }
-
-                patches[patchi] =
-                    geometricSurfacePatch
-                    (
-                        word(patchName),
-                        patchi
-                    );
-
-                // Stop reading current patch
-                break;
-            }
-        }
-    }
-
-    faces.shrink();
-
-    // Transfer DynamicLists to straight ones.
-    pointField allPoints(points.xfer());
-
-    *this = triSurface(faces, patches, allPoints, true);
-
-    stitchTriangles();
-
-    return true;
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/AC3D/writeAC.C b/src/surfMesh/triSurface/interfaces/AC3D/writeAC.C
deleted file mode 100644
index a8239eae303f624b2ff647140970134a61a094bf..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/AC3D/writeAC.C
+++ /dev/null
@@ -1,139 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IOmanip.H"
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void Foam::triSurface::writeAC(Ostream& os) const
-{
-    // Write with patches as separate objects under "world" object.
-    // Header is taken over from sample file.
-    // Defines separate materials for all patches. Recycle colours.
-
-    // Define 8 standard colours as r,g,b components
-    static scalar colourMap[] =
-    {
-        1, 1, 1,
-        1, 0, 0,
-        0, 1, 0,
-        0, 0, 1,
-        1, 1, 0,
-        0, 1, 1,
-        1, 0, 1,
-        0.5, 0.5, 1
-    };
-
-    // Calculate patch face indexing
-
-    labelList faceMap;
-
-    surfacePatchList patches(calcPatches(faceMap));
-
-
-    // Write header. Define materials.
-
-    os  << "AC3Db" << endl;
-
-    forAll(patches, patchi)
-    {
-        const word& pName = patches[patchi].name();
-
-        label colourI = patchi % 8;
-        label colourCompI = 3 * colourI;
-
-        os  << "MATERIAL \"" << pName << "Mat\" rgb "
-            << colourMap[colourCompI] << ' ' << colourMap[colourCompI+1]
-            << ' ' << colourMap[colourCompI+2]
-            << "  amb 0.2 0.2 0.2  emis 0 0 0  spec 0.5 0.5 0.5  shi 10"
-            << "  trans 0"
-            << endl;
-    }
-
-    os  << "OBJECT world" << endl
-        << "kids " << patches.size() << endl;
-
-
-    // Write patch points & faces.
-
-    label faceIndex = 0;
-
-    forAll(patches, patchi)
-    {
-        const surfacePatch& sp = patches[patchi];
-
-        os  << "OBJECT poly" << endl
-            << "name \"" << sp.name() << '"' << endl;
-
-        // Create patch with only patch faces included for ease of addressing
-
-        boolList include(size(), false);
-
-        forAll(sp, patchFacei)
-        {
-            const label facei = faceMap[faceIndex++];
-
-            include[facei] = true;
-        }
-
-        labelList pointMap;
-        labelList faceMap;
-
-        triSurface patch = subsetMesh(include, pointMap, faceMap);
-
-        // Now we have triSurface for this patch alone. Write it.
-
-        os << "numvert " << patch.nPoints() << endl;
-
-        forAll(patch.localPoints(), ptI)
-        {
-            const point& pt = patch.localPoints()[ptI];
-
-            os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
-        }
-
-        os << "numsurf " << patch.localFaces().size() << endl;
-
-        forAll(patch.localFaces(), facei)
-        {
-            const labelledTri& f = patch.localFaces()[facei];
-
-            os  << "SURF 0x20" << endl          // polygon
-                << "mat " << patchi << endl
-                << "refs " << f.size() << endl;
-
-            os << f[0] << " 0 0" << endl;
-            os << f[1] << " 0 0" << endl;
-            os << f[2] << " 0 0" << endl;
-        }
-
-        os << "kids 0" << endl;
-    }
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/GTS/readGTS.C b/src/surfMesh/triSurface/interfaces/GTS/readGTS.C
deleted file mode 100644
index 666e9257401fd0f8a07f8462bc24fa935a46b1b8..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/GTS/readGTS.C
+++ /dev/null
@@ -1,161 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IFstream.H"
-#include "StringStream.H"
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readGTS(const fileName& GTSfileName)
-{
-    IFstream GTSfile(GTSfileName);
-
-    if (!GTSfile.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << GTSfileName
-            << exit(FatalError);
-    }
-
-    // Read header
-    label nPoints, nEdges, nElems;
-
-    string line = getLineNoComment(GTSfile);
-    {
-        IStringStream lineStream(line);
-        lineStream >> nPoints >> nEdges >> nElems;
-    }
-
-    // Read points
-    pointField& points_ = const_cast<pointField&>(points());
-    points_.setSize(nPoints);
-
-    forAll(points_, pointi)
-    {
-        scalar x, y, z;
-        line = getLineNoComment(GTSfile);
-        {
-            IStringStream lineStream(line);
-            lineStream >> x >> y >> z;
-        }
-        points_[pointi] = point(x, y, z);
-    }
-
-    // Read edges (Foam indexing)
-    edgeList edges(nEdges);
-    forAll(edges, edgei)
-    {
-        label start, end;
-        line = getLineNoComment(GTSfile);
-        {
-            IStringStream lineStream(line);
-            lineStream >> start >> end;
-        }
-        edges[edgei] = edge(start - 1, end - 1);
-    }
-
-    // Read triangles. Convert references to edges into pointlabels
-    setSize(nElems);
-    forAll(*this, trianglei)
-    {
-        label e0Label, e1Label, e2Label;
-        label region = 0;
-
-        line = getLineNoComment(GTSfile);
-        {
-            IStringStream lineStream(line);
-            lineStream >> e0Label >> e1Label >> e2Label;
-
-            // Optional region number: read first, then check state on stream
-            if (lineStream)
-            {
-                label num;
-                lineStream >> num;
-                if (!lineStream.bad())
-                {
-                    region = num;
-                }
-            }
-        }
-
-        // Determine ordering of edges e0, e1
-        //  common:common vertex, shared by e0 and e1
-        //  e0Far:vertex on e0 which is not common
-        //  e1Far: ,,       e1  ,,
-        const edge& e0 = edges[e0Label - 1];
-        const edge& e1 = edges[e1Label - 1];
-        const edge& e2 = edges[e2Label - 1];
-
-        label common01 = e0.commonVertex(e1);
-        if (common01 == -1)
-        {
-            FatalErrorInFunction
-                << "Edges 0 and 1 of triangle " << trianglei
-                << " do not share a point.\n"
-                << "    edge0:" << e0 << endl
-                << "    edge1:" << e1
-                << exit(FatalError);
-        }
-
-        label e0Far = e0.otherVertex(common01);
-        label e1Far = e1.otherVertex(common01);
-
-        label common12 = e1.commonVertex(e2);
-        if (common12 == -1)
-        {
-            FatalErrorInFunction
-                << "Edges 1 and 2 of triangle " << trianglei
-                << " do not share a point.\n"
-                << "    edge1:" << e1 << endl
-                << "    edge2:" << e2
-                << exit(FatalError);
-        }
-        label e2Far = e2.otherVertex(common12);
-
-        // Does edge2 sit between edge1 and 0?
-        if ((common12 != e1Far) || (e2Far != e0Far))
-        {
-            FatalErrorInFunction
-                << "Edges of triangle " << trianglei
-                << " reference more than three points.\n"
-                << "    edge0:" << e0 << endl
-                << "    edge1:" << e1 << endl
-                << "    edge2:" << e2 << endl
-                << exit(FatalError);
-        }
-
-        operator[](trianglei) = labelledTri(e0Far, common01, e1Far, region);
-    }
-
-    // Construct patch names
-    setDefaultPatches();
-
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/NAS/readNAS.C b/src/surfMesh/triSurface/interfaces/NAS/readNAS.C
deleted file mode 100644
index dfd7955ebfe3fbe23637acef88d555bc5435c7c5..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/NAS/readNAS.C
+++ /dev/null
@@ -1,359 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
--------------------------------------------------------------------------------
-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 <http://www.gnu.org/licenses/>.
-
-Description
-    Nastran surface reader.
-
-    - Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions
-      to obtain patch names.
-    - Handles Nastran short, long, and comma-separated free formats.
-    - Properly handles the Nastran compact floating point notation: \n
-    \verbatim
-        GRID          28        10.20269-.030265-2.358-8
-    \endverbatim
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "NASCore.H"
-#include "IFstream.H"
-#include "StringStream.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-// Do weird things to extract number
-static inline scalar readNasScalar(const string& s)
-{
-    return Foam::fileFormats::NASCore::readNasScalar(s);
-}
-
-
-// Read a column of a given width from either a fixed-format NAS file, or a
-// comma-separated free-format NAS file
-static std::string readNASToken
-(
-    const string& line,
-    const size_t& width,
-    size_t& index
-)
-{
-    size_t indexStart = index;
-    size_t indexEnd = line.find(',', indexStart);
-    index = indexEnd + 1;
-
-    if (indexEnd == std::string::npos)
-    {
-        indexEnd = indexStart + width;
-        index = indexEnd;
-    }
-
-    return line.substr(indexStart, indexEnd - indexStart);
-}
-
-
-bool triSurface::readNAS(const fileName& fName)
-{
-    IFstream is(fName);
-
-    if (!is.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << fName
-            << exit(FatalError);
-    }
-
-    // coordinates of point
-    DynamicList<point> points;
-    // Nastran index of point
-    DynamicList<label> indices;
-    // Faces in terms of Nastran point indices
-    DynamicList<labelledTri> faces;
-    // From face group to patch
-    Map<label> groupToPatch;
-    label nPatches = 0;
-    // Name for face group
-    Map<word> groupToName;
-
-    // Ansa tags. Denoted by $ANSA_NAME. These will appear just before the
-    // first use of a type. We read them and store the pshell types which
-    // are used to name the patches.
-    label ansaId = -1;
-    word ansaType;
-    string ansaName;
-
-    // A single warning per unrecognized command
-    HashSet<word> unhandledCmd;
-
-    while (is.good())
-    {
-        size_t linei = 0;
-        string line;
-        is.getLine(line);
-
-        // ANSA extension
-        if (line.startsWith("$ANSA_NAME"))
-        {
-            const auto sem0 = line.find(';', 0);
-            const auto sem1 = line.find(';', sem0+1);
-            const auto sem2 = line.find(';', sem1+1);
-
-            if
-            (
-                sem0 != string::npos
-             && sem1 != string::npos
-             && sem2 != string::npos
-            )
-            {
-                ansaId = readLabel(line.substr(sem0+1, sem1-sem0-1));
-                ansaType = line.substr(sem1+1, sem2-sem1-1);
-
-                string nameString;
-                is.getLine(ansaName);
-
-                ansaName.removeEnd("\r");  // Possible CR-NL
-
-                ansaName = ansaName.substr(1);
-                // Info<< "ANSA tag for NastranID:" << ansaId
-                //     << " of type " << ansaType
-                //     << " name " << ansaName << endl;
-            }
-        }
-
-
-        // Hypermesh extension
-        // $HMNAME COMP                   1"partName"
-        if (line.startsWith("$HMNAME COMP") && line.find('"') != string::npos)
-        {
-            label groupId = readLabel(line.substr(16, 16));
-            IStringStream lineStream(line.substr(32));
-
-            string rawName;
-            lineStream >> rawName;
-
-            const word groupName = word::validate(rawName);
-            groupToName.insert(groupId, groupName);
-            Info<< "group " << groupId << " => " << groupName << endl;
-        }
-
-
-        if (line.empty() || line[0] == '$')
-        {
-            // Skip empty or comment
-            continue;
-        }
-
-        // Check if character 72 is continuation
-        if (line.size() > 72 && line[72] == '+')
-        {
-            line.resize(72);
-
-            while (true)
-            {
-                string buf;
-                is.getLine(buf);
-
-                if (buf.size() > 72 && buf[72] == '+')
-                {
-                    line += buf.substr(8, 64);
-                }
-                else
-                {
-                    line += buf.substr(8);
-                    break;
-                }
-            }
-        }
-
-        // Read first word
-        word cmd(IStringStream(readNASToken(line, 8, linei))());
-
-        if (cmd == "CTRIA3")
-        {
-            readNASToken(line, 8, linei);
-            label groupId = readLabel(readNASToken(line, 8, linei));
-            label a = readLabel(readNASToken(line, 8, linei));
-            label b = readLabel(readNASToken(line, 8, linei));
-            label c = readLabel(readNASToken(line, 8, linei));
-
-            // Convert group into patch
-            Map<label>::const_iterator iter = groupToPatch.find(groupId);
-
-            label patchi;
-            if (iter == groupToPatch.end())
-            {
-                patchi = nPatches++;
-                groupToPatch.insert(groupId, patchi);
-                Info<< "patch " << patchi << " => group " << groupId << endl;
-            }
-            else
-            {
-                patchi = iter();
-            }
-
-            faces.append(labelledTri(a, b, c, patchi));
-        }
-        else if (cmd == "CQUAD4")
-        {
-            readNASToken(line, 8, linei);
-            label groupId = readLabel(readNASToken(line, 8, linei));
-            label a = readLabel(readNASToken(line, 8, linei));
-            label b = readLabel(readNASToken(line, 8, linei));
-            label c = readLabel(readNASToken(line, 8, linei));
-            label d = readLabel(readNASToken(line, 8, linei));
-
-            // Convert group into patch
-            Map<label>::const_iterator iter = groupToPatch.find(groupId);
-
-            label patchi;
-            if (iter == groupToPatch.end())
-            {
-                patchi = nPatches++;
-                groupToPatch.insert(groupId, patchi);
-                Info<< "patch " << patchi << " => group " << groupId << endl;
-            }
-            else
-            {
-                patchi = iter();
-            }
-
-            faces.append(labelledTri(a, b, c, patchi));
-            faces.append(labelledTri(c, d, a, patchi));
-        }
-        else if (cmd == "PSHELL")
-        {
-            // Read shell type since group gives patchnames
-            label groupId = readLabel(readNASToken(line, 8, linei));
-            if (groupId == ansaId && ansaType == "PSHELL")
-            {
-                const word groupName = word::validate(ansaName);
-                groupToName.insert(groupId, groupName);
-                Info<< "group " << groupId << " => " << groupName << endl;
-            }
-        }
-        else if (cmd == "GRID")
-        {
-            label index = readLabel(readNASToken(line, 8, linei));
-            readNASToken(line, 8, linei);
-            scalar x = readNasScalar(readNASToken(line, 8, linei));
-            scalar y = readNasScalar(readNASToken(line, 8, linei));
-            scalar z = readNasScalar(readNASToken(line, 8, linei));
-
-            indices.append(index);
-            points.append(point(x, y, z));
-        }
-        else if (cmd == "GRID*")
-        {
-            // Long format is on two lines with '*' continuation symbol
-            // on start of second line.
-            // Typical line (spaces compacted)
-            // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
-            // *         2.14897901E+02
-            label index = readLabel(readNASToken(line, 16, linei));
-            readNASToken(line, 16, linei);
-            scalar x = readNasScalar(readNASToken(line, 16, linei));
-            scalar y = readNasScalar(readNASToken(line, 16, linei));
-
-            linei = 0;
-            is.getLine(line);
-            if (line[0] != '*')
-            {
-                FatalErrorInFunction
-                    << "Expected continuation symbol '*' when reading GRID*"
-                    << " (double precision coordinate) output" << nl
-                    << "Read:" << line << nl
-                    << "File:" << is.name()
-                    << " line:" << is.lineNumber()
-                    << exit(FatalError);
-            }
-            readNASToken(line, 8, linei);
-            scalar z = readNasScalar(readNASToken(line, 16, linei));
-
-            indices.append(index);
-            points.append(point(x, y, z));
-        }
-        else if (unhandledCmd.insert(cmd))
-        {
-            Info<< "Unhandled Nastran command " << line << nl
-                << "File:" << is.name() << " line:" << is.lineNumber() << endl;
-        }
-    }
-
-    points.shrink();
-    indices.shrink();
-    faces.shrink();
-
-
-    Info<< "Read triangles:" << faces.size() << " points:" << points.size()
-        << endl;
-
-    {
-        // Build inverse mapping (index to point)
-        Map<label> indexToPoint(2*indices.size());
-        forAll(indices, i)
-        {
-            indexToPoint.insert(indices[i], i);
-        }
-
-        // Relabel faces
-        forAll(faces, i)
-        {
-            labelledTri& f = faces[i];
-
-            f[0] = indexToPoint[f[0]];
-            f[1] = indexToPoint[f[1]];
-            f[2] = indexToPoint[f[2]];
-        }
-    }
-
-
-    // Convert groupToPatch to patchList.
-    geometricSurfacePatchList patches(nPatches);
-
-    forAllConstIters(groupToName, iter)
-    {
-        const label patchIdx = groupToPatch[iter.key()];
-        patches[patchIdx] = geometricSurfacePatch(iter.object(), patchIdx);
-    }
-
-    Info<< "patches:" << patches << endl;
-
-    // Transfer DynamicLists to straight ones.
-    pointField allPoints(points.xfer());
-
-    // Create triSurface
-    *this = triSurface(faces, patches, allPoints, true);
-
-    return true;
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/OBJ/readOBJ.C b/src/surfMesh/triSurface/interfaces/OBJ/readOBJ.C
deleted file mode 100644
index 62187851483b7910e91de183bd70be6e14522b9c..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/OBJ/readOBJ.C
+++ /dev/null
@@ -1,199 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IFstream.H"
-#include "StringStream.H"
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readOBJ(const fileName& OBJfileName)
-{
-    IFstream OBJfile(OBJfileName);
-
-    if (!OBJfile.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << OBJfileName
-            << exit(FatalError);
-    }
-
-    DynamicList<point> points;
-    DynamicList<labelledTri> faces;
-    HashTable<label> groupToPatch;
-
-    label groupID = 0;
-    label maxGroupID = 0;
-
-    while (OBJfile.good())
-    {
-        string line = getLineNoComment(OBJfile);
-
-        if (line.size())
-        {
-            if (line.removeEnd("\\"))
-            {
-                line += getLineNoComment(OBJfile);
-            }
-
-            // Read first word
-            IStringStream lineStream(line);
-            word cmd;
-            lineStream >> cmd;
-
-            if (cmd == "v")
-            {
-                scalar x, y, z;
-
-                lineStream >> x >> y >> z;
-
-                points.append(point(x, y, z));
-            }
-            else if (cmd == "g")
-            {
-                word group;
-
-                lineStream >> group;
-
-                HashTable<label>::const_iterator findGroup =
-                    groupToPatch.find(group);
-
-                if (findGroup != groupToPatch.end())
-                {
-                    groupID = findGroup();
-                }
-                else
-                {
-                    groupID = maxGroupID;
-
-                    groupToPatch.insert(group, groupID);
-
-                    maxGroupID++;
-                }
-            }
-            else if (cmd == "f")
-            {
-                DynamicList<label> verts;
-
-                // Assume 'f' is followed by space.
-                string::size_type endNum = 1;
-
-                while (true)
-                {
-                    string::size_type startNum =
-                        line.find_first_not_of(" \r", endNum);
-
-                    if (startNum == string::npos)
-                    {
-                        break;
-                    }
-
-                    endNum = line.find(' ', startNum);
-
-                    string vertexSpec;
-                    if (endNum != string::npos)
-                    {
-                        vertexSpec = line.substr(startNum, endNum-startNum);
-                    }
-                    else
-                    {
-                        vertexSpec = line.substr
-                        (
-                            startNum,
-                            line.size() - startNum
-                        );
-                    }
-
-                    string::size_type slashPos = vertexSpec.find('/');
-
-                    label vertI = 0;
-                    if (slashPos != string::npos)
-                    {
-                        IStringStream intStream(vertexSpec.substr(0, slashPos));
-
-                        intStream >> vertI;
-                    }
-                    else
-                    {
-                        IStringStream intStream(vertexSpec);
-
-                        intStream >> vertI;
-                    }
-                    verts.append(vertI - 1);
-                }
-
-                verts.shrink();
-
-                // Do simple face triangulation around f[0].
-                // Cannot use face::triangulation since no complete points yet.
-                for (label fp = 1; fp < verts.size() - 1; fp++)
-                {
-                    label fp1 = verts.fcIndex(fp);
-
-                    labelledTri tri(verts[0], verts[fp], verts[fp1], groupID);
-
-                    faces.append(tri);
-                }
-            }
-        }
-    }
-
-    points.shrink();
-    faces.shrink();
-
-    // Convert groupToPatch to patchList.
-    geometricSurfacePatchList patches(maxGroupID);
-
-    if (maxGroupID == 0)
-    {
-        // Add single (default) patch
-        patches = { geometricSurfacePatch("patch0", 0) };
-    }
-    else
-    {
-        forAllConstIters(groupToPatch, iter)
-        {
-            const label patchIdx = iter.object();
-
-            patches[patchIdx] = geometricSurfacePatch
-            (
-                iter.key(),
-                patchIdx
-            );
-        }
-    }
-
-
-    // Transfer DynamicLists to straight ones.
-    pointField allPoints(points.xfer());
-
-    // Create triSurface
-    *this = triSurface(faces, patches, allPoints, true);
-
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/OBJ/writeOBJ.C b/src/surfMesh/triSurface/interfaces/OBJ/writeOBJ.C
deleted file mode 100644
index 40abdae6a0f82f0bc10d9990a0f717bcc04b472e..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/OBJ/writeOBJ.C
+++ /dev/null
@@ -1,140 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-Description
-    Lightwave OBJ format.
-
-    Note: Java obj loader does not support '#' on line
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void triSurface::writeOBJ(const bool writeSorted, Ostream& os) const
-{
-    // Write header
-    os  << "# Wavefront OBJ file" << nl
-        << "# Regions:" << nl;
-
-    labelList faceMap;
-
-    surfacePatchList patches(calcPatches(faceMap));
-
-    const pointField& ps = points();
-
-    // Print patch names as comment
-    forAll(patches, patchi)
-    {
-        os  << "#     " << patchi << "    "
-            << patches[patchi].name() << nl;
-    }
-    os  << "#" << nl;
-
-    os  << "# points    : " << ps.size() << nl
-        << "# triangles : " << size() << nl
-        << "#" << nl;
-
-
-    // Write vertex coords
-    forAll(ps, pointi)
-    {
-        os  << "v "
-            << ps[pointi].x() << ' '
-            << ps[pointi].y() << ' '
-            << ps[pointi].z() << nl;
-    }
-
-    if (writeSorted)
-    {
-        label faceIndex = 0;
-
-        forAll(patches, patchi)
-        {
-            // Print all faces belonging to this patch
-
-            os  << "g " << patches[patchi].name() << nl;
-
-            for
-            (
-                label patchFacei = 0;
-                patchFacei < patches[patchi].size();
-                patchFacei++
-            )
-            {
-                const label facei = faceMap[faceIndex++];
-
-                os  << "f "
-                    << operator[](facei)[0] + 1 << ' '
-                    << operator[](facei)[1] + 1 << ' '
-                    << operator[](facei)[2] + 1
-                    //<< "  # " << operator[](facei).region()
-                    << nl;
-            }
-        }
-    }
-    else
-    {
-        // Get patch (=compact region) per face
-        labelList patchIDs(size());
-        forAll(patches, patchi)
-        {
-            label facei = patches[patchi].start();
-
-            forAll(patches[patchi], i)
-            {
-                patchIDs[faceMap[facei++]] = patchi;
-            }
-        }
-
-
-        label prevPatchi = -1;
-
-        forAll(*this, facei)
-        {
-            if (prevPatchi != patchIDs[facei])
-            {
-                prevPatchi = patchIDs[facei];
-                os  << "g " << patches[patchIDs[facei]].name() << nl;
-            }
-            os  << "f "
-                << operator[](facei)[0] + 1 << ' '
-                << operator[](facei)[1] + 1 << ' '
-                << operator[](facei)[2] + 1
-                << nl;
-        }
-    }
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/OFF/readOFF.C b/src/surfMesh/triSurface/interfaces/OFF/readOFF.C
deleted file mode 100644
index 62a0dec6ea8cbc5f616e71062840de15a79fd543..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/OFF/readOFF.C
+++ /dev/null
@@ -1,134 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-Description
-    Geomview OFF polyList format. Does triangulation.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IFstream.H"
-#include "StringStream.H"
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readOFF(const fileName& OFFfileName)
-{
-    IFstream OFFfile(OFFfileName);
-
-    if (!OFFfile.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << OFFfileName
-            << exit(FatalError);
-    }
-
-    // Read header
-    string hdr = getLineNoComment(OFFfile);
-    if (hdr != "OFF")
-    {
-        FatalErrorInFunction
-            << "OFF file " << OFFfileName
-            << " does not start with 'OFF'"
-            << exit(FatalError);
-    }
-
-
-    label nPoints, nEdges, nElems;
-
-    string line = getLineNoComment(OFFfile);
-    {
-        IStringStream lineStream(line);
-        lineStream >> nPoints >> nElems >> nEdges;
-    }
-
-    // Read points
-    pointField points(nPoints);
-
-    forAll(points, pointi)
-    {
-        scalar x, y, z;
-        line = getLineNoComment(OFFfile);
-        {
-            IStringStream lineStream(line);
-            lineStream >> x >> y >> z;
-        }
-        points[pointi] = point(x, y, z);
-    }
-
-    // Read faces & triangulate them,
-    DynamicList<labelledTri> tris(nElems);
-
-    for (label facei = 0; facei < nElems; facei++)
-    {
-        line = getLineNoComment(OFFfile);
-        {
-            IStringStream lineStream(line);
-
-            label nVerts;
-            lineStream >> nVerts;
-
-            face f(nVerts);
-
-            forAll(f, fp)
-            {
-                lineStream >> f[fp];
-            }
-
-            // Triangulate.
-            if (nVerts == 3)
-            {
-                tris.append(labelledTri(f[0], f[1], f[2], 0));
-            }
-            else if (nVerts == 4)
-            {
-                tris.append(labelledTri(f[0], f[1], f[2], 0));
-                tris.append(labelledTri(f[2], f[3], f[0], 0));
-            }
-            else
-            {
-                faceList triFaces(f.nTriangles(points));
-
-                label nTri = 0;
-
-                f.triangles(points, nTri, triFaces);
-
-                forAll(triFaces, triFacei)
-                {
-                    const face& f = triFaces[triFacei];
-
-                    tris.append(labelledTri(f[0], f[1], f[2], 0));
-                }
-            }
-        }
-    }
-
-    tris.shrink();
-
-    *this = triSurface(tris, points);
-
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/OFF/writeOFF.C b/src/surfMesh/triSurface/interfaces/OFF/writeOFF.C
deleted file mode 100644
index 838ee47606ff631d91efe25a582a3c479f8375ca..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/OFF/writeOFF.C
+++ /dev/null
@@ -1,116 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void triSurface::writeOFF(const bool writeSorted, Ostream& os) const
-{
-    // Write header
-    os  << "OFF" << endl
-        << "# Geomview OFF file" << endl
-        << "# Regions:" << endl;
-
-    labelList faceMap;
-    surfacePatchList patches(calcPatches(faceMap));
-
-    // Print patch names as comment
-    forAll(patches, patchi)
-    {
-        os  << "#     " << patchi << "    "
-            << patches[patchi].name() << endl;
-    }
-    os  << nl << endl;
-
-    const pointField& ps = points();
-
-    os  << "# nPoints  nTriangles  nEdges" << endl
-        << ps.size()
-        << ' ' << size()
-        << ' ' << nEdges()
-        << nl << endl;
-
-    // Write vertex coords
-    forAll(ps, pointi)
-    {
-        os  << ps[pointi].x() << ' '
-            << ps[pointi].y() << ' '
-            << ps[pointi].z() << " #" << pointi << endl;
-    }
-
-    os  << endl;
-
-    if (writeSorted)
-    {
-        label faceIndex = 0;
-
-        forAll(patches, patchi)
-        {
-            // Print all faces belonging to this patch
-
-            for
-            (
-                label patchFacei = 0;
-                patchFacei < patches[patchi].size();
-                patchFacei++
-            )
-            {
-                const label facei = faceMap[faceIndex++];
-
-                os  << "3 "
-                    << operator[](facei)[0] << ' '
-                    << operator[](facei)[1] << ' '
-                    << operator[](facei)[2] << ' '
-                    << operator[](facei).region()
-                    << endl;
-            }
-        }
-    }
-    else
-    {
-        forAll(*this, facei)
-        {
-            os  << "3 "
-                << operator[](facei)[0] << ' '
-                << operator[](facei)[1] << ' '
-                << operator[](facei)[2] << ' '
-                << operator[](facei).region()
-                << endl;
-        }
-    }
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/SMESH/writeSMESH.C b/src/surfMesh/triSurface/interfaces/SMESH/writeSMESH.C
deleted file mode 100644
index 46627f7e1b397055accdd24a2997b55873c825bf..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/SMESH/writeSMESH.C
+++ /dev/null
@@ -1,111 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void triSurface::writeSMESH(const bool writeSorted, Ostream& os) const
-{
-    const pointField& ps = points();
-
-    // Write header
-    os  << "# tetgen .smesh file" << endl
-        << ps.size() << " 3" << endl;   // 3 dimensions
-
-    // Write vertex coords
-    forAll(ps, pointi)
-    {
-        os  << pointi << ' '
-            << ps[pointi].x() << ' '
-            << ps[pointi].y() << ' '
-            << ps[pointi].z() << endl;
-    }
-
-    if (writeSorted)
-    {
-        labelList faceMap;
-
-        surfacePatchList patches(calcPatches(faceMap));
-
-        os  << size() << " 1" << endl;   // 1 attribute: region number
-
-        label faceIndex = 0;
-
-        forAll(patches, patchi)
-        {
-            // Print all faces belonging to this patch
-
-            for
-            (
-                label patchFacei = 0;
-                patchFacei < patches[patchi].size();
-                patchFacei++
-            )
-            {
-                const label facei = faceMap[faceIndex++];
-
-                os  << "3 " // triangles
-                    << operator[](facei)[0] << ' '
-                    << operator[](facei)[1] << ' '
-                    << operator[](facei)[2] << ' '
-                    << operator[](facei).region()   // region number
-                    << endl;
-            }
-        }
-
-        os  << '0' << endl      // holes
-            << '0' << endl;     // regions
-    }
-    else
-    {
-        os  << size() << " 1" << endl;   // 1 attribute: region number
-
-        forAll(*this, facei)
-        {
-            os  << "3 "
-                << operator[](facei)[0] << ' '
-                << operator[](facei)[1] << ' '
-                << operator[](facei)[2] << ' '
-                << operator[](facei).region()       // region number
-                << endl;
-        }
-
-        os  << '0' << endl      // holes
-            << '0' << endl;     // regions
-    }
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/STL/readSTL.C b/src/surfMesh/triSurface/interfaces/STL/readSTL.C
deleted file mode 100644
index 70b1e9f44454d172af6031f59e0127d865efb751..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/STL/readSTL.C
+++ /dev/null
@@ -1,92 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017 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 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "STLReader.H"
-#include "triSurface.H"
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readSTL(const fileName& STLfileName, bool forceBinary)
-{
-    // Read in the values
-    fileFormats::STLReader reader
-    (
-        STLfileName,
-        (
-            forceBinary
-          ? fileFormats::STLCore::BINARY
-          : fileFormats::STLCore::UNKNOWN
-        )
-    );
-
-    // Get the map for stitched surface points, with merge tolerance depending
-    // on the input format
-    labelList pointMap;
-    const label nUniquePoints = reader.mergePointsMap(pointMap);
-
-    const auto& readpts = reader.points();
-    const labelList& zoneIds = reader.zoneIds();
-
-    pointField& pointLst = storedPoints();
-    List<Face>& faceLst  = storedFaces();
-
-    // Sizing
-    pointLst.setSize(nUniquePoints);
-    faceLst.setSize(zoneIds.size());
-
-    // Assign points
-    forAll(readpts, pointi)
-    {
-        pointLst[pointMap[pointi]] = readpts[pointi];
-    }
-
-    // Assign triangles
-    label pointi = 0;
-    forAll(faceLst, i)
-    {
-        Face& f = faceLst[i];
-
-        f[0] = pointMap[pointi++];
-        f[1] = pointMap[pointi++];
-        f[2] = pointMap[pointi++];
-        f.region() = zoneIds[i];
-    }
-
-    // Set patch name/index.
-    if (reader.stlFormat() == fileFormats::STLCore::ASCII)
-    {
-        const List<word>& names = reader.names();
-
-        patches_.setSize(names.size());
-        forAll(patches_, patchi)
-        {
-            patches_[patchi] = geometricSurfacePatch(names[patchi], patchi);
-        }
-    }
-
-    return true;
-}
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/TRI/readTRI.C b/src/surfMesh/triSurface/interfaces/TRI/readTRI.C
deleted file mode 100644
index b8190d39d5437a515f96e195f205d17ce33bee54..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/TRI/readTRI.C
+++ /dev/null
@@ -1,172 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-Description
-    TRI (triangle) file reader. Comes out of e.g. AC3D.
-    lines are 9 floats (3 points, each 3 floats) followed by hex colour.
-    Is converted into regions: regions numbered from 0 up, each colour is
-    region.
-    Most of reading/stitching taken from STL reader.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "STLpoint.H"
-#include "SLList.H"
-#include "IFstream.H"
-#include "readHexLabel.H"
-#include "stringList.H"
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readTRI(const fileName& TRIfileName)
-{
-    IFstream TRIfile(TRIfileName);
-
-    if (!TRIfile.good())
-    {
-        FatalErrorInFunction
-            << "Cannot read file " << TRIfileName
-            << exit(FatalError);
-    }
-
-    SLList<STLpoint> STLpoints;
-    SLList<label> STLlabels;
-    HashTable<label, string> STLsolidNames;
-
-    // Max region number so far
-    label maxRegion = 0;
-
-    while (TRIfile)
-    {
-        string line = getLineNoComment(TRIfile);
-
-        if (line.empty())
-        {
-            break;
-        }
-
-        IStringStream lineStream(line);
-
-        STLpoint p
-        (
-            readScalar(lineStream),
-            readScalar(lineStream),
-            readScalar(lineStream)
-        );
-
-        if (!lineStream) break;
-
-        STLpoints.append(p);
-        STLpoints.append
-        (
-            STLpoint
-            (
-                readScalar(lineStream),
-                readScalar(lineStream),
-                readScalar(lineStream)
-            )
-        );
-        STLpoints.append
-        (
-            STLpoint
-            (
-                readScalar(lineStream),
-                readScalar(lineStream),
-                readScalar(lineStream)
-            )
-        );
-
-        // Region/colour in .tri file starts with 0x. Skip.
-
-        char zeroChar;
-        lineStream >> zeroChar;
-
-        const word rawSolidName(lineStream);
-
-        const word solidName("patch" + rawSolidName.substr(1));
-
-        label region  = -1;
-
-        auto fnd = STLsolidNames.cfind(solidName);
-
-        if (fnd.found())
-        {
-            region = fnd();
-        }
-        else
-        {
-            Pout<< "Mapping triangle colour 0" << rawSolidName
-                << " to region " << maxRegion << " name " << solidName
-                << endl;
-
-            region = maxRegion++;
-            STLsolidNames.insert(solidName, region);
-        }
-        STLlabels.append(region);
-    }
-
-
-    pointField rawPoints(STLpoints.size());
-
-    label pointi = 0;
-    forAllConstIter(SLList<STLpoint>, STLpoints, iter)
-    {
-        rawPoints[pointi++] = *iter;
-    }
-
-    setSize(STLlabels.size());
-
-    // Assign triangles
-    pointi = 0;
-    SLList<label>::const_iterator iter = STLlabels.begin();
-    forAll(*this, i)
-    {
-        operator[](i)[0] = pointi++;
-        operator[](i)[1] = pointi++;
-        operator[](i)[2] = pointi++;
-        operator[](i).region() = *iter;
-        ++iter;
-    }
-
-    // Assign coordinates
-    storedPoints().transfer(rawPoints);
-    // Merge duplicate points
-    stitchTriangles();
-
-    // Convert solidNames into regionNames
-    stringList names(STLsolidNames.toc());
-
-    patches_.setSize(names.size());
-
-    forAll(names, nameI)
-    {
-        patches_[nameI].name() = names[nameI];
-        patches_[nameI].geometricType() = geometricSurfacePatch::emptyType;
-    }
-
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/TRI/writeTRI.C b/src/surfMesh/triSurface/interfaces/TRI/writeTRI.C
deleted file mode 100644
index fbf421145fdefa5941569e4ebc85f10f3b85cdd3..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/TRI/writeTRI.C
+++ /dev/null
@@ -1,113 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "IOmanip.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void triSurface::writeTRI(const bool writeSorted, Ostream& os) const
-{
-    const pointField& ps = points();
-
-    // Write as cloud of triangles
-
-    labelList faceMap;
-
-    surfacePatchList patches(calcPatches(faceMap));
-
-    if (writeSorted)
-    {
-        label faceIndex = 0;
-
-        forAll(patches, patchi)
-        {
-            for
-            (
-                label patchFacei = 0;
-                patchFacei < patches[patchi].size();
-                patchFacei++
-            )
-            {
-                const label facei = faceMap[faceIndex++];
-
-                const point& p1 = ps[operator[](facei)[0]];
-                const point& p2 = ps[operator[](facei)[1]];
-                const point& p3 = ps[operator[](facei)[2]];
-
-                os  << p1.x() << token::SPACE
-                    << p1.y() << token::SPACE
-                    << p1.z() << token::SPACE
-
-                    << p2.x() << token::SPACE
-                    << p2.y() << token::SPACE
-                    << p2.z() << token::SPACE
-
-                    << p3.x() << token::SPACE
-                    << p3.y() << token::SPACE
-                    << p3.z() << token::SPACE
-
-                    << "0x" << hex << operator[](facei).region() << dec
-                    << endl;
-            }
-        }
-    }
-    else
-    {
-        forAll(*this, facei)
-        {
-            const point& p1 = ps[operator[](facei)[0]];
-            const point& p2 = ps[operator[](facei)[1]];
-            const point& p3 = ps[operator[](facei)[2]];
-
-            os  << p1.x() << token::SPACE
-                << p1.y() << token::SPACE
-                << p1.z() << token::SPACE
-
-                << p2.x() << token::SPACE
-                << p2.y() << token::SPACE
-                << p2.z() << token::SPACE
-
-                << p3.x() << token::SPACE
-                << p3.y() << token::SPACE
-                << p3.z() << token::SPACE
-
-                << "0x" << hex << operator[](facei).region() << dec
-                << endl;
-        }
-    }
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/VTK/readVTK.C b/src/surfMesh/triSurface/interfaces/VTK/readVTK.C
deleted file mode 100644
index d19b38e96c7d61705fe2c83091b65abda6f2493b..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/VTK/readVTK.C
+++ /dev/null
@@ -1,106 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2012-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
--------------------------------------------------------------------------------
-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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "VTKsurfaceFormat.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::triSurface::readVTK(const fileName& fName)
-{
-    // Read (and triangulate) point, faces, zone info
-    fileFormats::VTKsurfaceFormat<triFace> surf(fName);
-
-    List<labelledTri> tris(surf.size());
-    forAll(tris, i)
-    {
-        const triFace& f = surf[i];
-        tris[i] = labelledTri(f[0], f[1], f[2], 0);
-    }
-
-    // Add regions from zone
-    const List<surfZone>& surfZones = surf.surfZones();
-
-    geometricSurfacePatchList patches;
-
-    if (surfZones.size())
-    {
-        patches.setSize(surfZones.size());
-        forAll(surfZones, zoneI)
-        {
-            const surfZone& zone = surfZones[zoneI];
-
-            // Add patch. Convert synthetic 'zone' name into 'patch' for now.
-            // (vtk format does not contain region names)
-            word regionName = zone.name();
-            if (regionName != (string("zone") + name(zoneI)))
-            {
-                regionName = string("patch") + name(zoneI);
-            }
-
-            patches[zoneI] = geometricSurfacePatch
-            (
-                regionName,
-                zoneI,
-                zone.geometricType()
-            );
-
-            // Set triangle regions
-            for (label i = zone.start(); i < zone.start()+zone.size(); ++i)
-            {
-                tris[i].region() = zoneI;
-            }
-        }
-    }
-    else
-    {
-        // Add single (default) patch
-        // Triangle regions already set to 0
-        patches = { geometricSurfacePatch("patch0", 0) };
-    }
-
-
-    // Create triSurface
-    *this = triSurface
-    (
-        tris.xfer(),
-        patches,
-        surf.xferPoints()
-    );
-
-    return true;
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace Foam
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/interfaces/VTK/writeVTK.C b/src/surfMesh/triSurface/interfaces/VTK/writeVTK.C
deleted file mode 100644
index f4a57b96f858915bf8e0140a6322e4b10f7ada9d..0000000000000000000000000000000000000000
--- a/src/surfMesh/triSurface/interfaces/VTK/writeVTK.C
+++ /dev/null
@@ -1,167 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
--------------------------------------------------------------------------------
-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 <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "triSurface.H"
-#include "foamVtkOutput.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-// File-scope constant.
-//
-// TODO: make this run-time selectable (ASCII | BINARY)
-// - Legacy mode only
-
-static const Foam::vtk::formatType fmtType =
-    Foam::vtk::formatType::LEGACY_ASCII;
-    // Foam::vtk::formatType::LEGACY_BINARY;
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-void Foam::triSurface::writeVTK
-(
-    const bool writeSorted,
-    std::ostream& os
-) const
-{
-    autoPtr<vtk::formatter> format =
-        vtk::newFormatter(os, fmtType);
-
-    // Header
-    vtk::legacy::fileHeader
-    (
-        format(),
-        "triSurface",
-        vtk::fileTag::POLY_DATA
-    );
-
-    const pointField& pts = this->points();
-    const auto& faceLst = this->surfFaces();
-
-    const label nFaces = faceLst.size();
-
-    // Points
-    vtk::legacy::beginPoints(os, pts.size());
-
-    vtk::writeList(format(), pts);
-    format().flush();
-
-    // connectivity count (without additional storage)
-    // is simply 3 * nFaces
-
-    vtk::legacy::beginPolys(os, nFaces, 3*nFaces);
-
-    labelList faceMap;
-    surfacePatchList patches(calcPatches(faceMap));
-
-    const bool useFaceMap = (writeSorted && patches.size() > 1);
-
-    if (useFaceMap)
-    {
-        label faceIndex = 0;
-        for (const surfacePatch& patch : patches)
-        {
-            forAll(patch, i)
-            {
-                const Face& f = faceLst[faceMap[faceIndex++]];
-
-                format().write(label(3));   // The size prefix
-                vtk::writeList(format(), f);
-            }
-        }
-        format().flush();
-
-
-        // Write regions (zones) as CellData
-        if (patches.size() > 1)
-        {
-            vtk::legacy::dataHeader
-            (
-                os,
-                vtk::fileTag::CELL_DATA,
-                nFaces,
-                1  // Only one field
-            );
-
-            vtk::legacy::intField
-            (
-                os,
-                "region",
-                1, // nComponent
-                nFaces
-            );
-
-            faceIndex = 0;
-            for (const surfacePatch& patch : patches)
-            {
-                forAll(patch, i)
-                {
-                    const Face& f = faceLst[faceMap[faceIndex++]];
-                    format().write(f.region());
-                }
-            }
-            format().flush();
-        }
-    }
-    else
-    {
-        // No faceMap (unsorted)
-
-        for (const Face& f : faceLst)
-        {
-            format().write(label(3));   // The size prefix
-            vtk::writeList(format(), f);
-        }
-        format().flush();
-
-
-        // Write regions (zones) as CellData
-
-        vtk::legacy::dataHeader
-        (
-            os,
-            vtk::fileTag::CELL_DATA,
-            faceLst.size(),
-            1  // Only one field
-        );
-
-        vtk::legacy::intField
-        (
-            os,
-            "region",
-            1, // nComponent
-            faceLst.size()
-        );
-
-        for (const Face& f : faceLst)
-        {
-            format().write(f.region());
-        }
-        format().flush();
-    }
-}
-
-
-// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/patches/geometricSurfacePatch.C b/src/surfMesh/triSurface/patches/geometricSurfacePatch.C
index 45c3191b35df63422372eccfa4f0f67e5a31e39e..b92b2d592467a73ebcc41150e5d1acecb9e86acd 100644
--- a/src/surfMesh/triSurface/patches/geometricSurfacePatch.C
+++ b/src/surfMesh/triSurface/patches/geometricSurfacePatch.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -30,7 +30,7 @@ License
 
 namespace Foam
 {
-defineTypeNameAndDebug(geometricSurfacePatch, 0);
+    defineTypeNameAndDebug(geometricSurfacePatch, 0);
 }
 
 const Foam::word Foam::geometricSurfacePatch::emptyType = "empty";
@@ -64,7 +64,6 @@ Foam::geometricSurfacePatch::geometricSurfacePatch
     geometricType_(geometricType),
     name_(name),
     index_(index)
-
 {
     if (geometricType_.empty())
     {
@@ -83,7 +82,22 @@ Foam::geometricSurfacePatch::geometricSurfacePatch
     geometricType_(geometricType),
     name_(name),
     index_(index)
+{
+    if (geometricType_.empty())
+    {
+        geometricType_ = emptyType;
+    }
+}
+
 
+Foam::geometricSurfacePatch::geometricSurfacePatch
+(
+    const surfZoneIdentifier& ident
+)
+:
+    geometricType_(ident.geometricType()),
+    name_(ident.name()),
+    index_(ident.index())
 {
     if (geometricType_.empty())
     {
diff --git a/src/surfMesh/triSurface/patches/geometricSurfacePatch.H b/src/surfMesh/triSurface/patches/geometricSurfacePatch.H
index 3adfe452d7a4d77e9870040ab2d63abdc7db4318..cd796d3d0c1e0d9a7781fc9e67908a501c56987e 100644
--- a/src/surfMesh/triSurface/patches/geometricSurfacePatch.H
+++ b/src/surfMesh/triSurface/patches/geometricSurfacePatch.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -36,18 +36,16 @@ SourceFiles
 #ifndef geometricSurfacePatch_H
 #define geometricSurfacePatch_H
 
-#include "word.H"
-#include "label.H"
 #include "typeInfo.H"
+#include "surfZoneIdentifier.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
+// Forward declarations
 class dictionary;
-
-// Forward declaration of friend functions and operators
 class geometricSurfacePatch;
 
 Istream& operator>>(Istream& is, geometricSurfacePatch& p);
@@ -106,6 +104,10 @@ public:
             const label index
         );
 
+        //- Implicit conversion from surfZoneIdentifier, which has similar
+        //- information but in a different order
+        geometricSurfacePatch(const surfZoneIdentifier& ident);
+
         //- Construct from dictionary
         geometricSurfacePatch
         (
diff --git a/src/surfMesh/triSurface/triSurface.C b/src/surfMesh/triSurface/triSurface.C
index 6a7b60da3f747c897a904371572277b8e98441e9..3e86a1b4595d5009ad3cf459d4e4f84700642983 100644
--- a/src/surfMesh/triSurface/triSurface.C
+++ b/src/surfMesh/triSurface/triSurface.C
@@ -25,14 +25,10 @@ License
 
 #include "triSurface.H"
 #include "demandDrivenData.H"
-#include "Fstream.H"
 #include "Time.H"
-#include "boundBox.H"
-#include "SortableList.H"
-#include "PackedBoolList.H"
 #include "surfZoneList.H"
-#include "surfaceFormatsCore.H"
-#include "MeshedSurfaceProxy.H"
+#include "MeshedSurface.H"
+#include "ListOps.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -42,73 +38,8 @@ namespace Foam
 }
 
 
-// Note that these lists are a stop-gap measure until the read/write handling
-// gets properly updated
-const Foam::wordHashSet Foam::triSurface::readTypes_
-{
-    "ftr", "stl", "stlb", "gts", "obj", "off", "tri", "ac", "nas", "vtk"
-};
-
-
-const Foam::wordHashSet Foam::triSurface::writeTypes_
-{
-    "ftr", "stl", "stlb", "gts", "obj", "off", "tri", "ac", "smesh", "vtk",
-    // via proxy:
-    "inp", "vtp"
-};
-
-
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
-bool Foam::triSurface::canReadType(const word& ext, const bool verbose)
-{
-    return fileFormats::surfaceFormatsCore::checkSupport
-    (
-        readTypes(),
-        ext,
-        verbose,
-        "reading"
-   );
-}
-
-
-bool Foam::triSurface::canWriteType(const word& ext, const bool verbose)
-{
-    return fileFormats::surfaceFormatsCore::checkSupport
-    (
-        writeTypes(),
-        ext,
-        verbose,
-        "writing"
-    );
-}
-
-
-bool Foam::triSurface::canRead(const fileName& name, const bool verbose)
-{
-    word ext = name.ext();
-    if (ext == "gz")
-    {
-        ext = name.lessExt().ext();
-    }
-    return canReadType(ext, verbose);
-}
-
-
-const Foam::wordHashSet& Foam::triSurface::readTypes()
-{
-    return readTypes_;
-}
-
-
-const Foam::wordHashSet& Foam::triSurface::writeTypes()
-{
-    return writeTypes_;
-}
-
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
 Foam::fileName Foam::triSurface::triSurfInstance(const Time& d)
 {
     fileName foamName(d.caseName() + ".ftr");
@@ -217,50 +148,17 @@ Foam::List<Foam::labelledTri> Foam::triSurface::convertToTri
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-void Foam::triSurface::printTriangle
-(
-    Ostream& os,
-    const string& pre,
-    const labelledTri& f,
-    const pointField& points
-)
-{
-    os
-        << pre.c_str() << "vertex numbers:"
-        << f[0] << ' ' << f[1] << ' ' << f[2] << endl
-        << pre.c_str() << "vertex coords :"
-        << points[f[0]] << ' ' << points[f[1]] << ' ' << points[f[2]]
-        << pre.c_str() << "region        :" << f.region() << endl
-        << endl;
-}
-
-
-Foam::string Foam::triSurface::getLineNoComment(IFstream& is)
-{
-    string line;
-    do
-    {
-        is.getLine(line);
-    }
-    while ((line.empty() || line[0] == '#') && is.good());
-
-    return line;
-}
-
-
 // Remove non-triangles, double triangles.
 void Foam::triSurface::checkTriangles(const bool verbose)
 {
     // Simple check on indices ok.
     const label maxPointi = points().size() - 1;
 
-    forAll(*this, facei)
+    for (const triSurface::FaceType& f : *this)
     {
-        const triSurface::FaceType& f = (*this)[facei];
-
-        forAll(f, fp)
+        for (const label verti : f)
         {
-            if (f[fp] < 0 || f[fp] > maxPointi)
+            if (verti < 0 || verti > maxPointi)
             {
                 FatalErrorInFunction
                     << "triangle " << f
@@ -306,14 +204,12 @@ void Foam::triSurface::checkTriangles(const bool verbose)
             // Check if faceNeighbours use same points as this face.
             // Note: discards normal information - sides of baffle are merged.
 
-            forAll(fEdges, fp)
+            for (const label edgei : fEdges)
             {
-                const labelList& eFaces = edgeFaces()[fEdges[fp]];
+                const labelList& eFaces = edgeFaces()[edgei];
 
-                forAll(eFaces, i)
+                for (const label neighbour : eFaces)
                 {
-                    label neighbour = eFaces[i];
-
                     if (neighbour > facei)
                     {
                         // lower numbered faces already checked
@@ -383,21 +279,21 @@ void Foam::triSurface::checkEdges(const bool verbose)
 {
     const labelListList& eFaces = edgeFaces();
 
-    forAll(eFaces, edgeI)
+    forAll(eFaces, edgei)
     {
-        const labelList& myFaces = eFaces[edgeI];
+        const labelList& myFaces = eFaces[edgei];
 
         if (myFaces.empty())
         {
             FatalErrorInFunction
-                << "Edge " << edgeI << " with vertices " << edges()[edgeI]
+                << "Edge " << edgei << " with vertices " << edges()[edgei]
                 << " has no edgeFaces"
                 << exit(FatalError);
         }
         else if (myFaces.size() > 2 && verbose)
         {
             WarningInFunction
-                << "Edge " << edgeI << " with vertices " << edges()[edgeI]
+                << "Edge " << edgei << " with vertices " << edges()[edgei]
                 << " has more than 2 faces connected to it : " << myFaces
                 << endl;
         }
@@ -405,187 +301,21 @@ void Foam::triSurface::checkEdges(const bool verbose)
 }
 
 
-// Read triangles, points from Istream
-bool Foam::triSurface::read(Istream& is)
-{
-    is  >> patches_ >> storedPoints() >> storedFaces();
-
-    return true;
-}
-
-
-// Read from file in given format
-bool Foam::triSurface::read
-(
-    const fileName& name,
-    const word& ext,
-    const bool check
-)
-{
-    if (check && !exists(name))
-    {
-        FatalErrorInFunction
-            << "Cannnot read " << name << exit(FatalError);
-    }
-
-    if (ext == "gz")
-    {
-        fileName unzipName = name.lessExt();
-
-        // Do not check for existence. Let IFstream do the unzipping.
-        return read(unzipName, unzipName.ext(), false);
-    }
-    else if (ext == "ftr")
-    {
-        return read(IFstream(name)());
-    }
-    else if (ext == "stl")
-    {
-        return readSTL(name);
-    }
-    else if (ext == "stlb")
-    {
-        return readSTL(name, true);
-    }
-    else if (ext == "gts")
-    {
-        return readGTS(name);
-    }
-    else if (ext == "obj")
-    {
-        return readOBJ(name);
-    }
-    else if (ext == "off")
-    {
-        return readOFF(name);
-    }
-    else if (ext == "tri")
-    {
-        return readTRI(name);
-    }
-    else if (ext == "ac")
-    {
-        return readAC(name);
-    }
-    else if (ext == "nas")
-    {
-        return readNAS(name);
-    }
-    else if (ext == "vtk")
-    {
-        return readVTK(name);
-    }
-    else
-    {
-        FatalErrorInFunction
-            << "unknown file extension " << ext
-            << " for reading file " << name
-            << ". Supported extensions:" << nl
-            << "    " << flatOutput(readTypes_.sortedToc()) << nl
-            << exit(FatalError);
-
-        return false;
-    }
-}
-
-
-// Write to file in given format
-void Foam::triSurface::write
-(
-    const fileName& name,
-    const word& ext,
-    const bool sort
-) const
-{
-    if (ext == "ftr")
-    {
-        return write(OFstream(name)());
-    }
-    else if (ext == "stl")
-    {
-        return writeSTLASCII(sort, OFstream(name)());
-    }
-    else if (ext == "stlb")
-    {
-        std::ofstream outFile(name, std::ios::binary);
-
-        writeSTLBINARY(outFile);
-    }
-    else if (ext == "gts")
-    {
-        return writeGTS(sort, OFstream(name)());
-    }
-    else if (ext == "obj")
-    {
-        writeOBJ(sort, OFstream(name)());
-    }
-    else if (ext == "off")
-    {
-        writeOFF(sort, OFstream(name)());
-    }
-    else if (ext == "vtk")
-    {
-        std::ofstream outFile(name, std::ios::binary);
-        writeVTK(sort, outFile);
-    }
-    else if
-    (
-        ext == "inp"  // STARCD
-     || ext == "vtp"  // VTK
-    )
-    {
-        labelList faceMap;
-        List<surfZone> zoneLst = this->sortedZones(faceMap);
-
-        MeshedSurfaceProxy<labelledTri> proxy
-        (
-            this->points(),
-            this->surfFaces(),
-            zoneLst,
-            faceMap
-        );
-
-        proxy.write(name, ext);
-    }
-    else if (ext == "tri")
-    {
-        writeTRI(sort, OFstream(name)());
-    }
-    else if (ext == "ac")
-    {
-        writeAC(OFstream(name)());
-    }
-    else if (ext == "smesh")
-    {
-        writeSMESH(sort, OFstream(name)());
-    }
-    else
-    {
-        FatalErrorInFunction
-            << "unknown file extension " << ext
-            << " for writing file " << name
-            << ". Supported extensions:" << nl
-            << "    " << flatOutput(writeTypes_.sortedToc()) << nl
-            << exit(FatalError);
-    }
-}
-
-
 // Returns patch info. Sets faceMap to the indexing according to patch
 // numbers. Patch numbers start at 0.
 Foam::surfacePatchList
 Foam::triSurface::calcPatches(labelList& faceMap) const
 {
-    // Sort according to region numbers of labelledTri
-    SortableList<label> sortedRegion(size());
+    // Determine the sorted order:
+    // use sortedOrder directly (the intermediate list is discared anyhow)
 
-    forAll(sortedRegion, facei)
+    List<label> regions(size());
+    forAll(regions, facei)
     {
-        sortedRegion[facei] = operator[](facei).region();
+        regions[facei] = operator[](facei).region();
     }
-    sortedRegion.sort();
-
-    faceMap = sortedRegion.indices();
+    sortedOrder(regions, faceMap);
+    regions.clear();
 
     // Extend regions
     label maxRegion = patches_.size()-1;    // for non-compacted regions
@@ -685,6 +415,24 @@ Foam::triSurface::triSurface()
 {}
 
 
+Foam::triSurface::triSurface(const triSurface& surf)
+:
+    ParentType(surf, surf.points()),
+    patches_(surf.patches()),
+    sortedEdgeFacesPtr_(nullptr),
+    edgeOwnerPtr_(nullptr)
+{}
+
+
+Foam::triSurface::triSurface(triSurface&& surf)
+:
+    triSurface()
+{
+    FaceListType::operator=(std::move(static_cast<FaceListType&>(surf)));
+    storedPoints() = std::move(surf.storedPoints());
+    patches_ = std::move(surf.patches());
+}
+
 
 Foam::triSurface::triSurface
 (
@@ -776,47 +524,6 @@ Foam::triSurface::triSurface(const fileName& name, const scalar scaleFactor)
 }
 
 
-Foam::triSurface::triSurface(Istream& is)
-:
-    ParentType(List<Face>(), pointField()),
-    patches_(),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
-{
-    read(is);
-
-    setDefaultPatches();
-}
-
-
-Foam::triSurface::triSurface(const Time& d)
-:
-    ParentType(List<Face>(), pointField()),
-    patches_(),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
-{
-    fileName foamFile(d.caseName() + ".ftr");
-
-    fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
-
-    IFstream foamStream(foamPath);
-
-    read(foamStream);
-
-    setDefaultPatches();
-}
-
-
-Foam::triSurface::triSurface(const triSurface& ts)
-:
-    ParentType(ts, ts.points()),
-    patches_(ts.patches()),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
-{}
-
-
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 Foam::triSurface::~triSurface()
@@ -844,12 +551,22 @@ void Foam::triSurface::clearPatchMeshAddr()
 void Foam::triSurface::clearOut()
 {
     ParentType::clearOut();
-
     clearTopology();
     clearPatchMeshAddr();
 }
 
 
+void Foam::triSurface::swap(triSurface& surf)
+{
+    clearOut();
+    surf.clearOut();
+
+    FaceListType::swap(static_cast<FaceListType&>(surf));
+    storedPoints().swap(surf.storedPoints());
+    patches_.swap(surf.patches());
+}
+
+
 const Foam::labelListList& Foam::triSurface::sortedEdgeFaces() const
 {
     if (!sortedEdgeFacesPtr_)
@@ -980,24 +697,18 @@ void Foam::triSurface::markZone
         // Pick up neighbours of changedFaces
         DynamicList<label> newChangedFaces(2*changedFaces.size());
 
-        forAll(changedFaces, i)
+        for (const label facei : changedFaces)
         {
-            label facei = changedFaces[i];
-
             const labelList& fEdges = faceEdges()[facei];
 
-            forAll(fEdges, i)
+            for (const label edgei : fEdges)
             {
-                label edgeI = fEdges[i];
-
-                if (!borderEdge[edgeI])
+                if (!borderEdge[edgei])
                 {
-                    const labelList& eFaces = edgeFaces()[edgeI];
+                    const labelList& eFaces = edgeFaces()[edgei];
 
-                    forAll(eFaces, j)
+                    for (const label nbrFacei : eFaces)
                     {
-                        label nbrFacei = eFaces[j];
-
                         if (faceZone[nbrFacei] == -1)
                         {
                             faceZone[nbrFacei] = currentZone;
@@ -1102,13 +813,12 @@ void Foam::triSurface::subsetMeshMap
             // Renumber labels for face
             const triSurface::FaceType& f = locFaces[oldFacei];
 
-            forAll(f, fp)
+            for (const label verti : f)
             {
-                label labI = f[fp];
-                if (!pointHad[labI])
+                if (!pointHad[verti])
                 {
-                    pointHad[labI] = true;
-                    pointMap[pointi++] = labI;
+                    pointHad[verti] = true;
+                    pointMap[pointi++] = verti;
                 }
             }
         }
@@ -1162,99 +872,55 @@ Foam::triSurface Foam::triSurface::subsetMesh
 }
 
 
-void Foam::triSurface::write
+void Foam::triSurface::reset
 (
-    const fileName& name,
-    const bool sortByRegion
-) const
-{
-    write(name, name.ext(), sortByRegion);
-}
-
-
-void Foam::triSurface::write(Ostream& os) const
-{
-    os  << patches() << endl;
-
-    //Note: Write with global point numbering
-    os  << points() << nl
-        << static_cast<const List<labelledTri>&>(*this) << endl;
-
-    // Check state of Ostream
-    os.check(FUNCTION_NAME);
-}
-
-
-void Foam::triSurface::write(const Time& d) const
+    const Xfer<List<labelledTri>>& triangles,
+    const geometricSurfacePatchList& patches,
+    const Xfer<List<point>>& points
+)
 {
-    fileName foamFile(d.caseName() + ".ftr");
-
-    fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
+    clearOut();
 
-    OFstream foamStream(foamPath);
+    this->storedFaces().transfer(triangles());
+    this->storedPoints().transfer(points());
 
-    write(foamStream);
+    patches_ = patches;
 }
 
 
-void Foam::triSurface::writeStats(Ostream& os) const
+void Foam::triSurface::reset(MeshedSurface<labelledTri>& input)
 {
-    // Unfortunately nPoints constructs meshPoints() so do compact version
-    // ourselves.
-    PackedBoolList pointIsUsed(points().size());
+    const auto& zones = input.surfZones();
 
-    label nPoints = 0;
-    boundBox bb(boundBox::invertedBox);
-    labelHashSet regionsUsed;
-
-    for (const triSurface::FaceType& f : *this)
+    geometricSurfacePatchList patches(zones.size());
+    forAll(zones, zonei)
     {
-        regionsUsed.insert(f.region());
-
-        forAll(f, fp)
-        {
-            const label pointi = f[fp];
-            if (pointIsUsed.set(pointi, 1))
-            {
-                bb.add(points()[pointi]);
-                ++nPoints;
-            }
-        }
+        patches[zonei] = geometricSurfacePatch(zones[zonei]);
     }
 
-    os  << "Triangles    : " << size()
-        << " in " << regionsUsed.size() <<  " region(s)" << nl
-        << "Vertices     : " << nPoints << nl
-        << "Bounding Box : " << bb << endl;
+    this->reset(input.xferFaces(), patches, input.xferPoints());
 }
 
 
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
-void Foam::triSurface::operator=(const triSurface& ts)
+void Foam::triSurface::operator=(const triSurface& surf)
 {
-    List<labelledTri>::operator=(ts);
     clearOut();
-    storedPoints() = ts.points();
-    patches_ = ts.patches();
-}
-
-
-// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
-Foam::Istream& Foam::operator>>(Istream& is, triSurface& sm)
-{
-    sm.clearOut();
-    sm.read(is);
-    sm.setDefaultPatches();
-    return is;
+    FaceListType::operator=(static_cast<const FaceListType&>(surf));
+    storedPoints() = surf.points();
+    patches_ = surf.patches();
 }
 
 
-Foam::Ostream& Foam::operator<<(Ostream& os, const triSurface& sm)
+void Foam::triSurface::operator=(triSurface&& surf)
 {
-    sm.write(os);
-    return os;
+    clearOut();
+
+    FaceListType::operator=(std::move(static_cast<FaceListType&>(surf)));
+    storedPoints() = std::move(surf.storedPoints());
+    patches_ = std::move(surf.patches());
 }
 
 
diff --git a/src/surfMesh/triSurface/triSurface.H b/src/surfMesh/triSurface/triSurface.H
index a9ac604d56a9248df30710240b7fc5d00b195730..89b8e46e883a87dcef915b40a3651e042949fe28 100644
--- a/src/surfMesh/triSurface/triSurface.H
+++ b/src/surfMesh/triSurface/triSurface.H
@@ -48,19 +48,21 @@ SourceFiles
 namespace Foam
 {
 
+// Forward declarations
+
 class Time;
 class IFstream;
 class surfZone;
+class triSurface;
 
-// Forward declaration of friend functions and operators
+template<class Face> class MeshedSurface;
 
-class triSurface;
 Istream& operator>>(Istream&, triSurface&);
 Ostream& operator<<(Ostream&, const triSurface&);
 
 
 /*---------------------------------------------------------------------------*\
-                           Class triSurface Declaration
+                         Class triSurface Declaration
 \*---------------------------------------------------------------------------*/
 
 class triSurface
@@ -83,15 +85,13 @@ class triSurface
 
     // Private data
 
-        //- The number of bytes in the STL header
-        static const int STLheaderSize = 80;
-
-        //- Patch information (face ordering nFaces/startFace only used
-        //  during reading and writing)
+        //- Patch information
+        //  (face ordering nFaces/startFace only used during reading, writing)
         geometricSurfacePatchList patches_;
 
-        static const wordHashSet readTypes_;
-        static const wordHashSet writeTypes_;
+        static wordHashSet readTypes_;
+
+        static wordHashSet writeTypes_;
 
 
     // Demand driven private data.
@@ -100,7 +100,7 @@ class triSurface
         mutable labelListList* sortedEdgeFacesPtr_;
 
         //- Label of face that 'owns' edge (i.e. e.vec() is righthanded walk
-        //  along face)
+        //- along face)
         mutable labelList* edgeOwnerPtr_;
 
 
@@ -112,8 +112,9 @@ class triSurface
         //- Calculate owner
         void calcEdgeOwner() const;
 
-        //- Sort faces according to region. Returns patch list
-        //  and sets faceMap to index of labelledTri inside *this.
+        //- Sort faces according to region.
+        //  Returns patch list and sets faceMap to index of labelledTri
+        //  inside *this.
         surfacePatchList calcPatches(labelList& faceMap) const;
 
         //- Sets default values for patches
@@ -127,57 +128,38 @@ class triSurface
             const bool verbose = false
         );
 
-        //- Read in Foam format
-        bool read(Istream&);
-
-        //- Generic read routine. Chooses reader based on extension.
-        bool read(const fileName&, const word& ext, const bool check = true);
-
-        bool readSTL(const fileName&, bool forceBinary=false);
-        bool readGTS(const fileName&);
-        bool readOBJ(const fileName&);
-        bool readOFF(const fileName&);
-        bool readTRI(const fileName&);
-        bool readAC(const fileName&);
-        bool readNAS(const fileName&);
-        bool readVTK(const fileName&);
-
-        //- Generic write routine. Chooses writer based on extension.
-        void write(const fileName&, const word& ext, const bool sort) const;
+        //- Read in OpenFOAM format
+        bool read(Istream& is);
 
-        //- Write to Ostream in ASCII STL format.
-        //  Each region becomes 'solid' 'endsolid' block.
-        void writeSTLASCII(const bool writeSorted, Ostream&) const;
+        //- Read in STL format
+        bool readSTL(const fileName& filename, bool forceBinary=false);
 
-        //- Write to std::ostream in BINARY STL format
-        void writeSTLBINARY(std::ostream&) const;
-
-        //- Write to Ostream in GTS (Gnu Tri Surface library)
-        //  format.
-        void writeGTS(const bool writeSorted, Ostream&) const;
-
-        //- Write to Ostream in OBJ (Lightwave) format.
-        //  writeSorted=true: sort faces acc. to region and write as single
-        //  group. =false: write in normal order.
-        void writeOBJ(const bool writeSorted, Ostream&) const;
-
-        //- Write to Ostream in OFF (Geomview) format.
-        //  writeSorted=true: sort faces acc. to region and write as single
-        //  group. =false: write in normal order.
-        void writeOFF(const bool writeSorted, Ostream&) const;
+        //- Generic read routine. Chooses reader based on extension.
+        bool read
+        (
+            const fileName& filename,
+            const word& ext,
+            const bool check = true
+        );
 
-        //- Write to VTK legacy format.
-        void writeVTK(const bool writeSorted, std::ostream& os) const;
+        //- Write STL ASCII format.
+        //  Each region becomes a 'solid' 'endsolid' block.
+        void writeSTLASCII(const fileName& filename, const bool sort) const;
 
-        //- Write to Ostream in TRI (AC3D) format
-        //  Ac3d .tri format (unmerged triangle format)
-        void writeTRI(const bool writeSorted, Ostream&) const;
+        //- Write STL BINARY format
+        void writeSTLBINARY(const fileName& filename) const;
 
-        //- Write to Ostream in SMESH (tetgen) format
-        void writeSMESH(const bool writeSorted, Ostream&) const;
+        //- Write GTS (Gnu Tri Surface library) format.
+        void writeGTS(const fileName& filename, const bool sort) const;
 
-        //- Write to Ostream in AC3D format. Always sorted by patch.
-        void writeAC(Ostream&) const;
+        //- Generic write routine. Chooses writer based on extension.
+        //  The sort option may not have an effect.
+        void write
+        (
+            const fileName& filename,
+            const word& ext,
+            const bool sort
+        ) const;
 
 
     // Static private functions
@@ -185,29 +167,26 @@ class triSurface
         //- Convert faces to labelledTri. All get same region.
         static List<labelledTri> convertToTri
         (
-            const faceList&,
+            const faceList& faces,
             const label defaultRegion = 0
         );
 
         //- Convert triFaces to labelledTri. All get same region.
         static List<labelledTri> convertToTri
         (
-            const triFaceList&,
+            const triFaceList& faces,
             const label defaultRegion = 0
         );
 
         //- Helper function to print triangle info
         static void printTriangle
         (
-            Ostream&,
-            const Foam::string& pre,
-            const labelledTri&,
-            const pointField&
+            Ostream& os,
+            const string& pre,
+            const labelledTri& f,
+            const pointField& points
         );
 
-        //- Read non-comment line
-        static string getLineNoComment(IFstream&);
-
 
 protected:
 
@@ -233,7 +212,6 @@ public:
         //- Placeholder only, but do not remove - it is needed for GeoMesh
         typedef bool BoundaryMesh;
 
-
         //- Runtime type information
         ClassName("triSurface");
 
@@ -252,7 +230,10 @@ public:
         //- Can we write this file format?
         static bool canWriteType(const word& ext, const bool verbose=false);
 
+        //- Known readable file-types
         static const wordHashSet& readTypes();
+
+        //- Known writable file-types
         static const wordHashSet& writeTypes();
 
 
@@ -261,6 +242,12 @@ public:
         //- Construct null
         triSurface();
 
+        //- Copy construct
+        triSurface(const triSurface& surf);
+
+        //- Move construct
+        triSurface(triSurface&& surf);
+
         //- Construct from triangles, patches, points.
         triSurface
         (
@@ -293,8 +280,8 @@ public:
             const pointField& points
         );
 
-        //- Construct from triangles, points. Set region to 0 and default
-        //  patchName.
+        //- Construct from triangles, points Set region to 0 and default
+        //- patchName.
         triSurface
         (
             const triFaceList& triangles,
@@ -311,21 +298,21 @@ public:
         //- Construct from objectRegistry
         triSurface(const Time& d);
 
-        //- Construct as copy
-        triSurface(const triSurface& ts);
-
 
     //- Destructor
     virtual ~triSurface();
 
+
+    // Member Functions
+
         void clearOut();
 
         void clearTopology();
 
         void clearPatchMeshAddr();
 
+        void swap(triSurface& surf);
 
-    // Member Functions
 
       // Access
 
@@ -425,8 +412,8 @@ public:
             labelList& faceZone
         ) const;
 
-        //- 'Create' sub mesh, including only faces for which
-        //  boolList entry is true
+        //- 'Create' sub mesh, including only faces for which boolList
+        //- entry is true
         //  Sets: pointMap: from new to old localPoints
         //        faceMap: new to old faces
         void subsetMeshMap
@@ -452,6 +439,19 @@ public:
         //- Transfer stored points to an Xfer container
         Xfer<List<point>> xferPoints();
 
+        //- Alter contents by transferring (triangles, points) components.
+        //  Patch information is small and therefore just copied.
+        void reset
+        (
+            const Xfer<List<labelledTri>>& triangles,
+            const geometricSurfacePatchList& patches,
+            const Xfer<List<point>>& points
+        );
+
+        //- Alter contents by transferring (triangles, points) components.
+        //  Patch information is small and therefore just copied.
+        void reset(MeshedSurface<labelledTri>& input);
+
 
       // Write
 
@@ -470,7 +470,11 @@ public:
 
     // Member operators
 
-        void operator=(const triSurface&);
+        //- Copy assignment
+        void operator=(const triSurface& surf);
+
+        //- Move assignment
+        void operator=(triSurface&& surf);
 
 
     // IOstream Operators
diff --git a/src/surfMesh/triSurface/triSurfaceAddressing.C b/src/surfMesh/triSurface/triSurfaceAddressing.C
index ad10578404bc7f68e7cd1e680a5d371b4136b952..0ff563139c3927842b1c6dcd391ceb2a5f78bdc9 100644
--- a/src/surfMesh/triSurface/triSurfaceAddressing.C
+++ b/src/surfMesh/triSurface/triSurfaceAddressing.C
@@ -29,7 +29,6 @@ Description
 
 #include "triSurface.H"
 #include "HashTable.H"
-#include "SortableList.H"
 #include "transform.H"
 #include "PatchTools.H"
 
diff --git a/src/surfMesh/triSurface/triSurfaceIO.C b/src/surfMesh/triSurface/triSurfaceIO.C
new file mode 100644
index 0000000000000000000000000000000000000000..3e4fdc2a002412370d323a1c043617ec123192fa
--- /dev/null
+++ b/src/surfMesh/triSurface/triSurfaceIO.C
@@ -0,0 +1,375 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 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 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "triSurface.H"
+#include "Fstream.H"
+#include "Time.H"
+#include "boundBox.H"
+#include "PackedBoolList.H"
+#include "surfZoneList.H"
+#include "surfaceFormatsCore.H"
+#include "MeshedSurfaceProxy.H"
+#include "MeshedSurface.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+Foam::wordHashSet Foam::triSurface::readTypes_;
+Foam::wordHashSet Foam::triSurface::writeTypes_;
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+const Foam::wordHashSet& Foam::triSurface::readTypes()
+{
+    // Stop-gap measure until reading is handled more generally
+    if (readTypes_.empty())
+    {
+        readTypes_ = { "ftr", "stl", "stlb" };
+        readTypes_ += UnsortedMeshedSurface<labelledTri>::readTypes();
+        readTypes_ += MeshedSurface<labelledTri>::readTypes();
+    }
+
+    return readTypes_;
+}
+
+
+const Foam::wordHashSet& Foam::triSurface::writeTypes()
+{
+    // Stop-gap measure until writing is handled more generally
+    if (writeTypes_.empty())
+    {
+        writeTypes_ = { "ftr", "stl", "stlb", "gts" };
+        writeTypes_ += MeshedSurfaceProxy<labelledTri>::writeTypes();
+    }
+
+    return writeTypes_;
+}
+
+
+bool Foam::triSurface::canReadType(const word& ext, const bool verbose)
+{
+    return fileFormats::surfaceFormatsCore::checkSupport
+    (
+        readTypes(),
+        ext,
+        verbose,
+        "reading"
+    );
+}
+
+
+bool Foam::triSurface::canWriteType(const word& ext, const bool verbose)
+{
+    return fileFormats::surfaceFormatsCore::checkSupport
+    (
+        writeTypes(),
+        ext,
+        verbose,
+        "writing"
+    );
+}
+
+
+bool Foam::triSurface::canRead(const fileName& name, const bool verbose)
+{
+    word ext = name.ext();
+    if (ext == "gz")
+    {
+        ext = name.lessExt().ext();
+    }
+    return canReadType(ext, verbose);
+}
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::triSurface::printTriangle
+(
+    Ostream& os,
+    const string& pre,
+    const labelledTri& f,
+    const pointField& points
+)
+{
+    os
+        << pre.c_str() << "vertex numbers:"
+        << f[0] << ' ' << f[1] << ' ' << f[2] << endl
+        << pre.c_str() << "vertex coords :"
+        << points[f[0]] << ' ' << points[f[1]] << ' ' << points[f[2]]
+        << pre.c_str() << "region        :" << f.region() << endl
+        << endl;
+}
+
+
+bool Foam::triSurface::read(Istream& is)
+{
+    // Read triangles, points from Istream
+    is  >> patches_ >> storedPoints() >> storedFaces();
+
+    return true;
+}
+
+
+bool Foam::triSurface::read
+(
+    const fileName& name,
+    const word& ext,
+    const bool check
+)
+{
+    if (check && !exists(name))
+    {
+        FatalErrorInFunction
+            << "Cannnot read " << name << exit(FatalError);
+    }
+
+    if (ext == "gz")
+    {
+        fileName unzipName = name.lessExt();
+
+        // Do not check for existence. Let IFstream do the unzipping.
+        return read(unzipName, unzipName.ext(), false);
+    }
+
+    // Hard-coded readers
+    if (ext == "ftr")
+    {
+        return read(IFstream(name)());
+    }
+    else if (ext == "stl")
+    {
+        return readSTL(name);  // ASCII
+    }
+    else if (ext == "stlb")
+    {
+        return readSTL(name, true); // Force BINARY
+    }
+
+    // UnsortedMeshedSurface
+    {
+        using proxyType = UnsortedMeshedSurface<labelledTri>;
+        if (proxyType::readTypes().found(ext))
+        {
+            reset(proxyType::New(name, ext)());
+            return true;
+        }
+    }
+
+    // MeshedSurface
+    {
+        using proxyType = MeshedSurface<labelledTri>;
+        if (proxyType::readTypes().found(ext))
+        {
+            reset(proxyType::New(name, ext)());
+            return true;
+        }
+    }
+
+
+    FatalErrorInFunction
+        << "unknown file extension " << ext
+        << " for reading file " << name
+        << ". Supported extensions:" << nl
+        << "    " << flatOutput(readTypes_.sortedToc()) << nl
+        << exit(FatalError);
+
+    return false;
+}
+
+
+void Foam::triSurface::write
+(
+    const fileName& name,
+    const word& ext,
+    const bool sort
+) const
+{
+    // Hard-coded readers
+
+    if (ext == "ftr")
+    {
+        OFstream os(name);
+        write(os);
+    }
+    else if (ext == "stl")
+    {
+        writeSTLASCII(name, sort);
+    }
+    else if (ext == "stlb")
+    {
+        writeSTLBINARY(name);
+    }
+    else if (ext == "gts")
+    {
+        writeGTS(name, sort);
+    }
+    else if (MeshedSurfaceProxy<labelledTri>::canWriteType(ext))
+    {
+        labelList faceMap;
+        List<surfZone> zoneLst = this->sortedZones(faceMap);
+
+        MeshedSurfaceProxy<labelledTri> proxy
+        (
+            this->points(),
+            this->surfFaces(),
+            zoneLst,
+            faceMap
+        );
+
+        proxy.write(name, ext);
+    }
+    else
+    {
+        FatalErrorInFunction
+            << "unknown file extension " << ext
+            << " for writing file " << name
+            << ". Supported extensions:" << nl
+            << "    " << flatOutput(writeTypes_.sortedToc()) << nl
+            << exit(FatalError);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::triSurface::triSurface(Istream& is)
+:
+    ParentType(List<Face>(), pointField()),
+    patches_(),
+    sortedEdgeFacesPtr_(nullptr),
+    edgeOwnerPtr_(nullptr)
+{
+    read(is);
+
+    setDefaultPatches();
+}
+
+
+Foam::triSurface::triSurface(const Time& d)
+:
+    ParentType(List<Face>(), pointField()),
+    patches_(),
+    sortedEdgeFacesPtr_(nullptr),
+    edgeOwnerPtr_(nullptr)
+{
+    fileName foamFile(d.caseName() + ".ftr");
+
+    fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
+
+    IFstream foamStream(foamPath);
+
+    read(foamStream);
+
+    setDefaultPatches();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::triSurface::write
+(
+    const fileName& name,
+    const bool sortByRegion
+) const
+{
+    write(name, name.ext(), sortByRegion);
+}
+
+
+void Foam::triSurface::write(Ostream& os) const
+{
+    os  << patches() << nl;
+
+    //Note: Write with global point numbering
+    os  << points() << nl
+        << static_cast<const List<labelledTri>&>(*this) << nl;
+
+    // Check state of Ostream
+    os.check(FUNCTION_NAME);
+}
+
+
+void Foam::triSurface::write(const Time& d) const
+{
+    fileName foamFile(d.caseName() + ".ftr");
+
+    fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
+
+    OFstream foamStream(foamPath);
+
+    write(foamStream);
+}
+
+
+void Foam::triSurface::writeStats(Ostream& os) const
+{
+    // Unfortunately nPoints constructs meshPoints() so do compact version
+    // ourselves.
+    PackedBoolList pointIsUsed(points().size());
+
+    label nPoints = 0;
+    boundBox bb(boundBox::invertedBox);
+    labelHashSet regionsUsed;
+
+    for (const triSurface::FaceType& f : *this)
+    {
+        regionsUsed.insert(f.region());
+
+        forAll(f, fp)
+        {
+            const label pointi = f[fp];
+            if (pointIsUsed.set(pointi, 1))
+            {
+                bb.add(points()[pointi]);
+                ++nPoints;
+            }
+        }
+    }
+
+    os  << "Triangles    : " << size()
+        << " in " << regionsUsed.size() <<  " region(s)" << nl
+        << "Vertices     : " << nPoints << nl
+        << "Bounding Box : " << bb << endl;
+}
+
+
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
+
+Foam::Istream& Foam::operator>>(Istream& is, triSurface& sm)
+{
+    sm.clearOut();
+    sm.read(is);
+    sm.setDefaultPatches();
+    return is;
+}
+
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const triSurface& sm)
+{
+    sm.write(os);
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/surfMesh/triSurface/stitchTriangles.C b/src/surfMesh/triSurface/triSurfaceStitch.C
similarity index 88%
rename from src/surfMesh/triSurface/stitchTriangles.C
rename to src/surfMesh/triSurface/triSurfaceStitch.C
index 053eadd085d5e3f939f42b9727b9d8e5be755314..1a345cac052b0f4a16d62785302b2fd40e78ea4c 100644
--- a/src/surfMesh/triSurface/stitchTriangles.C
+++ b/src/surfMesh/triSurface/triSurfaceStitch.C
@@ -79,8 +79,8 @@ bool Foam::triSurface::stitchTriangles
             {
                 Pout<< "stitchTriangles : "
                     << "Removing triangle " << i
-                    << " with non-unique vertices." << endl
-                    << "    vertices   :" << newTri << endl
+                    << " with non-unique vertices." << nl
+                    << "    vertices   :" << newTri << nl
                     << "    coordinates:" << newTri.points(ps)
                     << endl;
             }
@@ -105,16 +105,13 @@ bool Foam::triSurface::stitchTriangles
 
             label nPoints = 0;
 
-            forAll(*this, i)
+            for (const labelledTri& f : *this)
             {
-                const triSurface::FaceType& f = operator[](i);
-
-                forAll(f, fp)
+                for (const label pointi : f)
                 {
-                    label pointi = f[fp];
                     if (pointIsUsed.set(pointi, 1))
                     {
-                        nPoints++;
+                        ++nPoints;
                     }
                 }
             }
@@ -135,15 +132,14 @@ bool Foam::triSurface::stitchTriangles
                 ps.setSize(newPointi);
 
                 newTriangleI = 0;
-                forAll(*this, i)
+                for (const labelledTri& f : *this)
                 {
-                    const labelledTri& tri = operator[](i);
                     operator[](newTriangleI++) = labelledTri
                     (
-                        pointMap[tri[0]],
-                        pointMap[tri[1]],
-                        pointMap[tri[2]],
-                        tri.region()
+                        pointMap[f[0]],
+                        pointMap[f[1]],
+                        pointMap[f[2]],
+                        f.region()
                     );
                 }
             }