From d199d9f5912f9f54c6d2d610f8be2d072d1f46c1 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Tue, 25 Feb 2020 13:01:08 +0100
Subject: [PATCH] ENH: add IOobject-based constructors for meshed surfaces
 (#1600)

- refactor logic from triSurfaceMesh for triSurface, MeshedSurface,
  UnsortedMeshedSurface.

  Makes it easier to locate and use surface files without the
  triSurfaceMesh (meshTools) infrastructure.

STYLE: remove unused sampledTriSurfaceMesh constructors
---
 .../triSurfaceMesh/triSurfaceMesh.C           | 106 +-----------
 .../triSurfaceMesh/triSurfaceMesh.H           |  20 ---
 .../distributedTriSurfaceMesh.C               |   4 +-
 .../triSurfaceMeshPointSet.C                  |  23 +--
 .../triSurfaceMeshPointSet.H                  |   6 +-
 .../sampledTriSurfaceMesh.C                   | 125 ++++++---------
 .../sampledTriSurfaceMesh.H                   |  31 ++--
 .../sampledTriSurfaceMeshNormal.C             |  14 +-
 .../sampledTriSurfaceMeshNormal.H             |  11 +-
 src/surfMesh/MeshedSurface/MeshedSurface.C    |  41 ++++-
 src/surfMesh/MeshedSurface/MeshedSurface.H    |  25 ++-
 .../UnsortedMeshedSurface.C                   |  62 +++++--
 .../UnsortedMeshedSurface.H                   |  19 ++-
 .../surfaceFormats/surfaceFormatsCore.C       | 151 +++++++++++++++++-
 .../surfaceFormats/surfaceFormatsCore.H       | 101 +++++++++---
 src/surfMesh/triSurface/triSurface.C          |   5 +-
 src/surfMesh/triSurface/triSurface.H          |  76 ++++++++-
 src/surfMesh/triSurface/triSurfaceIO.C        |  94 +++++++++--
 18 files changed, 586 insertions(+), 328 deletions(-)

diff --git a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
index 3db3cb4159d..75e7515fbb6 100644
--- a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
+++ b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.C
@@ -47,97 +47,6 @@ Foam::word Foam::triSurfaceMesh::meshSubDir = "triSurface";
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-Foam::fileName Foam::triSurfaceMesh::checkFile
-(
-    const IOobject& io,
-    const bool isGlobal
-)
-{
-    const fileName fName
-    (
-        isGlobal
-      ? io.globalFilePath(typeName)
-      : io.localFilePath(typeName)
-    );
-    if (fName.empty())
-    {
-        FatalErrorInFunction
-            << "Cannot find triSurfaceMesh starting from "
-            << io.objectPath() << exit(FatalError);
-    }
-
-    return fName;
-}
-
-
-Foam::fileName Foam::triSurfaceMesh::relativeFilePath
-(
-    const IOobject& io,
-    const fileName& f,
-    const bool isGlobal
-)
-{
-    fileName fName(f);
-    fName.expand();
-    if (!fName.isAbsolute())
-    {
-        // Is the specified file:
-        // - local to the cwd?
-        // - local to the case dir?
-        // - or just another name?
-        fName = fileHandler().filePath
-        (
-            isGlobal,
-            IOobject(io, fName),
-            word::null
-        );
-    }
-    return fName;
-}
-
-Foam::fileName Foam::triSurfaceMesh::checkFile
-(
-    const IOobject& io,
-    const dictionary& dict,
-    const bool isGlobal
-)
-{
-    fileName fName;
-    if (dict.readIfPresent("file", fName, keyType::LITERAL))
-    {
-        const fileName rawFName(fName);
-
-        fName = relativeFilePath(io, rawFName, isGlobal);
-
-        if (!exists(fName))
-        {
-            FatalErrorInFunction
-                << "Cannot find triSurfaceMesh " << rawFName
-                << " starting from " << io.objectPath()
-                << exit(FatalError);
-        }
-    }
-    else
-    {
-        fName =
-        (
-            isGlobal
-          ? io.globalFilePath(typeName)
-          : io.localFilePath(typeName)
-        );
-
-        if (!exists(fName))
-        {
-            FatalErrorInFunction
-                << "Cannot find triSurfaceMesh starting from "
-                << io.objectPath() << exit(FatalError);
-        }
-    }
-
-    return fName;
-}
-
-
 bool Foam::triSurfaceMesh::addFaceToEdge
 (
     const edge& e,
@@ -308,7 +217,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
             false       // searchableSurface already registered under name
         )
     ),
-    triSurface(checkFile(static_cast<const searchableSurface&>(*this), true)),
+    triSurface(static_cast<const searchableSurface&>(*this), dictionary::null),
     triSurfaceRegionSearch(static_cast<const triSurface&>(*this)),
     minQuality_(-1),
     surfaceClosed_(-1),
@@ -341,19 +250,16 @@ Foam::triSurfaceMesh::triSurfaceMesh
             false       // searchableSurface already registered under name
         )
     ),
