From 1f823838dcb90b38b1144928abcd608aa30c5871 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Fri, 14 Nov 2008 08:50:35 +0100
Subject: [PATCH] surfMesh code refactoring

---
 src/surfMesh/Make/files                       |   1 +
 src/surfMesh/MeshedSurface/MeshedSurface.C    | 114 +-------
 src/surfMesh/MeshedSurface/MeshedSurface.H    |   4 +-
 .../UnsortedMeshedSurface.C                   | 217 +--------------
 .../UnsortedMeshedSurface.H                   |  17 +-
 .../surfaceFormats/ac3d/AC3DsurfaceFormat.C   | 141 ----------
 .../surfaceFormats/ac3d/AC3DsurfaceFormat.H   |  28 +-
 .../ac3d/AC3DsurfaceFormatCore.C              | 174 ++++++++++++
 .../ac3d/AC3DsurfaceFormatCore.H              | 111 ++++++++
 .../surfaceFormats/gts/GTSsurfaceFormat.H     |   2 +-
 .../surfaceFormats/nas/NASsurfaceFormat.C     |  26 --
 .../surfaceFormats/nas/NASsurfaceFormat.H     |   7 +-
 .../surfaceFormats/nas/NASsurfaceFormatCore.C |  63 +++++
 .../surfaceFormats/nas/NASsurfaceFormatCore.H |  89 ++++++
 .../surfaceFormats/off/OFFsurfaceFormat.H     |   2 +-
 .../surfaceFormats/stl/STLsurfaceFormatCore.H |   1 +
 .../surfaceFormats/surfaceFormatsCore.C       | 260 ++++++++++++++++++
 .../surfaceFormats/surfaceFormatsCore.H       | 127 +++++++++
 18 files changed, 860 insertions(+), 524 deletions(-)
 create mode 100644 src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
 create mode 100644 src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
 create mode 100644 src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.C
 create mode 100644 src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.H
 create mode 100644 src/surfMesh/surfaceFormats/surfaceFormatsCore.C
 create mode 100644 src/surfMesh/surfaceFormats/surfaceFormatsCore.H

diff --git a/src/surfMesh/Make/files b/src/surfMesh/Make/files
index c7be4a4f32c..5273d674043 100644
--- a/src/surfMesh/Make/files
+++ b/src/surfMesh/Make/files
@@ -6,6 +6,7 @@ MeshedSurface/MeshedSurfaces.C
 UnsortedMeshedSurface/UnsortedMeshedSurfaces.C
 
 surfaceFormats = surfaceFormats
+$(surfaceFormats)/surfaceFormatsCore.C
 $(surfaceFormats)/ac3d/AC3DsurfaceFormatRunTime.C
 $(surfaceFormats)/ftr/FTRsurfaceFormatRunTime.C
 $(surfaceFormats)/gts/GTSsurfaceFormatRunTime.C
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.C b/src/surfMesh/MeshedSurface/MeshedSurface.C
index b7a3a2f5f9d..f9733790049 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.C
@@ -41,122 +41,28 @@ License
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-// File extension for 'native' raw format
-#undef  nativeSurfaceExt
-#define nativeSurfaceExt "ofs"
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 template<class Face>
 Foam::fileName Foam::MeshedSurface<Face>::triSurfInstance(const Time& d)
 {
-    fileName foamName(d.caseName() + "." + nativeSurfaceExt);
-
-    // Search back through the time directories list to find the time
-    // closest to and lower than current time
-
-    instantList ts = d.times();
-    label i;
-
-    for (i=ts.size()-1; i>=0; i--)
-    {
-        if (ts[i].value() <= d.timeOutputValue())
-        {
-            break;
-        }
-    }
-
-    // Noting that the current directory has already been searched
-    // for mesh data, start searching from the previously stored time directory
-
-    if (i>=0)
-    {
-        for (label j=i; j>=0; j--)
-        {
-            if (file(d.path()/ts[j].name()/typeName/foamName))
-            {
-                if (debug)
-                {
-                    Pout<< " MeshedSurface::triSurfInstance(const Time& d)"
-                        << "reading " << foamName
-                        << " from " << ts[j].name()/typeName
-                        << endl;
-                }
-
-                return ts[j].name();
-            }
-        }
-    }
-
-    if (debug)
-    {
-        Pout<< " MeshedSurface::triSurfInstance(const Time& d)"
-            << "reading " << foamName
-            << " from constant/" << endl;
-    }
-
-    return "constant";
+    return triSurfInstance(d, typeName);
 }
 
 
 template<class Face>
 Foam::fileName Foam::MeshedSurface<Face>::triSurfName(const Time& d)
 {
-    fileName foamName(d.caseName() + "." + nativeSurfaceExt);
-
-    // Search back through the time directories list to find the time
-    // closest to and lower than current time
-
-    instantList ts = d.times();
-    label i;
-
-    for (i=ts.size()-1; i>=0; i--)
-    {
-        if (ts[i].value() <= d.timeOutputValue())
-        {
-            break;
-        }
-    }
-
-    // Noting that the current directory has already been searched
-    // for mesh data, start searching from the previously stored time directory
-
-    if (i>=0)
-    {
-        for (label j=i; j>=0; j--)
-        {
-            fileName testName(d.path()/ts[j].name()/typeName/foamName);
-
-            if (file(testName))
-            {
-                if (debug)
-                {
-                    Pout<< " MeshedSurface::triSurfName(const Time& d)"
-                        << "reading " << foamName
-                        << " from " << ts[j].name()/typeName
-                        << endl;
-                }
-
-                return testName;
-            }
-        }
-    }
-
-    if (debug)
-    {
-        Pout<< " MeshedSurface::triSurfName(const Time& d)"
-            << "reading " << foamName
-            << " from constant/" << endl;
-    }
-
-    return d.path()/"constant"/typeName/foamName;
+    return triSurfName(d, typeName);
 }
 
