From da44c100f055fb29f075b59109aa5ca8726613f4 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Fri, 5 Mar 2021 15:52:57 +0100
Subject: [PATCH] ENH: support additional output meta data in FoamFile header

- currently add to mesh zones to provide a table of contents
  of the zone names that allows downstream consumers quick access to
  the information without needing to parse the entire file.
---
 src/OpenFOAM/Make/files                       |  1 +
 .../decomposedBlockData/decomposedBlockData.C |  6 ++
 src/OpenFOAM/db/regIOobject/regIOobject.C     | 15 +++--
 src/OpenFOAM/db/regIOobject/regIOobject.H     | 20 +++++++
 .../db/regIOobject/regIOobjectMetaData.C      | 59 +++++++++++++++++++
 .../collatedFileOperation.C                   |  9 +++
 .../fileOperation/fileOperation.C             |  3 +
 .../masterUncollatedFileOperation.C           |  3 +
 .../meshes/polyMesh/zones/ZoneMesh/ZoneMesh.C |  8 +++
 .../meshes/polyMesh/zones/ZoneMesh/ZoneMesh.H | 12 +++-
 10 files changed, 129 insertions(+), 7 deletions(-)
 create mode 100644 src/OpenFOAM/db/regIOobject/regIOobjectMetaData.C

diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 7db14b3cff5..ed399ab9834 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -327,6 +327,7 @@ $(IOobject)/IOobjectWriteHeader.C
 
 regIOobject = db/regIOobject
 /* $(regIOobject)/regIOobject.C in global.Cver */
+$(regIOobject)/regIOobjectMetaData.C
 $(regIOobject)/regIOobjectRead.C
 $(regIOobject)/regIOobjectWrite.C
 
diff --git a/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
index 379ef7fdd26..7470ad6c312 100644
--- a/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
+++ b/src/OpenFOAM/db/IOobjects/decomposedBlockData/decomposedBlockData.C
@@ -1024,6 +1024,12 @@ bool Foam::decomposedBlockData::writeObject
 
         osPtr.reset(new OFstream(objectPath(), IOstreamOption::BINARY));
 
