From 8f572a5e71d287e6aa0838b4cd810bd01d40c33d Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 6 Feb 2019 10:25:47 +0100
Subject: [PATCH] ENH: improve volRegion handling of moving meshes (#1194)

- implemented as lazy evaluation with an additional update() method.
  This avoids unnecessary changes until the values are actually
  required.

- apply mesh motion changes for momentum, volFieldValue,
  specieReactionRates function objects
---
 .../functionObjects/volRegion/volRegion.C     | 33 +++++++++---
 .../functionObjects/volRegion/volRegion.H     | 12 +++++
 .../functionObjects/volRegion/volRegionI.H    | 27 ++++++++++
 .../fieldValues/volFieldValue/volFieldValue.C | 10 ++--
 .../fieldValues/volFieldValue/volFieldValue.H |  4 +-
 .../volFieldValue/volFieldValueTemplates.C    | 10 ++--
 src/functionObjects/field/momentum/momentum.C | 52 +++++++++++++------
 src/functionObjects/field/momentum/momentum.H |  3 ++
 .../specieReactionRates/specieReactionRates.C | 21 +++-----
 .../specieReactionRates/specieReactionRates.H |  6 +--
 .../XiEngineFoam/kivaTest/system/controlDict  |  2 +
 .../XiEngineFoam/kivaTest/system/momentum     | 33 ++++++++++++
 12 files changed, 161 insertions(+), 52 deletions(-)
 create mode 100644 tutorials/combustion/XiEngineFoam/kivaTest/system/momentum

diff --git a/src/finiteVolume/functionObjects/volRegion/volRegion.C b/src/finiteVolume/functionObjects/volRegion/volRegion.C
index ceb7cdb801b..218639dde4f 100644
--- a/src/finiteVolume/functionObjects/volRegion/volRegion.C
+++ b/src/finiteVolume/functionObjects/volRegion/volRegion.C
@@ -109,6 +109,8 @@ void Foam::functionObjects::volRegion::calculateCache()
             << "    Region has no cells"
             << exit(FatalError);
     }
+
+    requireUpdate_ = false;
 }
 
 
@@ -137,6 +139,7 @@ Foam::functionObjects::volRegion::volRegion
 )
 :
     volMesh_(mesh),
+    requireUpdate_(true),
     cellIds_(),
     nCells_(0),
     V_(Zero),