+
 template<class Face>
 bool Foam::MeshedSurface<Face>::canRead(const word& ext, const bool verbose)
 {
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         return true;
     }
@@ -178,7 +84,7 @@ bool Foam::MeshedSurface<Face>::canWrite(const word& ext, const bool verbose)
     }
 
     // handle 'native' format directly
-    if (fExt == nativeSurfaceExt)
+    if (isNative(fExt))
     {
         return true;
     }
@@ -197,7 +103,7 @@ bool Foam::MeshedSurface<Face>::canWrite(const word& ext, const bool verbose)
 
             Info<<"Unknown file extension for writing: " << fExt << nl;
             // compact output:
-            Info<<"Valid types: ( " << nativeSurfaceExt;
+            Info<<"Valid types: ( " << nativeExt;
             forAll(known, i)
             {
                 Info<<" " << known[i];
@@ -229,7 +135,7 @@ void Foam::MeshedSurface<Face>::write
     const word ext = fName.ext();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         surf.write(OFstream(fName)());
         return;
@@ -899,7 +805,7 @@ bool Foam::MeshedSurface<Face>::read
     const word ext = fName.ext();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         return read(IFstream(fName)());
     }
@@ -923,7 +829,7 @@ bool Foam::MeshedSurface<Face>::read
     clear();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         return read(IFstream(fName)());
     }
@@ -975,6 +881,4 @@ void Foam::MeshedSurface<Face>::operator=(const MeshedSurface& surf)
 #include "MeshedSurfaceIO.C"
 #include "MeshedSurfaceNew.C"
 
-#undef  nativeSurfaceExt
-
 // ************************************************************************* //
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.H b/src/surfMesh/MeshedSurface/MeshedSurface.H
index bc7e59a1b1c..6e1851b1b17 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.H
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.H
@@ -48,6 +48,7 @@ SourceFiles
 #include "PrimitivePatchExtra.H"
 #include "boolList.H"
 #include "surfGroupList.H"
+#include "surfaceFormatsCore.H"
 #include "xfer.H"
 #include "face.H"
 #include "triFace.H"
@@ -78,7 +79,8 @@ template<class Face>
 template<class Face>
 class MeshedSurface
 :
