From 5579e7a62ba04de7f1fa8f00975d0ef2a3dee038 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Fri, 23 Oct 2020 16:38:00 +0200
Subject: [PATCH] ENH: improve some efficiency in expressions

- use refPtr to simplify some logic.
- avoid copying field if an average will be used
- initialize geometric fields with a uniform value instead of Zero
- minor tweak of method names

- apply bugfix #1889 (longer description elsewhere)
---
 .../expressions/exprDriver/exprDriver.H       |  10 +-
 .../expressions/exprDriver/exprDriverI.H      |   8 +-
 .../exprDriver/exprDriverTemplates.C          |  20 +--
 .../expressions/exprResult/exprResult.C       |  35 ++---
 .../expressions/exprResult/exprResult.H       |  74 +++++-----
 .../expressions/exprResult/exprResultI.H      | 130 ++++++++----------
 .../expressions/exprResult/exprResultStack.H  |   4 +-
 .../expressions/exprResult/exprResultStored.H |   4 +-
 .../exprResult/exprResultStoredStack.H        |   4 +-
 .../fields/fieldExprDriverTemplates.C         |  39 +++---
 .../expressions/base/fvExprDriver.H           |  29 ++--
 .../expressions/base/fvExprDriverI.H          |  26 ++--
 .../expressions/base/fvExprDriverTemplates.C  | 122 ++++++++--------
 .../fields/base/patchExprFieldBase.C          |   8 +-
 .../fields/base/patchExprFieldBase.H          |   4 +-
 .../patch/patchExprDriverTemplates.C          |  47 +++----
 16 files changed, 280 insertions(+), 284 deletions(-)

diff --git a/src/OpenFOAM/expressions/exprDriver/exprDriver.H b/src/OpenFOAM/expressions/exprDriver/exprDriver.H
index d94a0a82cd6..968030cd2bf 100644
--- a/src/OpenFOAM/expressions/exprDriver/exprDriver.H
+++ b/src/OpenFOAM/expressions/exprDriver/exprDriver.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2010-2018 Bernhard Gschaider
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -284,7 +284,7 @@ public:
 
         //- Return the expression result as a tmp field
         template<class Type>
-        tmp<Field<Type>> getResult(bool isPointVal=false);
+        tmp<Field<Type>> getResult(bool wantPointData=false);
 
         //- The result type as word - same as result().valueType()
         virtual word getResultType() const
@@ -388,7 +388,7 @@ public:
         bool isLocalVariable
         (
             const word& name,
-            bool isPointVal,
+            bool wantPointData = false,
             label expectedSize = -1
         ) const;
 
@@ -424,7 +424,7 @@ public:
         evaluate
         (
             const expressions::exprString& expr,
-            bool isPointVal = false
+            bool wantPointData = false
         );
 
         //- Evaluate the expression and return a single value
@@ -432,7 +432,7 @@ public:
         inline Type evaluateUniform
         (
             const expressions::exprString& expr,
-            bool isPointVal = false
+            bool wantPointData = false
         );
 
 
diff --git a/src/OpenFOAM/expressions/exprDriver/exprDriverI.H b/src/OpenFOAM/expressions/exprDriver/exprDriverI.H
index 5c5342e6417..6924af55e19 100644
--- a/src/OpenFOAM/expressions/exprDriver/exprDriverI.H
+++ b/src/OpenFOAM/expressions/exprDriver/exprDriverI.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -75,12 +75,12 @@ template<class Type>
 Foam::tmp<Foam::Field<Type>> Foam::expressions::exprDriver::evaluate
 (
     const expressions::exprString& expr,
-    bool isPointVal
+    bool wantPointData
 )
 {
     parse(expr);
 
-    return getResult<Type>(isPointVal);
+    return getResult<Type>(wantPointData);
 }
 
 