-    triSurface
-    (
-        checkFile(static_cast<const searchableSurface&>(*this), dict, true)
-    ),
+    triSurface(static_cast<const searchableSurface&>(*this), dict),
     triSurfaceRegionSearch(static_cast<const triSurface&>(*this), dict),
     minQuality_(-1),
     surfaceClosed_(-1),
     outsideVolType_(volumeType::UNKNOWN)
 {
-    // Reading from supplied file name instead of objectPath/filePath
+    // Adjust to use supplied file name instead of objectPath/filePath
     if (dict.readIfPresent("file", fName_, keyType::LITERAL))
     {
-        fName_ = relativeFilePath
+        fName_ = triSurface::relativeFilePath
         (
             static_cast<const searchableSurface&>(*this),
             fName_,
@@ -404,7 +310,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const readAction r)
             false       // searchableSurface already registered under name
         )
     ),
-    triSurface(),       // construct null
+    triSurface(),
     triSurfaceRegionSearch(static_cast<const triSurface&>(*this)),
     minQuality_(-1),
     surfaceClosed_(-1),
@@ -502,7 +408,7 @@ Foam::triSurfaceMesh::triSurfaceMesh
             false       // searchableSurface already registered under name
         )
     ),
-    triSurface(),       // construct null
+    triSurface(),
     triSurfaceRegionSearch(static_cast<const triSurface&>(*this), dict),
     minQuality_(-1),
     surfaceClosed_(-1),
diff --git a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
index 512d5bf2302..c3e62014d1f 100644
--- a/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
+++ b/src/meshTools/searchableSurfaces/triSurfaceMesh/triSurfaceMesh.H
@@ -106,26 +106,6 @@ protected:
 
     // Private Member Functions
 
-        //- Return fileName to load IOobject from
-        static fileName checkFile(const IOobject& io, const bool isGlobal);
-
-        //- Return fileName. If fileName is relative gets treated local to
-        //  IOobject
-        static fileName relativeFilePath
-        (
-            const IOobject&,
-            const fileName&,
-            const bool isGlobal
-        );
-
-        //- Return fileName to load IOobject from. Optional override of fileName
-        static fileName checkFile
-        (
-            const IOobject&,
-            const dictionary&,
-            const bool isGlobal
-        );
-
         //- Helper function for isSurfaceClosed
         static bool addFaceToEdge
         (
diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
index dc75f2f80cb..f0b9d402940 100644
--- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
+++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C
@@ -2557,7 +2557,7 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh(const IOobject& io)
 
     bounds().reduce();
 
-    const fileName actualFile(checkFile(io, true));
+    const fileName actualFile(triSurfaceMesh::checkFile(io, true));
 
     if
     (
@@ -2697,7 +2697,7 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
 
     bounds().reduce();
 
-    const fileName actualFile(checkFile(io, dict, true));
+    const fileName actualFile(triSurfaceMesh::checkFile(io, dict, true));
 
     if
     (
diff --git a/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.C b/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.C
index 685d192af65..9e7975f40d4 100644
--- a/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.C
+++ b/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -121,32 +122,34 @@ Foam::triSurfaceMeshPointSet::triSurfaceMeshPointSet
 )
 :
     sampledSet(name, mesh, searchEngine, dict),
-    surface_(dict.get<word>("surface"))
+    surfaceName_(dict.get<word>("surface"))
 {
-    // Load surface.
-    if (mesh.time().foundObject<triSurfaceMesh>(surface_))
+    // Get or load surface
+
+    const auto* surfPtr =
+        mesh.time().cfindObject<triSurfaceMesh>(surfaceName_);
+
+    if (surfPtr)
     {
         // Note: should use localPoints() instead of points() but assume
         // trisurface is compact.
-        sampleCoords_ = mesh.time().lookupObject<triSurfaceMesh>
-        (
-            surface_
-        ).points();
+        sampleCoords_ = surfPtr->points();
     }
     else
     {
-        sampleCoords_ = triSurfaceMesh
+        sampleCoords_ = triSurface
         (
             IOobject
             (
-                surface_,
+                surfaceName_,
                 mesh.time().constant(),     // instance
                 "triSurface",               // local
                 mesh.time(),
                 IOobject::MUST_READ,
                 IOobject::NO_WRITE,
                 false
-            )
+            ),
+            dictionary::null
         ).points();
     }
 
diff --git a/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.H b/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.H
index 5d34a61fd22..c0aa5580000 100644
--- a/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.H
+++ b/src/sampling/sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.H
@@ -60,10 +60,10 @@ class triSurfaceMeshPointSet
 :
     public sampledSet
 {
-    // Private data
+    // Private Data
 
-        //- Name of triSurfaceMesh
-        const word surface_;
+        //- The surface name
+        const word surfaceName_;
 
         //- Sampling points
         List<point> sampleCoords_;
diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C
index 14181bff0d4..f00bca31123 100644
--- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C
+++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C
@@ -33,7 +33,6 @@ License
 #include "treeDataCell.H"
 #include "treeDataFace.H"
 #include "meshTools.H"
-
 #include "addToRunTimeSelectionTable.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -78,8 +77,32 @@ namespace Foam
             }
         }
     };
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// The IOobject for reading
+inline static IOobject selectReadIO(const word& name, const Time& runTime)
+{
+    return IOobject
+    (
+        name,
+        runTime.constant(),     // instance
+        "triSurface",           // local
+        runTime,                // registry
+        IOobject::MUST_READ,
+        IOobject::NO_WRITE,
+        false   // no register
+    );
 }
 