-    public PrimitivePatchExtra<Face, ::Foam::List, pointField, point>
+    public PrimitivePatchExtra<Face, ::Foam::List, pointField, point>,
+    public fileFormats::surfaceFormatsCore
 {
     friend class UnsortedMeshedSurface<Face>;
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
index 1e20018eae2..0280a2f3542 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
@@ -37,128 +37,19 @@ License
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-// File extension for 'native' raw format
-#undef  nativeSurfaceExt
-#define nativeSurfaceExt "ofs"
-
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
-template<class Face>
-Foam::string Foam::UnsortedMeshedSurface<Face>::getLineNoComment(IFstream& is)
-{
-    string line;
-    do
-    {
-        is.getLine(line);
-    }
-    while ((line.size() == 0 || line[0] == '#') && is.good());
-
-    return line;
-}
-
 template<class Face>
 Foam::fileName Foam::UnsortedMeshedSurface<Face>::triSurfInstance(const Time& d)
 {
-    fileName foamName(d.caseName() + "." + nativeSurfaceExt);
-
-    // Search back through the time directories list to find the time
-    // closest to and lower than current time
-
-    instantList ts = d.times();
-    label i;
-
-    for (i=ts.size()-1; i>=0; i--)
-    {
-        if (ts[i].value() <= d.timeOutputValue())
-        {
-            break;
-        }
-    }
-
-    // Noting that the current directory has already been searched
-    // for mesh data, start searching from the previously stored time directory
-
-    if (i>=0)
-    {
-        for (label j=i; j>=0; j--)
-        {
-            if (file(d.path()/ts[j].name()/typeName/foamName))
-            {
-                if (debug)
-                {
-                    Pout<< " UnsortedMeshedSurface::triSurfInstance(const Time& d)"
-                        << "reading " << foamName
-                        << " from " << ts[j].name()/typeName
-                        << endl;
-                }
-
-                return ts[j].name();
-            }
-        }
-    }
-
-    if (debug)
-    {
-        Pout<< " UnsortedMeshedSurface::triSurfInstance(const Time& d)"
-            << "reading " << foamName
-            << " from constant/" << endl;
-    }
-
-    return "constant";
+    return triSurfInstance(d, typeName);
 }
 
 
 template<class Face>
 Foam::fileName Foam::UnsortedMeshedSurface<Face>::triSurfName(const Time& d)
 {
-    fileName foamName(d.caseName() + "." + nativeSurfaceExt);
-
-    // Search back through the time directories list to find the time
-    // closest to and lower than current time
-
-    instantList ts = d.times();
-    label i;
-
-    for (i=ts.size()-1; i>=0; i--)
-    {
-        if (ts[i].value() <= d.timeOutputValue())
-        {
-            break;
-        }
-    }
-
-    // Noting that the current directory has already been searched
-    // for mesh data, start searching from the previously stored time directory
-
-    if (i>=0)
-    {
-        for (label j=i; j>=0; j--)
-        {
-            fileName testName(d.path()/ts[j].name()/typeName/foamName);
-
-            if (file(testName))
-            {
-                if (debug)
-                {
-                    Pout<< " UnsortedMeshedSurface::triSurfName(const Time& d)"
-                        << "reading " << foamName
-                        << " from " << ts[j].name()/typeName
-                        << endl;
-                }
-
-                return testName;
-            }
-        }
-    }
-
-    if (debug)
-    {
-        Pout<< " UnsortedMeshedSurface::triSurfName(const Time& d)"
-            << "reading " << foamName
-            << " from constant/" << endl;
-    }
-
-    return d.path()/"constant"/typeName/foamName;
+    return triSurfName(d, typeName);
 }
 
 
@@ -179,7 +70,7 @@ bool Foam::UnsortedMeshedSurface<Face>::canRead
     }
 
     // handle 'native' format directly
-    if (fExt == nativeSurfaceExt)
+    if (isNative(fExt))
     {
         return true;
     }
@@ -199,7 +90,7 @@ bool Foam::UnsortedMeshedSurface<Face>::canRead
 
             Info<<"Unknown file extension for reading: " << fExt << nl;
             // compact output:
-            Info<<"Valid types: ( " << nativeSurfaceExt;
+            Info<<"Valid types: ( " << nativeExt;
             forAll(known, i)
             {
                 Info<<" " << known[i];
@@ -230,7 +121,7 @@ bool Foam::UnsortedMeshedSurface<Face>::canWrite
     }
 
     // handle 'native' format directly
-    if (fExt == nativeSurfaceExt)
+    if (isNative(fExt))
     {
         return true;
     }
@@ -249,7 +140,7 @@ bool Foam::UnsortedMeshedSurface<Face>::canWrite
 
             Info<<"Unknown file extension for writing: " << fExt << nl;
             // compact output:
-            Info<<"Valid types: ( " << nativeSurfaceExt;
+            Info<<"Valid types: ( " << nativeExt;
             forAll(known, i)
             {
                 Info<<" " << known[i];
@@ -281,7 +172,7 @@ void Foam::UnsortedMeshedSurface<Face>::write
     const word ext = fName.ext();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         surf.write(OFstream(fName)());
         return;
@@ -306,92 +197,6 @@ void Foam::UnsortedMeshedSurface<Face>::write
 }
 
 