@@ -89,7 +89,7 @@ template<class Type>
 inline Type Foam::expressions::exprDriver::evaluateUniform
 (
     const expressions::exprString& expr,
-    bool isPointVal
+    bool wantPointData
 )
 {
     parse(expr);
diff --git a/src/OpenFOAM/expressions/exprDriver/exprDriverTemplates.C b/src/OpenFOAM/expressions/exprDriver/exprDriverTemplates.C
index 063230b19f4..1a33ecee4ae 100644
--- a/src/OpenFOAM/expressions/exprDriver/exprDriverTemplates.C
+++ b/src/OpenFOAM/expressions/exprDriver/exprDriverTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -145,13 +145,13 @@ Type Foam::expressions::exprDriver::exprDriver::weightedSum
 
 template<class Type>
 Foam::tmp<Foam::Field<Type>>
-Foam::expressions::exprDriver::getResult(bool isPointVal)
+Foam::expressions::exprDriver::getResult(bool wantPointData)
 {
-    if (!result_.isPointValue(isPointVal))
+    if (!result_.isPointData(wantPointData))
     {
         FatalErrorInFunction
-            << "Expected a" << (isPointVal ? " point" : "")
-            << " field,  but found a" << (!isPointVal ? " point" : "")
+            << "Expected a" << (wantPointData ? " point" : "")
+            << " field,  but found a" << (!wantPointData ? " point" : "")
             << " field" << nl
             << exit(FatalError);
     }
@@ -166,15 +166,16 @@ template<class Type>
 bool Foam::expressions::exprDriver::isLocalVariable
 (
     const word& name,
-    bool isPointVal,
+    bool wantPointData,
     label expectedSize
 ) const
 {
     DebugInfo
-        << "Looking for local" << (isPointVal ? " point" : "")
+        << "Looking for local" << (wantPointData ? " point" : "")
         << " field name:" << name << " type:"
         << pTraits<Type>::typeName << " size:" << expectedSize;
 
+
     bool good = hasVariable(name);
 
     if (good)
@@ -182,10 +183,11 @@ bool Foam::expressions::exprDriver::isLocalVariable
         const exprResult& var = variable(name);
 
         DebugInfo
-            << " - found (" << var.valueType() << ' ' << var.isPointValue() << ')';
+            << " - found (" << var.valueType() << ' '
+            << var.isPointData() << ')';
 
 
-        good = (var.isType<Type>() && var.isPointValue(isPointVal));
+        good = (var.isType<Type>() && var.isPointData(wantPointData));
 
         // Do size checking if requested
         if (good && expectedSize >= 0)
diff --git a/src/OpenFOAM/expressions/exprResult/exprResult.C b/src/OpenFOAM/expressions/exprResult/exprResult.C
index 43de67484d2..afe1ae9b4cc 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResult.C
+++ b/src/OpenFOAM/expressions/exprResult/exprResult.C
@@ -166,7 +166,7 @@ bool Foam::expressions::exprResult::getUniformCheckedBool
         // TODO?
     }
 
-    result.setResult(avg, size);
+    result.setResult<Type>(avg, size);
 
     return true;
 }
@@ -207,7 +207,7 @@ Foam::expressions::exprResult::exprResult()
     refCount(),
     valType_(),
     isUniform_(false),
-    isPointVal_(false),
+    isPointData_(false),
     noReset_(false),
     needsReset_(false),
     size_(0),
@@ -245,7 +245,7 @@ Foam::expressions::exprResult::exprResult
     refCount(),
     valType_(dict.getOrDefault<word>("valueType", "")),
     isUniform_(dict.getOrDefault("isSingleValue", uniform)),
-    isPointVal_(dict.getOrDefault("isPointValue", false)),
+    isPointData_(dict.getOrDefault("isPointValue", false)),
     noReset_(dict.getOrDefault("noReset", false)),
     needsReset_(false),
     size_(0),
@@ -268,20 +268,21 @@ Foam::expressions::exprResult::exprResult
 
         const bool ok =
         (
-            readChecked<bool>("value", dict, len, uniform)
-         || readChecked<scalar>("value", dict, len, uniform)
+            // Just use <scalar> for <label>?
+            readChecked<scalar>("value", dict, len, uniform)
          || readChecked<vector>("value", dict, len, uniform)
          || readChecked<tensor>("value", dict, len, uniform)
          || readChecked<symmTensor>("value", dict, len, uniform)
          || readChecked<sphericalTensor>("value", dict, len, uniform)
+         || readChecked<bool>("value", dict, len, uniform)
         );
 
         if (!ok)
         {
             if (valType_.empty())
             {
-                // For the error message only
-                valType_ = "None";
+                // For error message only
+                valType_ = "none";
             }
 
             FatalErrorInFunction
@@ -316,12 +317,13 @@ Foam::expressions::exprResult::New
 
         if (!cstrIter.found())
         {
-            FatalErrorInLookup
+            FatalIOErrorInLookup
             (
+                dict,
                 "resultType",
                 resultType,
                 *emptyConstructorTablePtr_
-            ) << exit(FatalError);
+            ) << exit(FatalIOError);
         }
 
         DebugInfo
@@ -335,12 +337,13 @@ Foam::expressions::exprResult::New
 
     if (!cstrIter.found())
     {
-        FatalErrorInLookup
+        FatalIOErrorInLookup
         (
+            dict,
             "resultType",
             resultType,
             *dictionaryConstructorTablePtr_
-        ) << exit(FatalError);
+        ) << exit(FatalIOError);
     }
 
     DebugInfo
@@ -384,7 +387,7 @@ void Foam::expressions::exprResult::clear()
 {
     uglyDelete();
     valType_.clear();
-    objectPtr_.reset();
+    objectPtr_.reset(nullptr);
     size_ = 0;
 }
 
@@ -496,7 +499,7 @@ void Foam::expressions::exprResult::operator=(const exprResult& rhs)
 
     valType_ = rhs.valType_;
     isUniform_ = rhs.isUniform_;
-    isPointVal_ = rhs.isPointVal_;
+    isPointData_ = rhs.isPointData_;
     single_ = rhs.single_;
 
     if (rhs.fieldPtr_)
@@ -538,7 +541,7 @@ void Foam::expressions::exprResult::operator=(exprResult&& rhs)
 
     valType_ = rhs.valType_;
     isUniform_ = rhs.isUniform_;
-    isPointVal_ = rhs.isPointVal_;
+    isPointData_ = rhs.isPointData_;
     noReset_ = rhs.noReset_;
     needsReset_ = rhs.needsReset_;
     size_ = rhs.size_;
@@ -596,7 +599,7 @@ void Foam::expressions::exprResult::writeDict
     }
 
     os.writeEntry("resultType", valueType());