+} // End namespace Foam
+
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
@@ -94,14 +117,14 @@ void Foam::sampledTriSurfaceMesh::setZoneMap
     {
         sz += zn.size();
     }
+    zoneIds.resize(sz);
 
-    zoneIds.setSize(sz);
     forAll(zoneLst, zonei)
     {
         const surfZone& zn = zoneLst[zonei];
 
         // Assign sub-zone Ids
-        SubList<label>(zoneIds, zn.size(), zn.start()) = zonei;
+        SubList<label>(zoneIds, zn.range()) = zonei;
     }
 }
 
@@ -224,8 +247,8 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
             << " keeping:" << nFound << endl;
     }
 
-    // Now subset the surface. Do not use triSurface::subsetMesh since requires
-    // original surface to be in compact numbering.
+    // Now subset the surface.
+    // Done manually in case the original had non-compact point numbering
 
     const triSurface& s = surface_;
 
@@ -393,15 +416,10 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
 
     forAll(faceMap, facei)
     {
-        const labelledTri& origF = s[faceMap[facei]];
         face& f = surfFaces[facei];
 
-        f = triFace
-        (
-            reversePointMap[origF[0]],
-            reversePointMap[origF[1]],
-            reversePointMap[origF[2]]
-        );
+        f = s[faceMap[facei]];                  // Copy original face
+        inplaceRenumber(reversePointMap, f);    // renumber point ids
 
         for (const label labi : f)
         {
@@ -583,18 +601,11 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
 :
     sampledSurface(name, mesh),
     MeshStorage(),
+    surfaceName_(surfaceName),
     surface_
     (
-        IOobject
-        (
-            surfaceName,
-            mesh.time().constant(), // instance
-            "triSurface",           // local
-            mesh.time(),            // registry
-            IOobject::MUST_READ,
-            IOobject::NO_WRITE,
-            false
-        )
+        selectReadIO(surfaceName, mesh.time()),
+        dictionary::null
     ),
     sampleSource_(sampleSource),
     needsUpdate_(true),
@@ -615,57 +626,22 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
 :
     sampledSurface(name, mesh, dict),
     MeshStorage(),
-    surface_
+    surfaceName_
     (
-        IOobject
+        triSurface::findFile
         (
-            dict.get<word>("surface"),
-            mesh.time().constant(), // instance
-            "triSurface",           // local
-            mesh.time(),            // registry
-            IOobject::MUST_READ,
-            IOobject::NO_WRITE,
-            false
-        ),
-        dict
+            selectReadIO(dict.get<word>("surface"), mesh.time()),
+            dict
+        ).name()
     ),
-    sampleSource_(samplingSourceNames_.get("source", dict)),
-    needsUpdate_(true),
-    keepIds_(dict.lookupOrDefault("keepIds", false)),
-    originalIds_(),
-    zoneIds_(),
-    sampleElements_(),
-    samplePoints_()
-{}
-
-
-Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
-(
-    const word& name,
-    const polyMesh& mesh,
-    const triSurface& surface,
-    const word& sampleSourceName
-)
-:
-    sampledSurface(name, mesh),
-    MeshStorage(),
     surface_
     (
-        IOobject
-        (
-            name,
-            mesh.time().constant(), // instance
-            "triSurface",           // local
-            mesh.time(),            // registry
-            IOobject::NO_READ,
-            IOobject::NO_WRITE,
-            false
-        ),
-        surface
+        selectReadIO(dict.get<word>("surface"), mesh.time()),
+        dict
     ),
-    sampleSource_(samplingSourceNames_[sampleSourceName]),
+    sampleSource_(samplingSourceNames_.get("source", dict)),
     needsUpdate_(true),
-    keepIds_(false),
+    keepIds_(dict.lookupOrDefault("keepIds", false)),
     originalIds_(),
     zoneIds_(),
     sampleElements_(),
@@ -673,12 +649,6 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::sampledTriSurfaceMesh::~sampledTriSurfaceMesh()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::sampledTriSurfaceMesh::needsUpdate() const
@@ -700,7 +670,6 @@ bool Foam::sampledTriSurfaceMesh::expire()
     zoneIds_.clear();
 
     originalIds_.clear();
-    boundaryTreePtr_.clear();
     sampleElements_.clear();
     samplePoints_.clear();
 
@@ -717,11 +686,7 @@ bool Foam::sampledTriSurfaceMesh::update()
     }
 
     // Calculate surface and mesh overlap bounding box
