From b13689c6f2025f50f63a74f8e6f411c9ae92d387 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 8 Dec 2021 10:20:07 +0100
Subject: [PATCH] ENH: support optional dimensionSet reading

---
 src/OpenFOAM/dimensionSet/dimensionSet.C      |   2 +-
 src/OpenFOAM/dimensionSet/dimensionSet.H      |  39 +++++-
 src/OpenFOAM/dimensionSet/dimensionSetIO.C    | 112 +++++++++++++-----
 .../DimensionedField/DimensionedFieldIO.C     |   2 +-
 .../UniformDimensionedField.C                 |  10 +-
 5 files changed, 122 insertions(+), 43 deletions(-)

diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.C b/src/OpenFOAM/dimensionSet/dimensionSet.C
index 617b3439be0..008e0bfced2 100644
--- a/src/OpenFOAM/dimensionSet/dimensionSet.C
+++ b/src/OpenFOAM/dimensionSet/dimensionSet.C
@@ -113,7 +113,7 @@ Foam::dimensionSet::dimensionSet(const dimensionSet& ds)
 
 bool Foam::dimensionSet::dimensionless() const
 {
-    for (const scalar& val : exponents_)
+    for (const scalar val : exponents_)
     {
         // ie, mag(val) > smallExponent
         if ((val > smallExponent) || (val < -smallExponent))
diff --git a/src/OpenFOAM/dimensionSet/dimensionSet.H b/src/OpenFOAM/dimensionSet/dimensionSet.H
index 34c3c00be80..f3f5278e1d9 100644
--- a/src/OpenFOAM/dimensionSet/dimensionSet.H
+++ b/src/OpenFOAM/dimensionSet/dimensionSet.H
@@ -55,7 +55,7 @@ namespace Foam
 {
 
 // Forward Declarations
-
+class dictionary;
 class dimensionSet;
 class dimensionSets;
 
@@ -130,7 +130,7 @@ private:
 
             // Constructors
 
-                 tokeniser(Istream& is);
+                 explicit tokeniser(Istream& is);
 
 
             // Member Functions
@@ -154,8 +154,8 @@ private:
         };
 
 
-        //- Reset exponents to nearest integer if close to it. Used to
-        //  handle reading with insufficient precision.
+        //- Reset exponents to nearest integer if close to it.
+        //  Handles reading with insufficient precision.
         void round(const scalar tol);
 
         dimensionedScalar parse
@@ -165,6 +165,7 @@ private:
             const HashTable<dimensionedScalar>&
         ) const;
 
+
 public:
 
     // Declare name of the class and its debug switch
@@ -212,8 +213,22 @@ public:
         //- Copy construct
         dimensionSet(const dimensionSet& ds);
 
-        //- Construct from dictionary entry - usually "dimensions".
-        dimensionSet(const dictionary& dict, const word& entryName);
+        //- Construct from dictionary entry (usually "dimensions")
+        //  Dimensionless if non-mandatory and not found.
+        dimensionSet
+        (
+            const word& entryName,  //!< Lookup key. LITERAL (not REGEX)
+            const dictionary& dict,
+            const bool mandatory = true
+        );
+
+        //- Construct from dictionary entry (usually "dimensions")
+        dimensionSet
+        (
+            const dictionary& dict,
+            const word& entryName,  //!< Lookup key. LITERAL (not REGEX)
+            const bool mandatory = true
+        );
 
         //- Construct and return a clone
         autoPtr<dimensionSet> clone() const
@@ -245,6 +260,18 @@ public:
 
     // IO
 
+        //- Update the dimensions from dictionary entry.
+        //- FatalIOError if it is found and the number of tokens is incorrect,
+        //- or it is mandatory and not found.
+        //
+        //  \return true if the entry was found.
+        bool readEntry
+        (
+            const word& entryName,      //!< Lookup key. LITERAL (not REGEX)
+            const dictionary& dict,     //!< The dictionary
+            const bool mandatory = true //!< The entry is mandatory
+        );
+
         //- Read using provided units. Used only in initial parsing
         Istream& read
         (
diff --git a/src/OpenFOAM/dimensionSet/dimensionSetIO.C b/src/OpenFOAM/dimensionSet/dimensionSetIO.C
index d978ad90b75..71f9be97509 100644
--- a/src/OpenFOAM/dimensionSet/dimensionSetIO.C
+++ b/src/OpenFOAM/dimensionSet/dimensionSetIO.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,21 +26,37 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "dictionary.H"
 #include "dimensionSet.H"
-#include "IOstreams.H"
 #include "dimensionedScalar.H"
+#include "IOstreams.H"
 #include <limits>
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::dimensionSet::dimensionSet(const dictionary& dict, const word& entryName)
+Foam::dimensionSet::dimensionSet
+(
+    const word& entryName,
+    const dictionary& dict,
+    const bool mandatory
+)
+:
+    exponents_(Zero)
 {
-    const entry& e = dict.lookupEntry(entryName, keyType::LITERAL);
-    ITstream& is = e.stream();
+    this->readEntry(entryName, dict, mandatory);
+}
 
-    is >> *this;
 
-    e.checkITstream(is);
+Foam::dimensionSet::dimensionSet
+(
+    const dictionary& dict,
+    const word& entryName,
+    const bool mandatory
+)
+:
+    exponents_(Zero)
+{
+    this->readEntry(entryName, dict, mandatory);
 }
 
 
@@ -122,26 +138,24 @@ bool Foam::dimensionSet::tokeniser::valid(char c)
 
 Foam::label Foam::dimensionSet::tokeniser::priority(const token& t)
 {
-    if (!t.isPunctuation())
+    if (t.isPunctuation())
     {
-        return 0;
-    }
-    else if
-    (
-        t.pToken() == token::MULTIPLY
-     || t.pToken() == token::DIVIDE
-    )
-    {
-        return 2;
-    }
-    else if (t.pToken() == '^')
-    {
-        return 3;
-    }
-    else
-    {
-        return 0;
+        if
+        (
+            t.pToken() == token::MULTIPLY
+         || t.pToken() == token::DIVIDE
+        )
+        {
+            return 2;
+        }
+        else if (t.pToken() == '^')
+        {
+            return 3;
+        }
     }
+
+    // Default priority
+    return 0;
 }
 
 
@@ -230,6 +244,8 @@ void Foam::dimensionSet::tokeniser::putBack(const token& t)
 }
 
 
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
 void Foam::dimensionSet::round(const scalar tol)
 {
     scalar integralPart;
@@ -260,7 +276,7 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
     const HashTable<dimensionedScalar>& readSet
 ) const
 {
-    dimensionedScalar ds("", dimless, 1.0);
+    dimensionedScalar ds("", dimless, 1);
 
     // Get initial token
     token nextToken(tis.nextToken());
@@ -359,12 +375,12 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
             {
                 if (nextPrior > lastPrior)
                 {
-                    dimensionedScalar exp(parse(nextPrior, tis, readSet));
+                    dimensionedScalar expon(parse(nextPrior, tis, readSet));
 
-                    ds.dimensions().reset(pow(ds.dimensions(), exp.value()));
+                    ds.dimensions().reset(pow(ds.dimensions(), expon.value()));
                     // Round to nearest integer if close to it
                     ds.dimensions().round(10*smallExponent);
-                    ds.value() = Foam::pow(ds.value(), exp.value());
+                    ds.value() = Foam::pow(ds.value(), expon.value());
                 }
                 else
                 {
@@ -409,6 +425,38 @@ Foam::dimensionedScalar Foam::dimensionSet::parse
 }
 
 
+bool Foam::dimensionSet::readEntry
+(
+    const word& entryName,
+    const dictionary& dict,
+    const bool mandatory
+)
+{
+    const entry* eptr = dict.findEntry(entryName, keyType::LITERAL);
+
+    if (eptr)
+    {
+        const entry& e = *eptr;
+        ITstream& is = e.stream();
+
+        is >> *this;
+
+        e.checkITstream(is);
+
+        return true;
+    }
+    else if (mandatory)
+    {
+        FatalIOErrorInFunction(dict)
+            << "Entry '" << entryName << "' not found in dictionary "
+            << dict.relativeName() << nl
+            << exit(FatalIOError);
+    }
+
+    return false;
+}
+
+
 Foam::Istream& Foam::dimensionSet::read
 (
     Istream& is,
@@ -533,7 +581,7 @@ Foam::Istream& Foam::dimensionSet::read
 
 
             // Parse unit
-            dimensionSet symbolSet(dimless);
+            dimensionSet symbolSet;  // dimless
 
             const auto index = symbolPow.find('^');
             if (index != std::string::npos)
@@ -542,7 +590,7 @@ Foam::Istream& Foam::dimensionSet::read
                 const scalar exponent = readScalar(symbolPow.substr(index+1));
 
                 dimensionedScalar s;
-                s.read(readSet.lookup(symbol), readSet);
+                s.read(readSet.lookup(symbol, keyType::LITERAL), readSet);
 
                 symbolSet.reset(pow(s.dimensions(), exponent));
 
@@ -553,7 +601,7 @@ Foam::Istream& Foam::dimensionSet::read
             else
             {
                 dimensionedScalar s;
-                s.read(readSet.lookup(symbolPow), readSet);
+                s.read(readSet.lookup(symbolPow, keyType::LITERAL), readSet);
 
                 symbolSet.reset(s.dimensions());
                 multiplier *= s.value();
diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C
index ee234c64770..6dd9e2560c5 100644
--- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C
+++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C
@@ -38,7 +38,7 @@ void Foam::DimensionedField<Type, GeoMesh>::readField
     const word& fieldDictEntry
 )
 {
-    dimensions_.reset(dimensionSet(fieldDict, "dimensions"));
+    dimensions_.readEntry("dimensions", fieldDict);
 
     // Note: oriented state may have already been set on construction
     // - if so - do not reset by re-reading
diff --git a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C
index 650632e7604..b59ee2b1b91 100644
--- a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C
+++ b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C
@@ -85,8 +85,12 @@ template<class Type>
 bool Foam::UniformDimensionedField<Type>::readData(Istream& is)
 {
     dictionary dict(is);
-    scalar multiplier;
-    this->dimensions().read(dict.lookup("dimensions"), multiplier);
+    scalar multiplier(1);
+    this->dimensions().read
+    (
+        dict.lookup("dimensions", keyType::LITERAL),
+        multiplier
+    );
 
     dict.readEntry("value", this->value());
     this->value() *= multiplier;
@@ -98,7 +102,7 @@ bool Foam::UniformDimensionedField<Type>::readData(Istream& is)
 template<class Type>
 bool Foam::UniformDimensionedField<Type>::writeData(Ostream& os) const
 {
-    scalar multiplier;
+    scalar multiplier(1);
     os.writeKeyword("dimensions");
     this->dimensions().write(os, multiplier) << token::END_STATEMENT << nl;
     os.writeEntry("value", this->value()/multiplier) << nl;
-- 
GitLab