-    os.writeEntryIfDifferent<Switch>("noReset_", false, noReset_);
+    os.writeEntryIfDifferent<Switch>("noReset", false, noReset_);
 
     if (fieldPtr_ == nullptr)
     {
@@ -606,7 +609,7 @@ void Foam::expressions::exprResult::writeDict
     {
         os.writeEntry("valueType", valType_);
 
-        os.writeEntryIfDifferent<Switch>("isPointValue", false, isPointVal_);
+        os.writeEntryIfDifferent<Switch>("isPointValue", false, isPointData_);
         os.writeEntry<Switch>("isSingleValue", isUniform_);
 
         const bool ok =
diff --git a/src/OpenFOAM/expressions/exprResult/exprResult.H b/src/OpenFOAM/expressions/exprResult/exprResult.H
index 8ad1ec72a27..4588b22997b 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResult.H
+++ b/src/OpenFOAM/expressions/exprResult/exprResult.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -89,8 +89,8 @@ class exprResult
         //- Is single, uniform value (can be a non-field)
         bool isUniform_;
 
-        //- Is a point value
-        bool isPointVal_;
+        //- Represents point data
+        bool isPointData_;
 
         //- Whether or not the variable will be reset
         bool noReset_;
@@ -98,7 +98,7 @@ class exprResult
         //- Allow override of noReset_, but only accessible for subclasses
         bool needsReset_;
 
-        //- Size of field or object
+        //- Size (length) of field or object
         label size_;
 
         //- A %union of single values, including standard VectorSpace types
@@ -112,7 +112,7 @@ class exprResult
             symmTensor symmTensor_;
             sphericalTensor sphTensor_;
 
-            //- Construct null, zero-initialized
+            //- Default construct, zero-initialized
             singleValue();
 
             //- Copy construct
@@ -126,21 +126,24 @@ class exprResult
             inline const T& get() const
             {
                 WarningInFunction
-                    << "Not implemented for type " << pTraits<T>::typeName << nl;
+                    << "Not implemented for type "
+                    << pTraits<T>::typeName << nl;
                 return pTraits<T>::zero;
             }
 
-            //- Set new value for specified type. Returns updated value.
+            //- Set new value for specified type.
+            //  \return updated value
             template<class T>
             inline const T& set(const T& val)
             {
                 WarningInFunction
-                    << "Not implemented for type " << pTraits<T>::typeName << nl;
+                    << "Not implemented for type "
+                    << pTraits<T>::typeName << nl;
                 return val;
             }
         };
 
-        //- The single value
+        //- The single value representation
         singleValue single_;
 
         //- Allocated plain field (eg, scalarField)
@@ -182,7 +185,7 @@ class exprResult
             const bool parRun
         ) const;
 