-    treeBoundBox bb
-    (
-        surface_.triSurface::points(),
-        surface_.triSurface::meshPoints()
-    );
+    treeBoundBox bb(surface_.points(), surface_.meshPoints());
 
     // Check for overlap with (global!) mesh bb
     const bool intersect = bb.intersect(mesh().bounds());
@@ -732,7 +697,7 @@ bool Foam::sampledTriSurfaceMesh::update()
         // bounding box so we don't get any 'invalid bounding box' errors.
 
         WarningInFunction
-            << "Surface " << surface_.searchableSurface::name()
+            << "Surface " << surfaceName_
             << " does not overlap bounding box of mesh " << mesh().bounds()
             << endl;
 
@@ -865,7 +830,7 @@ Foam::tmp<Foam::tensorField> Foam::sampledTriSurfaceMesh::interpolate
 void Foam::sampledTriSurfaceMesh::print(Ostream& os) const
 {
     os  << "sampledTriSurfaceMesh: " << name() << " :"
-        << " surface:" << surface_.objectRegistry::name()
+        << " surface:" << surfaceName_
         << " faces:"   << faces().size()
         << " points:"  << points().size()
         << " zoneids:" << zoneIds().size();
diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.H b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.H
index 45d87dffaf8..47290a690dd 100644
--- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.H
+++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.H
@@ -28,8 +28,8 @@ Class
     Foam::sampledTriSurfaceMesh
 
 Description
-    A sampledSurface from a triSurfaceMesh. It samples on the points/triangles
-    of the triSurface.
+    A sampledSurface from a meshed surface.
+    It samples on the points/faces of the triSurface.
 
     - it either samples cells or (non-coupled) boundary faces
 
@@ -98,7 +98,7 @@ SourceFiles
 #define sampledTriSurfaceMesh_H
 
 #include "sampledSurface.H"
-#include "triSurfaceMesh.H"
+#include "triSurface.H"
 #include "MeshedSurface.H"
 #include "MeshedSurfacesFwd.H"
 
@@ -120,7 +120,7 @@ class sampledTriSurfaceMesh
     public meshedSurface
 {
 public:
-        //- Types of communications
+        //- Types of sampling regions
         enum samplingSource
         {
             cells,
@@ -130,7 +130,7 @@ public:
 
 private:
 
-    //- Private typedefs for convenience
+        //- Private typedefs for convenience
         typedef meshedSurface MeshStorage;
 
 
@@ -138,8 +138,11 @@ private:
 
         static const Enum<samplingSource> samplingSourceNames_;
 
+        //- The name of the input surface
+        word surfaceName_;
+
         //- Surface to sample on
-        const triSurfaceMesh surface_;
+        const triSurface surface_;
 
         //- Whether to sample internal cell values or boundary values
         const samplingSource sampleSource_;
@@ -151,12 +154,9 @@ private:
         bool keepIds_;
 
         //- List of element ids/order of the original surface,
-        //  when keepIds is active.
+        //- when keepIds is active.
         labelList originalIds_;
 
-        //- Search tree for all non-coupled boundary faces
-        mutable autoPtr<indexedOctree<treeDataFace>> boundaryTreePtr_;
-
         //- For compatibility with the meshSurf interface
         labelList zoneIds_;
 
@@ -210,18 +210,9 @@ public:
             const dictionary& dict
         );
 
-        //- Construct from triSurface
-        sampledTriSurfaceMesh
-        (
-            const word& name,
-            const polyMesh& mesh,
-            const triSurface& surface,
-            const word& sampleSourceName
-        );
-
 
     //- Destructor
-    virtual ~sampledTriSurfaceMesh();
+    virtual ~sampledTriSurfaceMesh() = default;
 
 
     // Member Functions
diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.C b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.C
index 056b7744bfa..af263f509b8 100644
--- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.C
+++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017-2018 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -67,18 +67,6 @@ Foam::sampledTriSurfaceMeshNormal::sampledTriSurfaceMeshNormal
 {}
 
 
-Foam::sampledTriSurfaceMeshNormal::sampledTriSurfaceMeshNormal
-(
-    const word& name,
-    const polyMesh& mesh,
-    const triSurface& surface,
-    const word& sampleSourceName
-)
-:
-    sampledTriSurfaceMesh(name, mesh, surface, sampleSourceName)
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::tmp<Foam::Field<Foam::vector>>
diff --git a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.H b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.H
index 95262653d15..c96407dd3e6 100644
--- a/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.H
+++ b/src/sampling/sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.H
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017-2018 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -110,15 +110,6 @@ public:
             const dictionary& dict
         );
 
-        //- Construct from triSurface
-        sampledTriSurfaceMeshNormal
-        (
-            const word& name,
-            const polyMesh& mesh,
-            const triSurface& surface,
-            const word& sampleSourceName
-        );
-
 
     //- Destructor
     virtual ~sampledTriSurfaceMeshNormal() = default;
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.C b/src/surfMesh/MeshedSurface/MeshedSurface.C
index 720e7536227..f9055b3b017 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.C
@@ -393,7 +393,11 @@ 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
+)
 :
     MeshedSurface<Face>()
 {
@@ -419,6 +423,16 @@ Foam::MeshedSurface<Face>::MeshedSurface(Istream& is)
 }
 
 