+        // Update meta-data for current state
+        const_cast<regIOobject&>
+        (
+            static_cast<const regIOobject&>(*this)
+        ).updateMetaData();
+
         decomposedBlockData::writeHeader
         (
             *osPtr,
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.C b/src/OpenFOAM/db/regIOobject/regIOobject.C
index d1dd2e90d32..94e77b8cc7c 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.C
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2018-2019 OpenCFD Ltd.
+    Copyright (C) 2018-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -29,8 +29,9 @@ License
 #include "regIOobject.H"
 #include "Time.H"
 #include "polyMesh.H"
-#include "registerSwitch.H"
+#include "dictionary.H"
 #include "fileOperation.H"
+#include "registerSwitch.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -73,7 +74,9 @@ Foam::regIOobject::regIOobject(const IOobject& io, const bool isTime)
     registered_(false),
     ownedByRegistry_(false),
     watchIndices_(),
-    eventNo_(isTime ? 0 : db().getEvent()) // No event for top-level Time
+    eventNo_(isTime ? 0 : db().getEvent()), // No event for top-level Time
+    metaDataPtr_(nullptr),
+    isPtr_(nullptr)
 {
     if (registerObject())
     {
@@ -90,6 +93,7 @@ Foam::regIOobject::regIOobject(const regIOobject& rio)
     ownedByRegistry_(false),
     watchIndices_(rio.watchIndices_),
     eventNo_(db().getEvent()),
+    metaDataPtr_(rio.metaDataPtr_.clone()),
     isPtr_(nullptr)
 {
     // Do not register copy with objectRegistry
@@ -103,6 +107,7 @@ Foam::regIOobject::regIOobject(const regIOobject& rio, bool registerCopy)
     ownedByRegistry_(false),
     watchIndices_(),
     eventNo_(db().getEvent()),
+    metaDataPtr_(rio.metaDataPtr_.clone()),
     isPtr_(nullptr)
 {
     if (registerCopy)
@@ -129,6 +134,7 @@ Foam::regIOobject::regIOobject
     ownedByRegistry_(false),
     watchIndices_(),
     eventNo_(db().getEvent()),
+    metaDataPtr_(rio.metaDataPtr_.clone()),
     isPtr_(nullptr)
 {
     if (registerCopy)
@@ -152,6 +158,7 @@ Foam::regIOobject::regIOobject
     ownedByRegistry_(false),
     watchIndices_(),
     eventNo_(db().getEvent()),
+    metaDataPtr_(rio.metaDataPtr_.clone()),
     isPtr_(nullptr)
 {
     if (registerObject())
@@ -474,7 +481,7 @@ bool Foam::regIOobject::headerOk()
 void Foam::regIOobject::operator=(const IOobject& io)
 {
     // Close any file
-    isPtr_.clear();
+    isPtr_.reset(nullptr);
 
     // Check out of objectRegistry
     checkOut();
diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.H b/src/OpenFOAM/db/regIOobject/regIOobject.H
index 262122f8bf5..8c1a7c52073 100644
--- a/src/OpenFOAM/db/regIOobject/regIOobject.H
+++ b/src/OpenFOAM/db/regIOobject/regIOobject.H
@@ -56,6 +56,8 @@ namespace Foam
 
 // Forward Declarations
 
+class dictionary;
+
 namespace functionEntries
 {
     class codeStream;
@@ -106,6 +108,9 @@ private:
         //- eventNo of last update
         label eventNo_;
 
+        //- Dictionary for any meta-data
+        autoPtr<dictionary> metaDataPtr_;
+
         //- Istream for reading
         autoPtr<ISstream> isPtr_;
 
@@ -277,6 +282,21 @@ public:
             virtual void rename(const word& newName);
 
 
+        // Meta-data
+
+            //- Return pointer to meta-data or nullptr
+            const dictionary* findMetaData() const noexcept;
+
+            //- Get or create meta-data
+            dictionary& getMetaData() noexcept;
+
+            //- Remove meta-data
+            void removeMetaData();
+
+            //- Update internal meta-data (eg, prior to writing)
+            virtual void updateMetaData();
+
+
         // Reading
 
             //- Return complete path + object name if the file exists
diff --git a/src/OpenFOAM/db/regIOobject/regIOobjectMetaData.C b/src/OpenFOAM/db/regIOobject/regIOobjectMetaData.C
new file mode 100644
index 00000000000..146b4e1d019
--- /dev/null
+++ b/src/OpenFOAM/db/regIOobject/regIOobjectMetaData.C
@@ -0,0 +1,59 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "regIOobject.H"
+#include "dictionary.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+const Foam::dictionary* Foam::regIOobject::findMetaData() const noexcept
+{
+    return metaDataPtr_.get();
+}
+
+
+Foam::dictionary& Foam::regIOobject::getMetaData() noexcept
+{
+    if (!metaDataPtr_)
+    {
+        metaDataPtr_.reset(new dictionary("meta"));
+    }
+    return *metaDataPtr_;
+}
+
+
+void Foam::regIOobject::removeMetaData()
+{
+    metaDataPtr_.reset(nullptr);
+}
+
+
+void Foam::regIOobject::updateMetaData()
+{}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
index 393b46ba156..2176b033c93 100644
--- a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
@@ -237,6 +237,12 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
 
     const bool isMaster = isMasterRank(proci);
 
+    // Update meta-data for current state
+    if (isMaster)
+    {
+        const_cast<regIOobject&>(io).updateMetaData();
+    }
+
     // Note: cannot do append + compression. This is a limitation
     // of ogzstream (or rather most compressed formats)
 
@@ -379,6 +385,9 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
     const Time& tm = io.time();
     const fileName& inst = io.instance();
 
+    // Update meta-data for current state
+    const_cast<regIOobject&>(io).updateMetaData();
+
     if (inst.isAbsolute() || !tm.processorCase())
     {
         mkDir(io.path());
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
index f20e1562ca5..bb35e2243a0 100644
--- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
@@ -635,6 +635,9 @@ bool Foam::fileOperation::writeObject
 
         OSstream& os = *osPtr;
 
+        // Update meta-data for current state
+        const_cast<regIOobject&>(io).updateMetaData();
+
         // If any of these fail, return (leave error handling to Ostream class)
 
         const bool ok =
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
index f46e0358189..a31190a22ac 100644
--- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
@@ -2182,6 +2182,9 @@ bool Foam::fileOperations::masterUncollatedFileOperation::writeObject
     // Make sure to pick up any new times
     setTime(io.time());
 
+    // Update meta-data for current state
+    const_cast<regIOobject&>(io).updateMetaData();
+
     autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, valid));
     OSstream& os = *osPtr;
 
diff --git a/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.C b/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.C
index 734777b9e3c..a97c20f5678 100644
--- a/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.C
@@ -644,6 +644,14 @@ void Foam::ZoneMesh<ZoneType, MeshType>::movePoints(const pointField& pts)
 }
 
 
+template<class ZoneType, class MeshType>
+void Foam::ZoneMesh<ZoneType, MeshType>::updateMetaData()
+{
+    dictionary& meta = this->getMetaData();
+    meta.set("names", this->names());
+}
+
+
 template<class ZoneType, class MeshType>
 bool Foam::ZoneMesh<ZoneType, MeshType>::writeData(Ostream& os) const
 {
diff --git a/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.H b/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.H
index 492fbd4c12e..a6dffca158d 100644
--- a/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.H
+++ b/src/OpenFOAM/meshes/polyMesh/zones/ZoneMesh/ZoneMesh.H
@@ -232,9 +232,6 @@ public:
         //- Correct zone mesh after moving points
         void movePoints(const pointField& pts);
 
-        //- writeData member function required by regIOobject
-        bool writeData(Ostream& os) const;
-
 
     // Member Operators
 
@@ -269,6 +266,15 @@ public:
         ZoneType& operator()(const word& zoneName, const bool verbose=false);
 
 
+    // IO
+
+        //- Update internal meta-data (eg, prior to writing)
+        void updateMetaData();
+
+        //- The writeData member function required by regIOobject
+        bool writeData(Ostream& os) const;
+
+
     // Ostream Operator
 
         friend Ostream& operator<< <ZoneType, MeshType>
-- 
GitLab