-        //- Type-checked retrieval of uniform field from current results
+        //- Type-checked retrieval of \c bool uniform field from current result
         //  \return True if the type check was satisfied
         bool getUniformCheckedBool
         (
@@ -233,13 +236,13 @@ class exprResult
 
 
         template<class Type>
-        inline void setResultImpl(Field<Type>*, bool isPointVal=false);
+        inline void setResultImpl(Field<Type>*, bool wantPointData=false);
 
         template<class Type>
-        inline void setResultImpl(const Field<Type>&, bool isPointVal=false);
+        inline void setResultImpl(const Field<Type>&, bool wantPointData=false);
 
         template<class Type>
-        inline void setResultImpl(Field<Type>&&, bool isPointVal=false);
+        inline void setResultImpl(Field<Type>&&, bool wantPointData=false);
 
         template<class Type>
         inline void setResultImpl(const Type& val, const label len);
@@ -250,19 +253,13 @@ class exprResult
         template<class Type>
         inline void setObjectResultImpl(Type* ptr);
 
-        template<class Type>
-        inline void setObjectResultImpl(autoPtr<Type>& ap);
-
-        template<class Type>
-        inline void setObjectResultImpl(autoPtr<Type>&& ap);
-
 
 protected:
 
     // Protected Member Functions
 
         //- Simulate virtual templated methods
-        inline virtual exprResult& target() { return *this; }
+        inline virtual expressions::exprResult& target() { return *this; }
 
         //- Reset at new timestep according to the derived class type
         virtual void resetImpl();
@@ -309,7 +306,7 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         exprResult();
 
         //- Copy construct
@@ -328,23 +325,19 @@ public:
 
         //- Construct by copying a field
         template<class Type>
-        exprResult(const Field<Type>& f);
+        explicit exprResult(const Field<Type>& fld);
 
         //- Construct by moving a field
         template<class Type>
-        exprResult(Field<Type>&& f);
-
-        //- Construct for an IOobject
-        template<class Type>
-        exprResult(autoPtr<Type>& ap);
+        explicit exprResult(Field<Type>&& fld);
 
         //- Construct for an IOobject
         template<class Type>
-        exprResult(autoPtr<Type>&& ap);
+        explicit exprResult(autoPtr<Type>&& obj);
 
         //- Construct from a dimensioned value
         template<class Type>
-        exprResult(const dimensioned<Type>& f);
+        explicit exprResult(const dimensioned<Type>& dt);
 
         #undef exprResult_Construct
         #define exprResult_Construct(Type)                                \
@@ -390,8 +383,9 @@ public:
         //- Basic type for the field or single value
         inline const word& valueType() const;
 
-        //- True if representing point values, or test if same as isPointVal
-        inline bool isPointValue(const bool isPointVal = true) const;
+        //- True if representing point data,
+        //- or test for same value as wantPointData argument
+        inline bool isPointData(const bool wantPointData=true) const;
 
         //- True if single, uniform value
         inline bool isUniform() const;
@@ -400,6 +394,12 @@ public:
         template<class Type>
         inline bool isType() const;
 
+        //- Return a single value when isUniform() is true,
+        //- or Zero when it is non-uniform or if the type mismatches,
+        //- which means that it can generally be considered as failsafe.
+        template<class Type>
+        inline Type getValue() const;
+
         //- True if valueType is a bool
         inline bool isBool() const;
 
@@ -436,15 +436,15 @@ public:
 
         //- Set result field, taking ownership of the pointer
         template<class Type>
-        inline void setResult(Field<Type>*, bool isPointVal=false);
+        inline void setResult(Field<Type>*, bool wantPointData=false);
 
         //- Set result field, taking copy of the field contents
         template<class Type>
-        inline void setResult(const Field<Type>& fld, bool isPointVal=false);
+        inline void setResult(const Field<Type>&, bool wantPointData=false);
 
         //- Set result field, moving field contents
         template<class Type>
-        inline void setResult(Field<Type>&&, bool isPointVal=false);
+        inline void setResult(Field<Type>&&, bool wantPointData=false);
 
         //- Set uniform result field of given size
         template<class Type>
@@ -454,11 +454,9 @@ public:
         template<class Type>
         inline void setSingleValue(const Type& val);
 
+        //- Set result object
         template<class Type>
-        inline void setObjectResult(autoPtr<Type>& o);
-
-        template<class Type>
-        inline void setObjectResult(autoPtr<Type>&& o);
+        inline void setObjectResult(autoPtr<Type>&& obj);
 
 
     // Access/Get results
diff --git a/src/OpenFOAM/expressions/exprResult/exprResultI.H b/src/OpenFOAM/expressions/exprResult/exprResultI.H
index 818fa4758f3..27fb817e82e 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResultI.H
+++ b/src/OpenFOAM/expressions/exprResult/exprResultI.H
@@ -33,18 +33,18 @@ namespace Foam
 namespace expressions
 {
     #undef  defineExpressionMethod
-    #define defineExpressionMethod(Type, Var)                                 \
+    #define defineExpressionMethod(Type, Member)                              \
         template<>                                                            \
         inline const Type& exprResult::singleValue::get<Type>() const         \
         {                                                                     \
-            return Var;                                                       \
+            return Member;                                                    \
         }                                                                     \
                                                                               \
         template<>                                                            \
         inline const Type& exprResult::singleValue::set(const Type& val)      \
         {                                                                     \
-            Var = val;                                                        \
-            return Var;                                                       \
+            Member = val;                                                     \
+            return Member;                                                    \
         }
 
     defineExpressionMethod(bool, bool_);
@@ -67,6 +67,7 @@ template<class Type>
 inline bool Foam::expressions::exprResult::deleteChecked()
 {
     const bool ok = isType<Type>();
+
     if (ok && fieldPtr_ != nullptr)
     {
         delete static_cast<Field<Type>*>(fieldPtr_);
@@ -88,6 +89,7 @@ inline bool Foam::expressions::exprResult::readChecked
 )
 {
     const bool ok = isType<Type>();
+
     if (ok)
     {
         uglyDelete();
@@ -190,52 +192,43 @@ bool Foam::expressions::exprResult::multiplyEqChecked
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class Type>
-Foam::expressions::exprResult::exprResult(const Field<Type>& f)
+Foam::expressions::exprResult::exprResult(const Field<Type>& fld)
 :
     exprResult()
 {
     DebugInFunction << nl;
 
-    setResult(f);
+    setResult(fld);
 }
 
 
 template<class Type>
-Foam::expressions::exprResult::exprResult(Field<Type>&& f)
+Foam::expressions::exprResult::exprResult(Field<Type>&& fld)
 :
     exprResult()
 {
     DebugInFunction << nl;
 
-    setResult(std::move(f));
+    setResult(std::move(fld));
 }
 
 
 template<class Type>
-Foam::expressions::exprResult::exprResult(autoPtr<Type>& o)
+Foam::expressions::exprResult::exprResult(autoPtr<Type>&& obj)
 :
     exprResult()
 {
-    setObjectResult(o);
+    setObjectResult(std::move(obj));
 }
 
 
 template<class Type>
-Foam::expressions::exprResult::exprResult(autoPtr<Type>&& o)
-:
-    exprResult()
-{
-    setObjectResult(o);
-}
-
-
-template<class Type>
-Foam::expressions::exprResult::exprResult(const dimensioned<Type>& f)
+Foam::expressions::exprResult::exprResult(const dimensioned<Type>& dt)
 :
     exprResult()
 {
     DebugInFunction << nl;
-    setSingleValue(f.value());
+    setSingleValue(dt.value());
 }
 
 
@@ -253,12 +246,12 @@ inline const Foam::word& Foam::expressions::exprResult::valueType() const
 }
 
 
-inline bool Foam::expressions::exprResult::isPointValue
+inline bool Foam::expressions::exprResult::isPointData
 (
-    const bool isPointVal
+    const bool wantPointData
 ) const
 {
-    return isPointVal_ == isPointVal;
+    return isPointData_ == wantPointData;
 }
 
 
@@ -275,6 +268,18 @@ inline bool Foam::expressions::exprResult::isType() const
 }
 
 
+template<class Type>
+inline Type Foam::expressions::exprResult::getValue() const
+{
+    if (!isUniform_ || !isType<Type>())
+    {
+        return Zero;
+    }
+
+    return single_.get<Type>();
+}
+
+
 inline bool Foam::expressions::exprResult::isBool() const
 {
     return valType_ == pTraits<bool>::typeName;
@@ -297,12 +302,12 @@ template<class Type>
 void Foam::expressions::exprResult::setResult
 (
     const Field<Type>& val,
-    bool isPointVal
+    bool wantPointData
 )
 {
     DebugInFunction << nl;
 
-    target().setResultImpl(val, isPointVal);
+    target().setResultImpl(val, wantPointData);
 }
 
 
@@ -310,12 +315,12 @@ template<class Type>
 void Foam::expressions::exprResult::setResult
 (
     Field<Type>&& val,
-    bool isPointVal
+    bool wantPointData
 )
 {
     DebugInFunction << nl;
 
-    target().setResultImpl(val, isPointVal);
+    target().setResultImpl(val, wantPointData);
 }
 
 
@@ -323,7 +328,7 @@ template<class Type>
 void Foam::expressions::exprResult::setResultImpl
 (
     const Field<Type>& fld,
-    bool isPointVal
+    bool wantPointData
 )
 {
     DebugInFunction << nl;
@@ -331,7 +336,7 @@ void Foam::expressions::exprResult::setResultImpl
     clear();
 
     isUniform_ = false;
-    isPointVal_ = isPointVal;
+    isPointData_ = wantPointData;
 
     size_ = fld.size();
     valType_ = pTraits<Type>::typeName;
@@ -345,7 +350,7 @@ template<class Type>
 void Foam::expressions::exprResult::setResultImpl
 (
     Field<Type>&& fld,
-    bool isPointVal
+    bool wantPointData
 )
 {
     DebugInFunction << nl;
@@ -353,7 +358,7 @@ void Foam::expressions::exprResult::setResultImpl
     clear();
 
     isUniform_ = false;
-    isPointVal_ = isPointVal;
+    isPointData_ = wantPointData;
 
     size_ = fld.size();
     valType_ = pTraits<Type>::typeName;
@@ -364,44 +369,26 @@ void Foam::expressions::exprResult::setResultImpl
 
 
 template<class Type>
-void Foam::expressions::exprResult::setObjectResult(autoPtr<Type>& ap)
+void Foam::expressions::exprResult::setObjectResult(autoPtr<Type>&& obj)
 {
-    target().setObjectResultImpl(ap.ptr());
-}
-
-
-template<class Type>
-void Foam::expressions::exprResult::setObjectResult(autoPtr<Type>&& ap)
-{
-    target().setObjectResultImpl(ap.ptr());
+    target().setObjectResultImpl(obj.ptr());  // release()
 }
 
 
 template<class T>
 void Foam::expressions::exprResult::setObjectResultImpl(T* ptr)
 {
-    DebugInFunction << nl;
+    clear();
 
     isUniform_ = false;
-    isPointVal_ = false;
-
-    size_ = ptr->size();
-    valType_ = ptr->typeName;
-    objectPtr_.reset(ptr);
-}
-
-
-template<class T>
-void Foam::expressions::exprResult::setObjectResultImpl(autoPtr<T>& o)
-{
-    setObjectResultImpl(o.ptr());
-}
+    isPointData_ = false;
 
-
-template<class T>
-void Foam::expressions::exprResult::setObjectResultImpl(autoPtr<T>&& o)
-{
-    setObjectResultImpl(o.ptr());
+    if (ptr != nullptr)
+    {
+        size_ = ptr->size();
+        valType_ = ptr->typeName;
+        objectPtr_.reset(ptr);
+    }
 }
 
 
@@ -409,10 +396,10 @@ template<class Type>
 void Foam::expressions::exprResult::setResult
 (
     Field<Type>* fldPtr,
-    bool isPointVal
+    bool wantPointData
 )
 {
-    target().setResultImpl(fldPtr, isPointVal);
+    target().setResultImpl(fldPtr, wantPointData);
 }
 
 
@@ -420,19 +407,20 @@ template<class Type>
 void Foam::expressions::exprResult::setResultImpl
 (
     Field<Type>* fldPtr,
-    bool isPointVal
+    bool wantPointData
 )
 {
-    DebugInFunction << nl;
-
     clear();
 
-    isPointVal_ = isPointVal;
     isUniform_ = false;
+    isPointData_ = wantPointData;
 
-    size_ = fldPtr->size();
-    valType_ = pTraits<Type>::typeName;
-    fieldPtr_ = fldPtr;
+    if (fldPtr != nullptr)
+    {
+        size_ = fldPtr->size();
+        valType_ = pTraits<Type>::typeName;
+        fieldPtr_ = fldPtr;
+    }
 }
 
 
@@ -458,7 +446,7 @@ void Foam::expressions::exprResult::setResultImpl
 
     clear();
 
-    isPointVal_ = false;
+    isPointData_ = false;
 
     size_ = len;
     valType_ = pTraits<Type>::typeName;
@@ -653,8 +641,8 @@ void Foam::expressions::exprResult::setSingleValueImpl(const Type& val)
 
     clear();
 
-    isPointVal_ = false;
     isUniform_ = true;
+    isPointData_ = false;
 
     single_.set(val);
     size_ = 1;
diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStack.H b/src/OpenFOAM/expressions/exprResult/exprResultStack.H
index 6efdd0b1279..b8737431a41 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResultStack.H
+++ b/src/OpenFOAM/expressions/exprResult/exprResultStack.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -78,7 +78,7 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         exprResultStack();
 
         //- Copy construct
diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStored.H b/src/OpenFOAM/expressions/exprResult/exprResultStored.H
index 5d0a9a07d1e..cb9755dd4bf 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResultStored.H
+++ b/src/OpenFOAM/expressions/exprResult/exprResultStored.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -89,7 +89,7 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         exprResultStored();
 
         //- Copy construct
diff --git a/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H
index 8475e49f8fe..1bdeab2a892 100644
--- a/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H
+++ b/src/OpenFOAM/expressions/exprResult/exprResultStoredStack.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -71,7 +71,7 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         exprResultStoredStack();
 
         //- Copy construct
diff --git a/src/OpenFOAM/expressions/fields/fieldExprDriverTemplates.C b/src/OpenFOAM/expressions/fields/fieldExprDriverTemplates.C
index bac587f61eb..073171f0c94 100644
--- a/src/OpenFOAM/expressions/fields/fieldExprDriverTemplates.C
+++ b/src/OpenFOAM/expressions/fields/fieldExprDriverTemplates.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,43 +34,42 @@ Foam::expressions::fieldExpr::parseDriver::getField
     const word& name
 ) const
 {
-    bool isPointVal = false;
-    bool isUniformVal = false;
+    bool hasPointData = false;
 
-    tmp<Field<Type>> tfield;
+    refPtr<expressions::exprResult> tvar;
 
     if (hasVariable(name) && variable(name).isType<Type>())
     {
-        const expressions::exprResult& var = variable(name);
-
-        isPointVal = var.isPointValue();
-        isUniformVal = var.isUniform();
-
-        tfield = var.cref<Type>().clone();
+        tvar.cref(variable(name));
+        hasPointData = tvar().isPointData();
     }
 
-    if (tfield.valid())
+
+    if (tvar.valid())
     {
-        const label fldLen = tfield().size();
-        const label len = (isPointVal ? this->pointSize() : this->size());
+        const auto& var = tvar.cref();
+        const Field<Type>& vals = var.cref<Type>();
+
+        const label len = (hasPointData ? this->pointSize() : this->size());
 
-        if (returnReduce((fldLen == len), andOp<bool>()))
+        if (returnReduce((vals.size() == len), andOp<bool>()))
         {
-            return tfield;
+            // Return a copy of the field
+            return tmp<Field<Type>>::New(vals);
         }
 
-        if (!isUniformVal)
+        if (!var.isUniform())
         {
             WarningInFunction
                 << "Variable " << name
-                << " does not fit the size and is not a uniform value." << nl
-                << "Using average value" << endl;
+                << " is nonuniform and does not fit the size"
+                << ". Using average" << endl;
         }
 
-        return tmp<Field<Type>>::New(this->size(), gAverage(tfield));
+        return tmp<Field<Type>>::New(this->size(), gAverage(vals));
     }
 
-    return tfield;
+    return nullptr;
 }
 
 
diff --git a/src/finiteVolume/expressions/base/fvExprDriver.H b/src/finiteVolume/expressions/base/fvExprDriver.H
index e532636b2d8..fe49ba05a50 100644
--- a/src/finiteVolume/expressions/base/fvExprDriver.H
+++ b/src/finiteVolume/expressions/base/fvExprDriver.H
@@ -163,6 +163,7 @@ protected:
         }
 
         //- Default boundary type for volume fields is zeroGradient
+        //- since they are essentially just internal fields.
         template<class Type>
         static inline word defaultBoundaryType
         (
@@ -211,8 +212,8 @@ protected:
         bool isGlobalVariable
         (
             const word& name,
-            bool isPointVal,
-            label expectedSize = -1
+            const bool wantPointData = false,
+            const label expectedSize = -1
         ) const;
 
         //- Return the global variable if available or a null result
@@ -226,8 +227,8 @@ protected:
         bool isField
         (
             const word& name,
-            bool isPointVal = false,
-            label expectSize = -1  //!< ignored
+            const bool wantPointData = false,
+            const label expectSize = -1  //!< ignored
         ) const;
 
 
@@ -236,8 +237,8 @@ protected:
         inline tmp<GeomField> getOrReadField
         (
             const word& name,
-            bool mandatory = true,
-            bool getOldTime = false
+            const bool mandatory = true,
+            const bool getOldTime = false
         );
 
         //- Retrieve point field from memory or disk
@@ -245,8 +246,8 @@ protected:
         inline tmp<GeomField> getOrReadPointField
         (
             const word& name,
-            bool mandatory = true,
-            bool getOldTime = false
+            const bool mandatory = true,
+            const bool getOldTime = false
         );
 
         //- Retrieve field from memory or disk (implementation)
@@ -255,8 +256,8 @@ protected:
         (
             const word& name,
             const MeshRef& meshRef,
-            bool mandatory = true,
-            bool getOldTime = false
+            const bool mandatory = true,
+            const bool getOldTime = false
         );
 
         //- Helper function for getOrReadField
@@ -461,8 +462,8 @@ public:
         inline bool isVariableOrField
         (
             const word& name,
-            bool isPointVal = false,
-            label expectSize = -1
+            const bool wantPointData = false,
+            const label expectSize = -1
         ) const;
 
         //- Retrieve local/global variable as a tmp field
@@ -475,7 +476,7 @@ public:
         tmp<Field<Type>> getVariable
         (
             const word& name,
-            label expectSize,
+            const label expectSize,
             const bool mandatory = true
         ) const;
 
@@ -568,7 +569,7 @@ public:
         inline bool isVariable
         (
             const word& name,
-            bool isPointVal = false,
+            bool wantPointData = false,
             label expectSize = -1
         ) const;
 
diff --git a/src/finiteVolume/expressions/base/fvExprDriverI.H b/src/finiteVolume/expressions/base/fvExprDriverI.H
index 004871bc5d3..5ad3c395f3e 100644
--- a/src/finiteVolume/expressions/base/fvExprDriverI.H
+++ b/src/finiteVolume/expressions/base/fvExprDriverI.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -73,14 +73,14 @@ template<class Type>
 inline bool Foam::expressions::fvExprDriver::isVariable
 (
     const word& name,
-    bool isPointVal,
-    label expectedSize
+    const bool wantPointData,
+    const label expectedSize
 ) const
 {
     return
     (
-        this->isLocalVariable<Type>(name, isPointVal, expectedSize)
-     || this->isGlobalVariable<Type>(name, isPointVal, expectedSize)
+        this->isLocalVariable<Type>(name, wantPointData, expectedSize)
+     || this->isGlobalVariable<Type>(name, wantPointData, expectedSize)
     );
 }
 
@@ -89,15 +89,15 @@ template<class Type>
 inline bool Foam::expressions::fvExprDriver::isVariableOrField
 (
     const word& name,
-    bool isPointVal,
-    label expectedSize
+    const bool wantPointData,
+    const label expectedSize
 )
 const
 {
     return
     (
-        this->isVariable<Type>(name, isPointVal, expectedSize)
-     || this->isField<Type>(name, isPointVal)
+        this->isVariable<Type>(name, wantPointData, expectedSize)
+     || this->isField<Type>(name, wantPointData)
     );
 }
 
@@ -107,8 +107,8 @@ inline Foam::tmp<GeomField>
 Foam::expressions::fvExprDriver::getOrReadField
 (
     const word& name,
-    bool mandatory,
-    bool getOldTime
+    const bool mandatory,
+    const bool getOldTime
 )
 {
     return this->getOrReadFieldImpl<GeomField>
@@ -126,8 +126,8 @@ inline Foam::tmp<GeomField>
 Foam::expressions::fvExprDriver::getOrReadPointField
 (
     const word& name,
-    bool mandatory,
-    bool getOldTime
+    const bool mandatory,
+    const bool getOldTime
 )
 {
     return this->getOrReadFieldImpl<GeomField>
diff --git a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C
index 70eda6a08d8..2ee53ed84e2 100644
--- a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C
+++ b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -36,21 +36,23 @@ template<class Type>
 bool Foam::expressions::fvExprDriver::isGlobalVariable
 (
     const word& name,
-    bool isPointVal,
-    label expectedSize
+    const bool wantPointData,
+    const label expectedSize
 ) const
 {
     DebugInfo
-        << "Looking for global" << (isPointVal ? " point" : "")
+        << "Looking for global" << (wantPointData ? " point" : "")
         << " field name:" << name;
 
-    const exprResult& result = lookupGlobal(name);
+    const expressions::exprResult& result = lookupGlobal(name);
 
     DebugInfo
-        << " - found (" << result.valueType() << ' ' << result.isPointValue() << ')';
+        << " - found (" << result.valueType() << ' '
+        << result.isPointData() << ')';
 
 
-    bool good = (result.isType<Type>() && result.isPointValue(isPointVal));
+    bool good =
+        (result.isType<Type>() && result.isPointData(wantPointData));
 
     // Do size checking if requested
     if (good && expectedSize >= 0)
@@ -75,48 +77,47 @@ Foam::tmp<Foam::Field<Type>>
 Foam::expressions::fvExprDriver::getVariable
 (
     const word& name,
-    label expectedSize,
+    const label expectedSize,
     const bool mandatory
 ) const
 {
-    tmp<Field<Type>> tresult;
-
-    bool isSingleValue = false;
+    refPtr<expressions::exprResult> tvar;
 
     if (hasVariable(name) && variable(name).isType<Type>())
     {
-        isSingleValue = variable(name).isUniform();
-        tresult = variable(name).cref<Type>().clone();
+        tvar.cref(variable(name));
     }
-    else if (isGlobalVariable<Type>(name, false))
+    else if (isGlobalVariable<Type>(name))
     {
-        const exprResult& var = lookupGlobal(name);
-
-        isSingleValue = var.isUniform();
-
-        tresult = var.cref<Type>().clone();
+        tvar.cref(lookupGlobal(name));
     }
 
-    if (tresult.valid())
+
+    if (tvar.valid())
     {
+        const auto& var = tvar.cref();
+
+        const Field<Type>& vals = var.cref<Type>();
+
         if
         (
             expectedSize < 0
-         || returnReduce((tresult->size() == expectedSize), andOp<bool>())
+         || returnReduce((vals.size() == expectedSize), andOp<bool>())
         )
         {
-            return tresult;
+            // Return a copy of the field
+            return tmp<Field<Type>>::New(vals);
         }
 
-        if (!isSingleValue)
+        if (!var.isUniform())
         {
             WarningInFunction
                 << "Variable " << name
-                << " is not a single value and does not fit the size "
+                << " is nonuniform and does not fit the size "
                 << expectedSize << ". Using average" << endl;
         }
 
-        return tmp<Field<Type>>::New(expectedSize, gAverage(tresult()));
+        return tmp<Field<Type>>::New(expectedSize, gAverage(vals));
     }
 
     if (mandatory)
@@ -197,7 +198,7 @@ template<class Type>
 bool Foam::expressions::fvExprDriver::isField
 (
     const word& name,
-    bool isPointVal,
+    bool wantPointData,
     label
 ) const
 {
@@ -212,7 +213,7 @@ bool Foam::expressions::fvExprDriver::isField
 
     return
     (
-        isPointVal
+        wantPointData
       ? this->foundField<pfieldType>(name)
       :
         (
@@ -240,17 +241,29 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
             << "> Type: " << GeomField::typeName << endl;
     }
 
+    refPtr<expressions::exprResult> tvar;
+
+    if (hasVariable(name) && variable(name).isType<Type>())
+    {
+        tvar.cref(variable(name));
+    }
+    else if (isGlobalVariable<Type>(name))
+    {
+        tvar.cref(lookupGlobal(name));
+    }
+
+
     tmp<GeomField> tfield;
 
-    if
-    (
-        (hasVariable(name) && variable(name).isType<Type>())
-     || isGlobalVariable<Type>(name, false)
-    )
+    if (tvar.valid())
     {
+        const auto& var = tvar.cref();
+        const Type deflt(var.getValue<Type>());
+
         if (debug)
         {
-            Info<< "Getting " << name << " from variables" << endl;
+            Info<< "Getting " << name << " from variables. Default: "
+                << deflt << endl;
         }
 
         if (debug)
@@ -259,12 +272,15 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
                 << GeomField::typeName << nl;
         }
 
-        tfield.reset
+        tfield = GeomField::New
         (
-            GeomField::New(name, meshRef, dimensioned<Type>(Zero))
+            name,
+            meshRef,
+            dimensioned<Type>(deflt),
+            // Patch is zeroGradient (volFields) or calculated (other)
+            defaultBoundaryType(GeomField::null())
         );
-
-        GeomField& fld = tfield.ref();
+        auto& fld = tfield.ref();
 
         if (debug)
         {
@@ -272,16 +288,7 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
                 << fld.ownedByRegistry() << endl;
         }
 
-        Field<Type> vals;
-
-        if (hasVariable(name) && variable(name).isType<Type>())
-        {
-            vals = variable(name).cref<Type>();
-        }
-        else
-        {
-            vals = lookupGlobal(name).cref<Type>();
-        }
+        const Field<Type>& vals = var.cref<Type>();
 
         if (debug)
         {
@@ -294,7 +301,7 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
         }
         else
         {
-            Type avg = gAverage(vals);
+            const Type avg = gAverage(vals);
 
             bool noWarn = false;
 
@@ -321,21 +328,23 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
 
     const objectRegistry& obr = meshRef.thisDb();
 
-    if (searchInMemory() && obr.foundObject<GeomField>(name))
+    const GeomField* origFldPtr;
+
+    if
+    (
+        searchInMemory()
+     && (origFldPtr = obr.cfindObject<GeomField>(name)) != nullptr
+    )
     {
         if (debug)
         {
             Info<< "Retrieve registered: " << name << nl;
         }
 
-        const GeomField& origFld = obr.lookupObject<GeomField>(name);
+        const GeomField& origFld = *origFldPtr;
 
         // Avoid shadowing the original object
-
-        tfield.reset
-        (
-            GeomField::New(name + "_exprDriverCopy", origFld)
-        );
+        tfield = GeomField::New(name + "_exprDriverCopy", origFld);
 
         if (getOldTime)
         {
@@ -369,9 +378,10 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
         // oldTime automatically read
     }
 
+
     if (debug)
     {
-        Info<< "field: valid()=" << tfield.valid() << endl;
+        Info<< "field: valid()=" << Switch::name(tfield.valid()) << endl;
     }
 
     if (tfield.valid())
diff --git a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C
index 64176eb47c1..8d0e5e39748 100644
--- a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C
+++ b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C
@@ -39,7 +39,7 @@ void Foam::expressions::patchExprFieldBase::readExpressions
 (
     const dictionary& dict,
     enum expectedTypes expectedType,
-    bool isPointVal
+    bool wantPointData
 )
 {
     if (debug_)
@@ -108,7 +108,7 @@ void Foam::expressions::patchExprFieldBase::readExpressions
         else if (!exprFrac.empty())
         {
             evalFrac = true;
-            if (isPointVal)
+            if (wantPointData)
             {
                 exprFrac = "toPoint(" + exprFrac + ")";
             }
@@ -149,7 +149,7 @@ Foam::expressions::patchExprFieldBase::patchExprFieldBase
 (
     const dictionary& dict,
     enum expectedTypes expectedType,
-    bool isPointVal
+    bool wantPointData
 )
 :
     debug_(dict.getOrDefault("debug", false)),
@@ -158,7 +158,7 @@ Foam::expressions::patchExprFieldBase::patchExprFieldBase
     gradExpr_(),
     fracExpr_()
 {
-    readExpressions(dict, expectedType, isPointVal);
+    readExpressions(dict, expectedType, wantPointData);
 }
 
 
diff --git a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H
index bb15e768e2e..9c3ceef058e 100644
--- a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H
+++ b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H
@@ -99,7 +99,7 @@ private:
         (
             const dictionary& dict,
             enum expectedTypes expectedType,
-            bool isPointVal = false
+            bool wantPointData = false
         );
 
 
@@ -118,7 +118,7 @@ public:
         (
             const dictionary& dict,
             enum expectedTypes expectedType = expectedTypes::VALUE_TYPE,
-            bool isPointVal = false
+            bool wantPointData = false
         );
 
 
diff --git a/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C
index 7fafffbc503..1fe151c0794 100644
--- a/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C
+++ b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -36,51 +36,46 @@ Foam::expressions::patchExpr::parseDriver::getVariableIfAvailable
     const word& name
 ) const
 {
-    bool isPointVal = false;
-    bool isUniformVal = false;
+    bool hasPointData = false;
 
-    tmp<Field<Type>> tfield;
+    refPtr<expressions::exprResult> tvar;
 
     if (hasVariable(name) && variable(name).isType<Type>())
     {
-        const expressions::exprResult& var = variable(name);
-
-        isPointVal = var.isPointValue();
-        isUniformVal = var.isUniform();
-
-        tfield = var.cref<Type>().clone();
+        tvar.cref(variable(name));
+        hasPointData = tvar().isPointData();
     }
-    else if (isGlobalVariable<Type>(name, false))
+    else if (isGlobalVariable<Type>(name))
     {
-        const expressions::exprResult& var = lookupGlobal(name);
-
-        isUniformVal = var.isUniform();
-
-        tfield = var.cref<Type>().clone();
+        tvar.cref(lookupGlobal(name));
     }
 
-    if (tfield.valid())
+
+    if (tvar.valid())
     {
-        const label fldLen = tfield().size();
-        const label len = (isPointVal ? this->pointSize() : this->size());
+        const auto& var = tvar.cref();
+        const Field<Type>& vals = var.cref<Type>();
+
+        const label len = (hasPointData ? this->pointSize() : this->size());
 
-        if (returnReduce((fldLen == len), andOp<bool>()))
+        if (returnReduce((vals.size() == len), andOp<bool>()))
         {
-            return tfield;
+            // Return a copy of the field
+            return tmp<Field<Type>>::New(vals);
         }
 
-        if (!isUniformVal)
+        if (!var.isUniform())
         {
             WarningInFunction
                 << "Variable " << name
-                << " does not fit the size and is not a uniform value." << nl
-                << "Using average value" << endl;
+                << " is nonuniform and does not fit the size"
+                << ". Using average" << endl;
         }
 
-        return tmp<Field<Type>>::New(this->size(), gAverage(tfield));
+        return tmp<Field<Type>>::New(this->size(), gAverage(vals));
     }
 
-    return tfield;
+    return nullptr;
 }
 
 
-- 
GitLab