+template<class Face>
+Foam::MeshedSurface<Face>::MeshedSurface
+(
+    const Time& runTime
+)
+:
+    MeshedSurface<Face>(runTime, word::null)
+{}
+
+
 template<class Face>
 Foam::MeshedSurface<Face>::MeshedSurface
 (
@@ -452,6 +466,31 @@ Foam::MeshedSurface<Face>::MeshedSurface
 }
 
 
+template<class Face>
+Foam::MeshedSurface<Face>::MeshedSurface
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+:
+    MeshedSurface<Face>()
+{
+    fileName fName
+    (
+        fileFormats::surfaceFormatsCore::checkFile(io, dict, isGlobal)
+    );
+
+    // TBD:
+    // word fExt(dict.getOrDefault<word>("surfaceType", fName.ext()));
+    // read(fName, fExt);
+
+    this->read(fName, fName.ext());
+
+    this->scalePoints(dict.getOrDefault<scalar>("scale", 0));
+}
+
+
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 template<class Face>
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.H b/src/surfMesh/MeshedSurface/MeshedSurface.H
index a11ed9c8b20..4d407384705 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.H
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.H
@@ -270,19 +270,32 @@ public:
         );
 
         //- Construct from a surfMesh
-        MeshedSurface(const surfMesh& mesh);
+        explicit MeshedSurface(const surfMesh& mesh);
 
         //- Construct from file name (uses extension to determine type)
-        MeshedSurface(const fileName& name);
+        explicit MeshedSurface(const fileName& name);
 
         //- Construct from file name (uses extension to determine type)
-        MeshedSurface(const fileName& name, const word& ext);
+        explicit MeshedSurface(const fileName& name, const word& ext);
 
         //- Construct from Istream
-        MeshedSurface(Istream& is);
+        explicit MeshedSurface(Istream& is);
 
-        //- Construct from database
-        MeshedSurface(const Time& runTime, const word& surfName = word::null);
+        //- Construct from database (as surfMesh) with default name
+        explicit MeshedSurface(const Time& runTime);
+
+        //- Construct from database (as surfMesh) with given surface name
+        MeshedSurface(const Time& runTime, const word& surfName);
+
+        //- Read construct using IO to find the file location.
+        //  Dictionary may contain optional 'file' entry, and an
+        //  optional 'scale' entry (eg, 0.001: mm -> m)
+        MeshedSurface
+        (
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
 
 
     // Declare run-time constructor selection table
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
index 9c978b472bc..95633cd35d1 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
@@ -270,17 +270,55 @@ Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
 template<class Face>
 Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
 (
-    const Time& t,
+    const Time& runTime
+)
+:
+    UnsortedMeshedSurface<Face>()
+{
+    MeshedSurface<Face> surf(runTime);
+    transfer(surf);
+}
+
+
+template<class Face>
+Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
+(
+    const Time& runTime,
     const word& surfName
 )
 :
     UnsortedMeshedSurface<Face>()
 {
-    MeshedSurface<Face> surf(t, surfName);
+    MeshedSurface<Face> surf(runTime, surfName);
     transfer(surf);
 }
 
 
+template<class Face>
+Foam::UnsortedMeshedSurface<Face>::UnsortedMeshedSurface
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+:
+    UnsortedMeshedSurface<Face>()
+{
+    fileName fName
+    (
+        fileFormats::surfaceFormatsCore::checkFile(io, dict, isGlobal)
+    );
+
+    // TBD:
+    // word fExt(dict.getOrDefault<word>("surfaceType", fName.ext()));
+    // read(fName, fExt);
+
+    this->read(fName, fName.ext());
+
+    this->scalePoints(dict.getOrDefault<scalar>("scale", 0));
+}
+
+
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
 template<class Face>
@@ -291,19 +329,15 @@ void Foam::UnsortedMeshedSurface<Face>::setOneZone()
     zoneIds_.resize(size());
     zoneIds_ = 0;
 
-    word zoneName;
-    if (zoneToc_.size())
-    {
-        zoneName = zoneToc_[0].name();
-    }
-    if (zoneName.empty())
-    {
-        zoneName = "zone0";
-    }
-
     // Assign single default zone
     zoneToc_.resize(1);
-    zoneToc_[0] = surfZoneIdentifier(zoneName, 0);
+
+    zoneToc_[0].index() = 0;
+
+    if (zoneToc_[0].name().empty())
+    {
+        zoneToc_[0].name() = "zone0";
+    }
 }
 
 
@@ -324,7 +358,7 @@ void Foam::UnsortedMeshedSurface<Face>::setZones
         zoneToc_[zonei] = zone;
 
         // Assign sub-zone Ids
-        SubList<label>(zoneIds_, zone.size(), zone.start()) = zonei;
+        SubList<label>(zoneIds_, zone.range()) = zonei;
     }
 }
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
index 9d77d7003d1..d286d417b69 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
@@ -203,19 +203,28 @@ public:
         );
 
         //- Construct from file name (uses extension to determine type)
-        UnsortedMeshedSurface(const fileName& name);
+        explicit UnsortedMeshedSurface(const fileName& name);
 
         //- Construct from file name (uses extension to determine type)
         UnsortedMeshedSurface(const fileName& name, const word& ext);
 
         //- Construct from Istream
-        UnsortedMeshedSurface(Istream& is);
+        explicit UnsortedMeshedSurface(Istream& is);
 
-        //- Construct from objectRegistry and a named surface
+        //- Construct from database (as surfMesh) with default name
+        explicit UnsortedMeshedSurface(const Time& runTime);
+
+        //- Construct from database (as surfMesh) with given surface name
+        UnsortedMeshedSurface(const Time& runTime, const word& surfName);
+
+        //- Read construct using IO to find the file location.
+        //  Dictionary may contain optional 'file' entry, and an
+        //  optional 'scale' entry (eg, 0.001: mm -> m)
         UnsortedMeshedSurface
         (
-            const Time& t,
-            const word& surfName = word::null
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
         );
 
 
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
index 1b2ae22fcc9..fed6385b6a9 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2012 OpenFOAM Foundation
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,7 +27,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "surfaceFormatsCore.H"
-
 #include "Time.H"
 #include "ListOps.H"
 #include "Fstream.H"
@@ -157,6 +156,154 @@ Foam::fileName Foam::fileFormats::surfaceFormatsCore::findMeshFile
 #endif
 
 