-// Returns patch info.
-// Sets faceMap to the indexing according to patch numbers.
-// Patch numbers start at 0.
-template<class Face>
-Foam::surfGroupList Foam::UnsortedMeshedSurface<Face>::sortedRegions
-(
-    const UList<label>& regionLst,
-    const Map<word>& patchNames,
-    labelList& faceMap
-)
-{
-    // determine sort order according to region numbers
-
-    // std::sort() really seems to mix up the order.
-    // and std::stable_sort() might take too long / too much memory
-
-    // Assuming that we have relatively fewer regions compared to the
-    // number of items, just do it ourselves
-
-    // step 1: get region sizes and store (regionId => patchI)
-    Map<label> regionLookup;
-    forAll(regionLst, faceI)
-    {
-        const label regId = regionLst[faceI];
-
-        Map<label>::iterator iter = regionLookup.find(regId);
-        if (iter == regionLookup.end())
-        {
-            regionLookup.insert(regId, 1);
-        }
-        else
-        {
-            iter()++;
-        }
-    }
-
-    // step 2: assign start/size (and name) to the newPatches
-    // re-use the lookup to map (regionId => patchI)
-    surfGroupList patchLst(regionLookup.size());
-    label patchStart = 0;
-    label patchI = 0;
-    forAllIter(Map<label>, regionLookup, iter)
-    {
-        label regId = iter.key();
-
-        word patchName;
-        Map<word>::const_iterator iter2 = patchNames.find(regId);
-        if (iter2 == patchNames.end())
-        {
-            patchName = word("patch") + ::Foam::name(patchI);
-        }
-        else
-        {
-            patchName = iter2();
-        }
-
-        patchLst[patchI] = surfGroup
-        (
-            patchName,
-            0,           // initialize with zero size
-            patchStart,
-            patchI
-        );
-
-        // increment the start for the next patch
-        // and save the (regionId => patchI) mapping
-        patchStart += iter();
-        iter() = patchI++;
-    }
-
-
-    // step 3: build the re-ordering
-    faceMap.setSize(regionLst.size());
-
-    forAll(regionLst, faceI)
-    {
-        label patchI = regionLookup[regionLst[faceI]];
-
-        faceMap[faceI] = patchLst[patchI].start() + patchLst[patchI].size()++;
-    }
-
-    // with reordered faces registered in faceMap
-    return patchLst;
-}
-
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Face>
@@ -835,7 +640,7 @@ Foam::surfGroupList Foam::UnsortedMeshedSurface<Face>::sortedRegions
         patchNames.insert(patchI, patches_[patchI].name());
     }
 
-    return sortedRegions(regions_, patchNames, faceMap);
+    return sortedPatchRegions(regions_, patchNames, faceMap);
 }
 
 
@@ -985,7 +790,7 @@ bool Foam::UnsortedMeshedSurface<Face>::read
     const word ext = fName.ext();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         return read(IFstream(fName)());
     }
@@ -1009,7 +814,7 @@ bool Foam::UnsortedMeshedSurface<Face>::read
     clear();
 
     // handle 'native' format directly
-    if (ext == nativeSurfaceExt)
+    if (isNative(ext))
     {
         return read(IFstream(fName)());
     }
@@ -1065,6 +870,4 @@ void Foam::UnsortedMeshedSurface<Face>::operator=
 #include "UnsortedMeshedSurfaceIO.C"
 #include "UnsortedMeshedSurfaceNew.C"
 
-#undef nativeSurfaceExt
-
 // ************************************************************************* //
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
index ac727d7ce78..1249007c12e 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
@@ -52,6 +52,7 @@ SourceFiles
 #include "boolList.H"
 #include "surfPatchIdentifierList.H"
 #include "surfGroupList.H"
+#include "surfaceFormatsCore.H"
 #include "xfer.H"
 #include "face.H"
 #include "triFace.H"
@@ -83,7 +84,8 @@ template<class Face>
 template<class Face>
 class UnsortedMeshedSurface
 :