@@ -158,10 +161,7 @@ Foam::functionObjects::volRegion::volRegion
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-bool Foam::functionObjects::volRegion::read
-(
-    const dictionary& dict
-)
+bool Foam::functionObjects::volRegion::read(const dictionary& dict)
 {
     switch (regionType_)
     {
@@ -195,6 +195,15 @@ bool Foam::functionObjects::volRegion::read
 
 const Foam::labelList& Foam::functionObjects::volRegion::cellIDs() const
 {
+    #ifdef FULLDEBUG
+    if (requireUpdate_)
+    {
+        FatalErrorInFunction
+            << "Retrieving cached values that are not up-to-date" << nl
+            << exit(FatalError);
+    }
+    #endif
+
     switch (regionType_)
     {
         case vrtCellSet:
@@ -213,15 +222,27 @@ const Foam::labelList& Foam::functionObjects::volRegion::cellIDs() const
 }
 
 
+bool Foam::functionObjects::volRegion::update()
+{
+    if (requireUpdate_)
+    {
+        calculateCache();
+        return true;
+    }
+
+    return false;
+}
+
+
 void Foam::functionObjects::volRegion::updateMesh(const mapPolyMesh&)
 {
-    calculateCache();
+    requireUpdate_ = true;
 }
 
 
 void Foam::functionObjects::volRegion::movePoints(const polyMesh&)
 {
-    calculateCache();
+    requireUpdate_ = true;
 }
 
 
diff --git a/src/finiteVolume/functionObjects/volRegion/volRegion.H b/src/finiteVolume/functionObjects/volRegion/volRegion.H
index 7702368c2f4..2f05c292b1a 100644
--- a/src/finiteVolume/functionObjects/volRegion/volRegion.H
+++ b/src/finiteVolume/functionObjects/volRegion/volRegion.H
@@ -30,6 +30,11 @@ Group
 Description
     Volume (cell) region selection class.
 
+    The adjustments for mesh changes have been implemented with a lazy
+    evaluation, to avoid unnecessary recalculation until the values are
+    actually required. The update() method is used to ensure the cache
+    values are up-to-date.
+
     Examples of function object specification:
     \verbatim
     volRegion0
@@ -96,6 +101,9 @@ class volRegion
 
         const fvMesh& volMesh_;
 
+        //- Flag to indicate whether the volRegion requires updating
+        bool requireUpdate_;
+
         //- The cell ids, from cellSet
         labelList cellIds_;
 
@@ -178,6 +186,10 @@ public:
         //- Return total volume of the selected region
         inline scalar V() const;
 
+        //- Update the cached values as required
+        //  \return False if the values were already up to date
+        bool update();
+
 
         //- Read from dictionary
         virtual bool read(const dictionary& dict);
diff --git a/src/finiteVolume/functionObjects/volRegion/volRegionI.H b/src/finiteVolume/functionObjects/volRegion/volRegionI.H
index b2a810a7252..81efe0c0289 100644
--- a/src/finiteVolume/functionObjects/volRegion/volRegionI.H
+++ b/src/finiteVolume/functionObjects/volRegion/volRegionI.H
@@ -28,18 +28,45 @@ License
 inline const Foam::functionObjects::volRegion::regionTypes&
 Foam::functionObjects::volRegion::regionType() const
 {
+    #ifdef FULLDEBUG
+    if (requireUpdate_)
+    {
+        FatalErrorInFunction
+            << "Retrieving cached values that are not up-to-date" << nl
+            << exit(FatalError);
+    }
+    #endif
+
     return regionType_;
 }
 
 
 inline Foam::label Foam::functionObjects::volRegion::nCells() const
 {
+    #ifdef FULLDEBUG
+    if (requireUpdate_)
+    {
+        FatalErrorInFunction
+            << "Retrieving cached values that are not up-to-date" << nl
+            << exit(FatalError);
+    }
+    #endif
+
     return nCells_;
 }
 
 
 inline Foam::scalar Foam::functionObjects::volRegion::V() const
 {
+    #ifdef FULLDEBUG
+    if (requireUpdate_)
+    {
+        FatalErrorInFunction
+            << "Retrieving cached values that are not up-to-date" << nl
+            << exit(FatalError);
+    }
+    #endif
+
     return V_;
 }
 
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
index 9a356559dba..4c87de3f578 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -229,12 +229,6 @@ Foam::functionObjects::fieldValues::volFieldValue::volFieldValue
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::functionObjects::fieldValues::volFieldValue::~volFieldValue()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::functionObjects::fieldValues::volFieldValue::read
@@ -251,6 +245,8 @@ bool Foam::functionObjects::fieldValues::volFieldValue::read
 
 bool Foam::functionObjects::fieldValues::volFieldValue::write()
 {
+    volRegion::update();        // Ensure cached values are valid
+
     fieldValue::write();
 
     if (Pstream::master())
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
index ae299430ae2..ee3b63777ea 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -272,7 +272,7 @@ public:
 
 
     //- Destructor
-    virtual ~volFieldValue();
+    virtual ~volFieldValue() = default;
 
 
     // Public Member Functions
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
index c74056862c6..91641ad3515 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -260,14 +260,12 @@ Foam::functionObjects::fieldValues::volFieldValue::filterField
     const Field<Type>& field
 ) const
 {
-    if (isNull(cellIDs()))
+    if (volRegion::vrtAll == this->volRegion::regionType())
     {
         return field;
     }
-    else
-    {
-        return tmp<Field<Type>>::New(field, cellIDs());
-    }
+
+    return tmp<Field<Type>>::New(field, cellIDs());
 }
 
 
diff --git a/src/functionObjects/field/momentum/momentum.C b/src/functionObjects/field/momentum/momentum.C
index d36af0afd3b..342b46eb978 100644
--- a/src/functionObjects/field/momentum/momentum.C
+++ b/src/functionObjects/field/momentum/momentum.C
@@ -44,6 +44,16 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
 
+void Foam::functionObjects::momentum::purgeFields()
+{
+    objectRegistry& obr = const_cast<objectRegistry&>(obr_);
+
+    obr.erase(scopedName("momentum"));
+    obr.erase(scopedName("angularMomentum"));
+    obr.erase(scopedName("angularVelocity"));
+}
+
+
 template<class GeoField>
 Foam::autoPtr<GeoField>
 Foam::functionObjects::momentum::newField
@@ -75,6 +85,13 @@ void Foam::functionObjects::momentum::calc()
 {
     initialise();
 
+    // Ensure volRegion is properly up-to-date.
+    // Purge old fields if anything has changed (eg, mesh size etc)
+    if (volRegion::update())
+    {
+        purgeFields();
+    }
+
     // When field writing is not enabled we need our local storage
     // for the momentum and angular velocity fields
     autoPtr<volVectorField> tmomentum, tAngularMom, tAngularVel;
@@ -292,22 +309,27 @@ void Foam::functionObjects::momentum::initialise()
 
 void Foam::functionObjects::momentum::writeValues(Ostream& os)
 {
-    Log << type() << " " << name() << " write:" << nl;
+    if (log)
+    {
+        Info<< type() << " " << name() << " write:" << nl;
 
-    Log << "    Sum of Momentum";
+        Info<< "    Sum of Momentum";
 
-    if (regionType_ != vrtAll)
-    {
-        Log << ' ' << regionTypeNames_[regionType_]
-            << ' ' << regionName_;
-    }
+        if (regionType_ != vrtAll)
+        {
+            Info<< ' ' << regionTypeNames_[regionType_]
+                << ' ' << regionName_;
+        }
 
-    Log << nl
-        << "        linear  : " << sumMomentum_ << nl;
+        Info<< " (volume " << volRegion::V() << ')' << nl
+            << "        linear  : " << sumMomentum_ << nl;
 
-    if (hasCsys_)
-    {
-        Log << "        angular : " << sumAngularMom_ << nl;
+        if (hasCsys_)
+        {
+            Info<< "        angular : " << sumAngularMom_ << nl;
+        }
+
+        Info<< endl;
     }
 
     if (writeToFile())
@@ -323,8 +345,6 @@ void Foam::functionObjects::momentum::writeValues(Ostream& os)
 
         os << tab << volRegion::V() << endl;
     }
-
-    Log << endl;
 }
 
 
@@ -496,7 +516,7 @@ bool Foam::functionObjects::momentum::write()
 {
     if (writeMomentum_ || (hasCsys_ && (writeVelocity_ || writePosition_)))
     {
-        Log <<"Writing fields" << nl;
+        Log << "Writing fields" << nl;
 
         const volVectorField* fieldPtr;
 
@@ -572,12 +592,14 @@ bool Foam::functionObjects::momentum::write()
 void Foam::functionObjects::momentum::updateMesh(const mapPolyMesh& mpm)
 {
     volRegion::updateMesh(mpm);
+    purgeFields();  // Mesh motion makes calculated fields dubious
 }
 
 
 void Foam::functionObjects::momentum::movePoints(const polyMesh& pm)
 {
     volRegion::movePoints(pm);
+    purgeFields();  // Mesh motion makes calculated fields dubious
 }
 
 
diff --git a/src/functionObjects/field/momentum/momentum.H b/src/functionObjects/field/momentum/momentum.H
index 4db24cbfe48..b6ad1c3b2d8 100644
--- a/src/functionObjects/field/momentum/momentum.H
+++ b/src/functionObjects/field/momentum/momentum.H
@@ -134,6 +134,9 @@ class momentum
 {
     // Private Member Functions
 
+        //- Remove calculated fields from the registry
+        void purgeFields();
+
         //- Calculate the fields and integral values
         void calc();
 
diff --git a/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.C b/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.C
index ff2c442d801..4a8e9cd0557 100644
--- a/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.C
+++ b/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2016-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -82,14 +82,6 @@ specieReactionRates
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-template<class ChemistryModelType>
-Foam::functionObjects::specieReactionRates<ChemistryModelType>::
-~specieReactionRates()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class ChemistryModelType>
@@ -117,8 +109,11 @@ bool Foam::functionObjects::specieReactionRates<ChemistryModelType>::write()
     const label nSpecie = chemistryModel_.nSpecie();
     const label nReaction = chemistryModel_.nReaction();
 
-    // Region volume
-    const scalar V = this->V();
+    volRegion::update();        // Ensure cached values are valid
+
+    const scalar volTotal = this->volRegion::V();
+
+    const bool useAll = (volRegion::vrtAll == this->volRegion::regionType());
 
     for (label ri=0; ri<nReaction; ri++)
     {
@@ -134,7 +129,7 @@ bool Foam::functionObjects::specieReactionRates<ChemistryModelType>::write()
 
             scalar sumVRRi = 0;
 
-            if (isNull(cellIDs()))
+            if (useAll)
             {
                 sumVRRi = fvc::domainIntegrate(RR).value();
             }
@@ -146,7 +141,7 @@ bool Foam::functionObjects::specieReactionRates<ChemistryModelType>::write()
                 );
             }
 
-            file() << token::TAB << sumVRRi/V;
+            file() << token::TAB << sumVRRi / volTotal;
         }
 
         file() << nl;
diff --git a/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.H b/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.H
index 5e89180183f..3e9debb4f7b 100644
--- a/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.H
+++ b/src/thermophysicalModels/chemistryModel/functionObjects/specieReactionRates/specieReactionRates.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -101,13 +101,13 @@ public:
 
 
     //- Destructor
-    virtual ~specieReactionRates();
+    virtual ~specieReactionRates() = default;
 
 
     // Member Functions
 
         //- Read the specieReactionRates data
-        virtual bool read(const dictionary&);
+        virtual bool read(const dictionary& dict);
 
         //- Do nothing
         virtual bool execute();
diff --git a/tutorials/combustion/XiEngineFoam/kivaTest/system/controlDict b/tutorials/combustion/XiEngineFoam/kivaTest/system/controlDict
index c5c5fe4178d..cadd13e8635 100644
--- a/tutorials/combustion/XiEngineFoam/kivaTest/system/controlDict
+++ b/tutorials/combustion/XiEngineFoam/kivaTest/system/controlDict
@@ -75,6 +75,8 @@ functions
             }
         #};
     }
+
+    #include "momentum"
 }
 
 // ************************************************************************* //
diff --git a/tutorials/combustion/XiEngineFoam/kivaTest/system/momentum b/tutorials/combustion/XiEngineFoam/kivaTest/system/momentum
new file mode 100644
index 00000000000..9c9d09135d1
--- /dev/null
+++ b/tutorials/combustion/XiEngineFoam/kivaTest/system/momentum
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+// Calculate momentum fields
+momentum
+{
+    type    momentum;
+    libs    ("libfieldFunctionObjects.so");
+    log     true;
+
+    writeControl    writeTime;
+    // executeInterval 10;
+
+    // writeToFile     true;
+
+    writeMomentum   true;
+    writePosition   true;
+    writeVelocity   true;
+
+    // Cells to select (all/cellSet/cellZone)
+    regionType  all;
+    // name     c0;
+
+    cylindrical false;
+
+    origin  (0 0 0);
+    rotation
+    {
+        type cylindrical;
+        axis (1 0 0);   //< local Z
+    }
+}
+
+
+// ************************************************************************* //
-- 
GitLab