+Foam::fileName Foam::fileFormats::surfaceFormatsCore::relativeFilePath
+(
+    const IOobject& io,
+    const fileName& f,
+    const bool isGlobal
+)
+{
+    fileName fName(f);
+    fName.expand();
+    if (!fName.isAbsolute())
+    {
+        // Is the specified file:
+        // - local to the cwd?
+        // - local to the case dir?
+        // - or just another name?
+        fName = fileHandler().filePath
+        (
+            isGlobal,
+            IOobject(io, fName),
+            word::null
+        );
+    }
+    return fName;
+}
+
+
+Foam::fileName Foam::fileFormats::surfaceFormatsCore::findFile
+(
+    const IOobject& io,
+    const bool isGlobal
+)
+{
+    fileName fName
+    (
+        isGlobal
+      ? io.globalFilePath(word::null)
+      : io.localFilePath(word::null)
+    );
+
+    if (!exists(fName))
+    {
+        fName.clear();
+    }
+
+    return fName;
+}
+
+
+Foam::fileName Foam::fileFormats::surfaceFormatsCore::findFile
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+{
+    fileName fName;
+    if (dict.readIfPresent("file", fName, keyType::LITERAL))
+    {
+        fName = relativeFilePath(io, fName, isGlobal);
+    }
+    else
+    {
+        fName =
+        (
+            isGlobal
+          ? io.globalFilePath(word::null)
+          : io.localFilePath(word::null)
+        );
+    }
+
+    if (!exists(fName))
+    {
+        fName.clear();
+    }
+
+    return fName;
+}
+
+
+Foam::fileName Foam::fileFormats::surfaceFormatsCore::checkFile
+(
+    const IOobject& io,
+    const bool isGlobal
+)
+{
+    fileName fName
+    (
+        isGlobal
+      ? io.globalFilePath(word::null)
+      : io.localFilePath(word::null)
+    );
+
+    if (fName.empty())
+    {
+        FatalErrorInFunction
+            << "Cannot find surface starting from "
+            << io.objectPath() << nl
+            << exit(FatalError);
+    }
+
+    return fName;
+}
+
+
+Foam::fileName Foam::fileFormats::surfaceFormatsCore::checkFile
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+{
+    fileName fName;
+    if (dict.readIfPresent("file", fName, keyType::LITERAL))
+    {
+        const fileName rawFName(fName);
+
+        fName = relativeFilePath(io, rawFName, isGlobal);
+
+        if (!exists(fName))
+        {
+            FatalErrorInFunction
+                << "Cannot find surface " << rawFName
+                << " starting from " << io.objectPath() << nl
+                << exit(FatalError);
+        }
+    }
+    else
+    {
+        fName =
+        (
+            isGlobal
+          ? io.globalFilePath(word::null)
+          : io.localFilePath(word::null)
+        );
+
+        if (!exists(fName))
+        {
+            FatalErrorInFunction
+                << "Cannot find surface starting from "
+                << io.objectPath() << nl
+                << exit(FatalError);
+        }
+    }
+
+    return fName;
+}
+
+
 bool Foam::fileFormats::surfaceFormatsCore::checkSupport
 (
     const wordHashSet& available,
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
index 079f964e6cb..70fe0d39951 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -48,9 +49,12 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declarations
+// Forward Declarations
 class ISstream;
 class Time;
+class triSurface;
+class IOobject;
+class dictionary;
 
 namespace fileFormats
 {
@@ -63,10 +67,15 @@ class surfaceFormatsCore
 {
 protected:
 
+    // Friendship with triSurface (for IO helpers)
+    friend class ::Foam::triSurface;
+
+
+    // General
+
         //- 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
         template<class Container>
@@ -76,9 +85,41 @@ protected:
             const word& name = "zone0"
         )
         {
-            return List<surfZone>(1, surfZone(name, container.size(), 0, 0));
+            return List<surfZone>(1, surfZone(name, container.size()));
         }
 
+
+    // IO helpers
+
+        //- Return fileName.
+        //  If fileName is relative gets treated as local to IOobject.
+        //  Duplicate of triSurfaceMesh::relativeFilePath
+        static fileName relativeFilePath
+        (
+            const IOobject& io,
+            const fileName& f,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Return fileName to load IOobject from.
+        //  Fatal if the file does not exist
+        static fileName checkFile
+        (
+            const IOobject& io,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Return fileName to load IOobject from.
+        //  Supports optional override of fileName with "file" entry
+        //  Fatal if the file does not exist
+        static fileName checkFile
+        (
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+
 public:
 
     // Static Data
@@ -99,39 +140,57 @@ public:
             const word& functionName
         );
 
-        //- Return the local file name (within time directory)
-        //  NEEDS FIXING
-        static fileName localMeshFileName
+        //- Use IOobject information to resolve file to load from,
+        //- or empty if the file does not exist.
+        static fileName findFile
         (
-            const word& surfName = word::null
+            const IOobject& io,
+            const bool isGlobal = true  //!< resolve as a global file
         );
 
-        //- Find instance with surfName
-        //  NEEDS FIXING
-        static fileName findMeshInstance
+        //- Use IOobject information to resolve file to load from,
+        //- or empty if the file does not exist.
+        //  Supports optional override of fileName with "file" entry
+        static fileName findFile
         (
-            const Time&,
-            const word& surfName = word::null
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
         );
 
-        //- Find mesh file with surfName
-        //  NEEDS FIXING
-        static fileName findMeshFile
-        (
-            const Time&,
-            const word& surfName = word::null
-        );
+
+//        //- Return the local file name (within time directory)
+//        //  NEEDS FIXING
+//        static fileName localMeshFileName
+//        (
+//            const word& surfName = word::null
+//        );
+//
+//        //- Find instance with surfName
+//        //  NEEDS FIXING
+//        static fileName findMeshInstance
+//        (
+//            const Time&,
+//            const word& surfName = word::null
+//        );
+//
+//        //- Find mesh file with surfName
+//        //  NEEDS FIXING
+//        static fileName findMeshFile
+//        (
+//            const Time&,
+//            const word& surfName = word::null
+//        );
 
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         surfaceFormatsCore() = default;
 
 
     //- Destructor
     virtual ~surfaceFormatsCore() = default;
-
 };
 
 
diff --git a/src/surfMesh/triSurface/triSurface.C b/src/surfMesh/triSurface/triSurface.C
index db8c29b2b7e..624b6b1e233 100644
--- a/src/surfMesh/triSurface/triSurface.C
+++ b/src/surfMesh/triSurface/triSurface.C
@@ -504,10 +504,7 @@ Foam::triSurface::triSurface
     const scalar scaleFactor
 )
 :
-    ParentType(List<Face>(), pointField()),
-    patches_(),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
+    triSurface()
 {
     read(name, ext);
     scalePoints(scaleFactor);
diff --git a/src/surfMesh/triSurface/triSurface.H b/src/surfMesh/triSurface/triSurface.H
index 0c5a01ebede..5556203a1e7 100644
--- a/src/surfMesh/triSurface/triSurface.H
+++ b/src/surfMesh/triSurface/triSurface.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2019 OpenCFD Ltd.
+    Copyright (C) 2016-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -51,9 +51,9 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declarations
-
+// Forward Declarations
 class Time;
+class IOobject;
 class IFstream;
 class surfZone;
 class triSurface;
@@ -240,6 +240,54 @@ public:
         static const wordHashSet& writeTypes();
 
 
+    // IO helpers
+
+        //- Return fileName.
+        //  If fileName is relative gets treated as local to IOobject.
+        static fileName relativeFilePath
+        (
+            const IOobject& io,
+            const fileName& f,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Return fileName to load IOobject from.
+        //  Fatal if the file does not exist
+        static fileName checkFile
+        (
+            const IOobject& io,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Return fileName to load IOobject from.
+        //  Supports optional override of fileName with "file" entry
+        //  Fatal if the file does not exist
+        static fileName checkFile
+        (
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Use IOobject information to resolve file to load from,
+        //- or empty if the file does not exist.
+        static fileName findFile
+        (
+            const IOobject& io,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+        //- Use IOobject information to resolve file to load from,
+        //- or empty if the file does not exist.
+        //  Supports optional override of fileName with "file" entry
+        static fileName findFile
+        (
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
+
+
     // Constructors
 
         //- Construct null
@@ -286,7 +334,11 @@ public:
 
         //- Construct from file name (uses extension to determine type).
         //  Optional (positive, non-zero) point scaling is possible.
-        triSurface(const fileName& name, const scalar scaleFactor = -1);
+        explicit triSurface
+        (
+            const fileName& name,
+            const scalar scaleFactor = -1
+        );
 
         //- Construct from file name (uses extension to determine type)
         triSurface
@@ -297,10 +349,20 @@ public:
         );
 
         //- Construct from Istream
-        triSurface(Istream& is);
+        explicit triSurface(Istream& is);
+
+        //- Construct from objectRegistry by reading an ".ftr" file
+        explicit triSurface(const Time& d);
 
-        //- Construct from objectRegistry
-        triSurface(const Time& d);
+        //- Read construct using IO to find the file location.
+        //  Dictionary may contain optional 'file' entry, and an
+        //  optional 'scale' entry (eg, 0.001: mm -> m)
+        triSurface
+        (
+            const IOobject& io,
+            const dictionary& dict,
+            const bool isGlobal = true  //!< resolve as a global file
+        );
 
 
     //- Destructor
diff --git a/src/surfMesh/triSurface/triSurfaceIO.C b/src/surfMesh/triSurface/triSurfaceIO.C
index e7383ffedaa..6fe241b1a11 100644
--- a/src/surfMesh/triSurface/triSurfaceIO.C
+++ b/src/surfMesh/triSurface/triSurfaceIO.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -104,6 +104,62 @@ bool Foam::triSurface::canRead(const fileName& name, const bool verbose)
     return canReadType(ext, verbose);
 }
 
+
+
+
+Foam::fileName Foam::triSurface::relativeFilePath
+(
+    const IOobject& io,
+    const fileName& f,
+    const bool isGlobal
+)
+{
+    return fileFormats::surfaceFormatsCore::relativeFilePath(io, f, isGlobal);
+}
+
+
+Foam::fileName Foam::triSurface::checkFile
+(
+    const IOobject& io,
+    const bool isGlobal
+)
+{
+    return fileFormats::surfaceFormatsCore::checkFile(io, isGlobal);
+}
+
+
+Foam::fileName Foam::triSurface::checkFile
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+{
+    return fileFormats::surfaceFormatsCore::checkFile(io, dict, isGlobal);
+}
+
+
+Foam::fileName Foam::triSurface::findFile
+(
+    const IOobject& io,
+    const bool isGlobal
+)
+{
+    return fileFormats::surfaceFormatsCore::findFile(io, isGlobal);
+}
+
+
+Foam::fileName Foam::triSurface::findFile
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+{
+    return fileFormats::surfaceFormatsCore::findFile(io, dict, isGlobal);
+}
+
+
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 void Foam::triSurface::printTriangle
@@ -143,7 +199,8 @@ bool Foam::triSurface::read
     if (check && !exists(name))
     {
         FatalErrorInFunction
-            << "Cannnot read " << name << exit(FatalError);
+            << "Cannnot read " << name << nl
+            << exit(FatalError);
     }
 
     if (ext == "gz")
@@ -257,10 +314,7 @@ void Foam::triSurface::write
 
 Foam::triSurface::triSurface(Istream& is)
 :
-    ParentType(List<Face>(), pointField()),
-    patches_(),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
+    triSurface()
 {
     read(is);
 
@@ -270,10 +324,7 @@ Foam::triSurface::triSurface(Istream& is)
 
 Foam::triSurface::triSurface(const Time& d)
 :
-    ParentType(List<Face>(), pointField()),
-    patches_(),
-    sortedEdgeFacesPtr_(nullptr),
-    edgeOwnerPtr_(nullptr)
+    triSurface()
 {
     fileName foamFile(d.caseName() + ".ftr");
 
@@ -287,6 +338,29 @@ Foam::triSurface::triSurface(const Time& d)
 }
 
 
+Foam::triSurface::triSurface
+(
+    const IOobject& io,
+    const dictionary& dict,
+    const bool isGlobal
+)
+:
+    triSurface()
+{
+    fileName fName(checkFile(io, dict, isGlobal));
+
+    // TBD:
+    // word fileExt = dict.getOrDefault<word>("surfaceType", fName.ext());
+    // read(fName, ext);
+
+    read(fName, fName.ext());
+
+    scalePoints(dict.getOrDefault<scalar>("scale", 0));
+
+    setDefaultPatches();
+}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 void Foam::triSurface::write
-- 
GitLab