-    public PrimitivePatchExtra<Face, ::Foam::List, pointField, point>
+    public PrimitivePatchExtra<Face, ::Foam::List, pointField, point>,
+    public fileFormats::surfaceFormatsCore      
 {
     friend class MeshedSurface<Face>;
 
@@ -128,10 +130,6 @@ protected:
 
     // Static protected functions
 
-        //- Read non-comment line
-        static string getLineNoComment(IFstream&);
-
-
     // Protected Member functions
 
         //- Sets default patch names based on the maximum patch number
@@ -187,15 +185,6 @@ public:
         //- Can we write this file format?
         static bool canWrite(const word& ext, const bool verbose=false);
 
-        //- Determine the sort order from the region list.
-        //  Returns patch list and sets faceMap to indices within faceLst
-        static surfGroupList sortedRegions
-        (
-            const UList<label>& regionLst,
-            const Map<word>& patchNames,
-            labelList& faceMap
-        );
-
     // Constructors
 
         //- Construct null
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
index 938b393e761..c6e857523d9 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.C
@@ -35,147 +35,6 @@ License
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-template<class Face>
-template<class Type>
-Type Foam::fileFormats::AC3DsurfaceFormat<Face>::parse(const string& str)
-{
-    IStringStream ss(str);
-
-    Type t;
-    ss >> t;
-    return t;
-}
-
-
-template<class Face>
-bool Foam::fileFormats::AC3DsurfaceFormat<Face>::readCmd
-(
-    IFstream& is,
-    string& cmd,
-    string& args
-)
-{
-    if (is.good())
-    {
-        string line;
-        is.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.
-template<class Face>
-bool Foam::fileFormats::AC3DsurfaceFormat<Face>::cueTo
-(
-    IFstream& is,
-    const string& cmd,
-    string& args
-)
-{
-    while (is.good())
-    {
-        string line;
-        is.getLine(line);
-
-        string::size_type space = line.find(' ');
-
-        if (space != string::npos)
-        {
-            if (line.substr(0, space) == cmd)
-            {
-                args = line.substr(space+1);
-
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-
-// Similar to cueTo(), but throws error if cmd not found
-template<class Face>
-Foam::string Foam::fileFormats::AC3DsurfaceFormat<Face>::cueToOrDie
-(
-    IFstream& is,
-    const string& cmd,
-    const string& errorMsg
-)
-{
-    string args;
-    if (!cueTo(is, cmd, args))
-    {
-        FatalErrorIn
-        (
-            "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
-        )
-            << "Cannot find command " << cmd
-            << " " << errorMsg
-            << exit(FatalError);
-    }
-
-    return args;
-}
-
-
-template<class Face>
-void Foam::fileFormats::AC3DsurfaceFormat<Face>::writeHeader
-(
-    Ostream& os,
-    const List<surfGroup>& patchLst
-)
-{
-    // 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
-    };
-
-    // Write header. Define materials.
-    os  << "AC3Db" << nl;
-
-    forAll(patchLst, patchI)
-    {
-        const word& pName = patchLst[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"
-            << nl;
-    }
-
-    os  << "OBJECT world" << nl
-        << "kids " << patchLst.size() << endl;
-}
-
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
index 68f9d58291e..bedad11ffd0 100644
--- a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormat.H
@@ -35,7 +35,7 @@ Note
    optimized for this, but at expense of losing a common reading approach.
 
 SourceFiles
-    AC3DfileFormat.C
+    AC3DsurfaceFormat.C
 
 \*---------------------------------------------------------------------------*/
 
@@ -46,6 +46,7 @@ SourceFiles
 #include "OFstream.H"
 #include "MeshedSurface.H"
 #include "UnsortedMeshedSurface.H"
+#include "AC3DsurfaceFormatCore.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -61,7 +62,8 @@ namespace fileFormats
 template<class Face>
 class AC3DsurfaceFormat
 :
-    public UnsortedMeshedSurface<Face>
+    public UnsortedMeshedSurface<Face>,
+    public AC3DsurfaceFormatCore
 {
     //- Private typedefs for convenience
     typedef AC3DsurfaceFormat<Face>     ThisType;
@@ -69,28 +71,6 @@ class AC3DsurfaceFormat
 
     // Private Member Functions
 
-        //- Read a type via IStringStream
-        template<class Type>
-        static Type parse(const string&);
-
-        //- Read cmd, args from IFstream
-        static bool readCmd(IFstream&, string& cmd, string& args);
-
-        //- Cue up to cmd, reading args
-        static bool cueTo(IFstream&, const string& cmd, string& args);
-
-        //- Cue up to cmd, reading args or exit with a FatalError
-        //  returns the command args
-        static string cueToOrDie
-        (
-            IFstream&,
-            const string& cmd,
-            const string& errorMsg=string::null
-        );
-
-        //- Write header with materials
-        static void writeHeader(Ostream&, const List<surfGroup>&);
-
         //- Disallow default bitwise copy construct
         AC3DsurfaceFormat(const AC3DsurfaceFormat<Face>&);
 
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
new file mode 100644
index 00000000000..8923aceb655
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.C
@@ -0,0 +1,174 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+\*---------------------------------------------------------------------------*/
+
+#include "AC3DsurfaceFormatCore.H"
+#include "clock.H"
+#include "IFstream.H"
+#include "IStringStream.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Type>
+Type Foam::fileFormats::AC3DsurfaceFormatCore::parse(const string& str)
+{
+    IStringStream ss(str);
+
+    Type t;
+    ss >> t;
+    return t;
+}
+
+
+bool Foam::fileFormats::AC3DsurfaceFormatCore::readCmd
+(
+    IFstream& is,
+    string& cmd,
+    string& args
+)
+{
+    if (is.good())
+    {
+        string line;
+        is.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.
+bool Foam::fileFormats::AC3DsurfaceFormatCore::cueTo
+(
+    IFstream& is,
+    const string& cmd,
+    string& args
+)
+{
+    while (is.good())
+    {
+        string line;
+        is.getLine(line);
+
+        string::size_type space = line.find(' ');
+
+        if (space != string::npos)
+        {
+            if (line.substr(0, space) == cmd)
+            {
+                args = line.substr(space+1);
+
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+// Similar to cueTo(), but throws error if cmd not found
+Foam::string Foam::fileFormats::AC3DsurfaceFormatCore::cueToOrDie
+(
+    IFstream& is,
+    const string& cmd,
+    const string& errorMsg
+)
+{
+    string args;
+    if (!cueTo(is, cmd, args))
+    {
+        FatalErrorIn
+        (
+            "fileFormats::AC3DsurfaceFormat::read(const fileName&)"
+        )
+            << "Cannot find command " << cmd
+            << " " << errorMsg
+            << exit(FatalError);
+    }
+
+    return args;
+}
+
+
+void Foam::fileFormats::AC3DsurfaceFormatCore::writeHeader
+(
+    Ostream& os,
+    const List<surfGroup>& patchLst
+)
+{
+    // 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
+    };
+
+    // Write header. Define materials.
+    os  << "AC3Db" << nl;
+
+    forAll(patchLst, patchI)
+    {
+        const word& pName = patchLst[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"
+            << nl;
+    }
+
+    os  << "OBJECT world" << nl
+        << "kids " << patchLst.size() << endl;
+}
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+// ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
new file mode 100644
index 00000000000..60a10cf911b
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/ac3d/AC3DsurfaceFormatCore.H
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Class
+    Foam::fileFormats::AC3DsurfaceFormatCore
+
+Description
+    Internal class used by the AC3DsurfaceFormat
+
+SourceFiles
+    AC3DsurfaceFormatCore.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef AC3DsurfaceFormatCore_H
+#define AC3DsurfaceFormatCore_H
+
+#include "Ostream.H"
+#include "OFstream.H"
+#include "MeshedSurface.H"
+#include "UnsortedMeshedSurface.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fileFormats
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class AC3DfileFormat Declaration
+\*---------------------------------------------------------------------------*/
+
+class AC3DsurfaceFormatCore
+{
+protected:
+        // Protected Member Functions
+
+        //- Read a type via IStringStream
+        template<class Type>
+        static Type parse(const string&);
+
+        //- Read cmd, args from IFstream
+        static bool readCmd(IFstream&, string& cmd, string& args);
+
+        //- Cue up to cmd, reading args
+        static bool cueTo(IFstream&, const string& cmd, string& args);
+
+        //- Cue up to cmd, reading args or exit with a FatalError
+        //  returns the command args
+        static string cueToOrDie
+        (
+            IFstream&,
+            const string& cmd,
+            const string& errorMsg=string::null
+        );
+
+        //- Write header with materials
+        static void writeHeader(Ostream&, const List<surfGroup>&);
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        AC3DsurfaceFormatCore()
+        {}
+
+    // Destructor
+
+        ~AC3DsurfaceFormatCore()
+        {}
+
+    // Member Functions
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileFormats
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
index 1a983fb794b..fe81ba5903d 100644
--- a/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/gts/GTSsurfaceFormat.H
@@ -49,7 +49,7 @@ namespace fileFormats
 {
 
 /*---------------------------------------------------------------------------*\
-                      Class GTSsurfaceFormat Declaration
+                     Class GTSsurfaceFormat Declaration
 \*---------------------------------------------------------------------------*/
 
 template<class Face>
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
index 29fc4bd3f40..a61f378c788 100644
--- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C
@@ -33,32 +33,6 @@ License
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 
-// Do weird things to extract number
-template<class Face>
-Foam::scalar Foam::fileFormats::NASsurfaceFormat<Face>::parseNASCoord
-(
-    const string& s
-)
-{
-    size_t expSign = s.find_last_of("+-");
-
-    if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1]))
-    {
-        scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))());
-        scalar exponent = readScalar(IStringStream(s.substr(expSign+1))());
-
-        if (s[expSign] == '-')
-        {
-            exponent = -exponent;
-        }
-        return mantissa*pow(10, exponent);
-    }
-    else
-    {
-        return readScalar(IStringStream(s)());
-    }
-}
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Face>
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
index 093ad170db2..a7c2869fef9 100644
--- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.H
@@ -48,6 +48,7 @@ SourceFiles
 #include "OFstream.H"
 #include "MeshedSurface.H"
 #include "UnsortedMeshedSurface.H"
+#include "NASsurfaceFormatCore.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -63,7 +64,8 @@ namespace fileFormats
 template<class Face>
 class NASsurfaceFormat
 :
-    public UnsortedMeshedSurface<Face>
+    public UnsortedMeshedSurface<Face>,
+    public NASsurfaceFormatCore
 {
     //- Private typedefs for convenience
     typedef NASsurfaceFormat<Face>      ThisType;
@@ -71,9 +73,6 @@ class NASsurfaceFormat
 
     // Private Member Functions
 
-        //- Do weird things to extract number
-        static scalar parseNASCoord(const string&);
-
         //- Disallow default bitwise copy construct
         NASsurfaceFormat(const NASsurfaceFormat<Face>&);
 
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.C
new file mode 100644
index 00000000000..1a51adc0498
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.C
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+\*---------------------------------------------------------------------------*/
+
+#include "NASsurfaceFormatCore.H"
+#include "IFstream.H"
+#include "IStringStream.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+// Do weird things to extract number
+Foam::scalar Foam::fileFormats::NASsurfaceFormatCore::parseNASCoord
+(
+    const string& s
+)
+{
+    size_t expSign = s.find_last_of("+-");
+
+    if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1]))
+    {
+        scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))());
+        scalar exponent = readScalar(IStringStream(s.substr(expSign+1))());
+
+        if (s[expSign] == '-')
+        {
+            exponent = -exponent;
+        }
+        return mantissa*pow(10, exponent);
+    }
+    else
+    {
+        return readScalar(IStringStream(s)());
+    }
+}
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+
+// ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.H
new file mode 100644
index 00000000000..83d0910dd27
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormatCore.H
@@ -0,0 +1,89 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Class
+    Foam::fileFormats::NASsurfaceFormatCore
+
+Description
+    Internal class used by the NASsurfaceFormat
+
+SourceFiles
+    NASsurfaceFormatCore.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef NASsurfaceFormatCore_H
+#define NASsurfaceFormatCore_H
+
+#include "Ostream.H"
+#include "OFstream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fileFormats
+{
+
+/*---------------------------------------------------------------------------*\
+                   Class NASsurfaceFormatCore Declaration
+\*---------------------------------------------------------------------------*/
+
+class NASsurfaceFormatCore
+{
+protected:
+
+    // Protected Member Functions
+
+        //- Do weird things to extract number
+        static scalar parseNASCoord(const string&);
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        NASsurfaceFormatCore()
+        {}
+
+    // Destructor
+
+        ~NASsurfaceFormatCore()
+        {}
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileFormats
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
index c3ac05591af..02a4f1f2c10 100644
--- a/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
+++ b/src/surfMesh/surfaceFormats/off/OFFsurfaceFormat.H
@@ -39,7 +39,7 @@ Note
     When writing, it is set to the region number (integer).
 
 SourceFiles
-    OFFfileFormat.C
+    OFFsurfaceFormat.C
 
 \*---------------------------------------------------------------------------*/
 
diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H
index c7b93a96eda..1aeeae7d95b 100644
--- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H
@@ -108,6 +108,7 @@ public:
         );
 
     // Destructor
+
         ~STLsurfaceFormatCore();
 
     // Member Functions
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
new file mode 100644
index 00000000000..0b5cb98322a
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
@@ -0,0 +1,260 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+\*---------------------------------------------------------------------------*/
+
+#include "surfaceFormatsCore.H"
+#include "IFstream.H"
+#include "OFstream.H"
+#include "Time.H"
+#include "SortableList.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+// File extension for 'native' raw format
+Foam::word Foam::fileFormats::surfaceFormatsCore::nativeExt("ofs");
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+//- Check if file extension corresponds to 'native' surface format
+bool
+Foam::fileFormats::surfaceFormatsCore::isNative(const word& ext)
+{
+    return (ext == nativeExt);
+}
+
+
+Foam::string
+Foam::fileFormats::surfaceFormatsCore::getLineNoComment
+(
+    IFstream& is
+)
+{
+    string line;
+    do
+    {
+        is.getLine(line);
+    }
+    while ((line.size() == 0 || line[0] == '#') && is.good());
+
+    return line;
+}
+
+
+Foam::fileName
+Foam::fileFormats::surfaceFormatsCore::triSurfInstance
+(
+    const Time& d,
+    const word& subdirName
+)
+{
+    fileName foamName(d.caseName() + ".ofs");
+
+    // Search back through the time directories list to find the time
+    // closest to and lower than current time
+
+    instantList ts = d.times();
+    label i;
+
+    for (i=ts.size()-1; i>=0; i--)
+    {
+        if (ts[i].value() <= d.timeOutputValue())
+        {
+            break;
+        }
+    }
+
+    // Noting that the current directory has already been searched
+    // for mesh data, start searching from the previously stored time directory
+
+    if (i>=0)
+    {
+        for (label j=i; j>=0; j--)
+        {
+            if (file(d.path()/ts[j].name()/subdirName/foamName))
+            {
+                return ts[j].name();
+            }
+        }
+    }
+
+    return "constant";
+}
+
+
+Foam::fileName
+Foam::fileFormats::surfaceFormatsCore::triSurfName
+(
+    const Time& d,
+    const word& subdirName
+)
+{
+    fileName foamName(d.caseName() + ".ofs");
+
+    // Search back through the time directories list to find the time
+    // closest to and lower than current time
+
+    instantList ts = d.times();
+    label i;
+
+    for (i=ts.size()-1; i>=0; i--)
+    {
+        if (ts[i].value() <= d.timeOutputValue())
+        {
+            break;
+        }
+    }
+
+    // Noting that the current directory has already been searched
+    // for mesh data, start searching from the previously stored time directory
+
+    if (i>=0)
+    {
+        for (label j=i; j>=0; j--)
+        {
+            fileName testName(d.path()/ts[j].name()/subdirName/foamName);
+
+            if (file(testName))
+            {
+                return testName;
+            }
+        }
+    }
+
+    return d.path()/"constant"/subdirName/foamName;
+}
+
+
+// Returns patch info.
+// Sets faceMap to the indexing according to patch numbers.
+// Patch numbers start at 0.
+Foam::surfGroupList
+Foam::fileFormats::surfaceFormatsCore::sortedPatchRegions
+(
+    const UList<label>& regionLst,
+    const Map<word>& patchNames,
+    labelList& faceMap
+)
+{
+    // determine sort order according to region numbers
+
+    // std::sort() really seems to mix up the order.
+    // and std::stable_sort() might take too long / too much memory
+
+    // Assuming that we have relatively fewer regions compared to the
+    // number of items, just do it ourselves
+
+    // step 1: get region sizes and store (regionId => patchI)
+    Map<label> regionLookup;
+    forAll(regionLst, faceI)
+    {
+        const label regId = regionLst[faceI];
+
+        Map<label>::iterator iter = regionLookup.find(regId);
+        if (iter == regionLookup.end())
+        {
+            regionLookup.insert(regId, 1);
+        }
+        else
+        {
+            iter()++;
+        }
+    }
+
+    // step 2: assign start/size (and name) to the newPatches
+    // re-use the lookup to map (regionId => patchI)
+    surfGroupList patchLst(regionLookup.size());
+    label patchStart = 0;
+    label patchI = 0;
+    forAllIter(Map<label>, regionLookup, iter)
+    {
+        label regId = iter.key();
+
+        word patchName;
+        Map<word>::const_iterator iter2 = patchNames.find(regId);
+        if (iter2 == patchNames.end())
+        {
+            patchName = word("patch") + ::Foam::name(patchI);
+        }
+        else
+        {
+            patchName = iter2();
+        }
+
+        patchLst[patchI] = surfGroup
+        (
+            patchName,
+            0,           // initialize with zero size
+            patchStart,
+            patchI
+        );
+
+        // increment the start for the next patch
+        // and save the (regionId => patchI) mapping
+        patchStart += iter();
+        iter() = patchI++;
+    }
+
+
+    // step 3: build the re-ordering
+    faceMap.setSize(regionLst.size());
+
+    forAll(regionLst, faceI)
+    {
+        label patchI = regionLookup[regionLst[faceI]];
+
+        faceMap[faceI] = patchLst[patchI].start() + patchLst[patchI].size()++;
+    }
+
+    // with reordered faces registered in faceMap
+    return patchLst;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::fileFormats::surfaceFormatsCore::surfaceFormatsCore()
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::fileFormats::surfaceFormatsCore::~surfaceFormatsCore()
+{}
+
+// * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
new file mode 100644
index 00000000000..835471887ef
--- /dev/null
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Class
+    Foam::fileFormats::surfaceFormatsCore
+
+Description
+    A collection of helper functions for reading/writing surface formats.
+
+SourceFiles
+    surfaceFormatsCore.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef surfaceFormatsCore_H
+#define surfaceFormatsCore_H
+
+#include "surfPatchIdentifierList.H"
+#include "surfGroupList.H"
+#include "labelList.H"
+#include "Map.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of friend functions and operators
+
+class IFstream;
+class Time;
+   
+namespace fileFormats
+{
+
+/*---------------------------------------------------------------------------*\
+                    Class surfaceFormatsCore Declaration
+\*---------------------------------------------------------------------------*/
+
+class surfaceFormatsCore
+{
+public:
+
+    // Static Data
+
+        //- The file extension corresponding to 'native' surface format
+        static word nativeExt;
+
+    // Static Member Functions
+
+        //- Check if file extension corresponds to 'native' surface format
+        static bool isNative(const word&);
+
+        //- Read non-comment line
+        static string getLineNoComment(IFstream&);
+
+        //- Name of UnsortedMeshedSurface directory to use.
+        static fileName triSurfInstance(const Time&, const word& subdirName);
+
+        //- Name of UnsortedMeshedSurface directory to use.
+        static fileName triSurfName(const Time&, const word& subdirName);
+
+        //- Determine the sort order from the region list.
+        //  Returns patch list and sets faceMap to indices within faceLst
+        static surfGroupList sortedPatchRegions
+        (
+            const UList<label>& regionLst,
+            const Map<word>& patchNames,
+            labelList& faceMap
+        );
+
+    // Constructors
+
+        //- Construct null
+        surfaceFormatsCore();
+
+    // Destructor
+
+        virtual ~surfaceFormatsCore();
+
+    // Member Functions
+
+    // Access
+
+    // Edit
+
+    // Read
+
+    // Write
+
+    // Member operators
+
+    // Ostream Operator
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace fileFormats
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab