From 8d90b165182c77f7246cb144aa640ca014a5f373 Mon Sep 17 00:00:00 2001
From: Andrew Heather <>
Date: Mon, 23 May 2022 20:25:05 +0100
Subject: [PATCH] ENH: multiFieldValue - extended to operate on general
 function objects

- Previously, the multiFieldValue function object was limited to operate on
  lists of fieldValue function objects.
- Any function objects that generate results can now be used, e.g.

pressureAverage
{
    type    multiFieldValue;
    libs    (fieldFunctionObjects);

    operation   average;

    functions
    {
        inlet
        {
            type            surfaceFieldValue;
            operation       areaAverage;
            regionType      patch;
            name            inlet;
            fields          (p);

            writeFields     no;
            writeToFile     no;
            log             no;
            resultFields    (areaAverage(inlet,p));
        }
        outlet
        {
            type            surfaceFieldValue;
            operation       areaAverage;
            regionType      patch;
            name            outlet;
            fields          (p);

            writeFields     no;
            writeToFile     no;
            log             no;
        }
        average
        {
            type            valueAverage;
            functionObject  testSample1;
            fields          (average(p));

            writeToFile     no;
            log             no;
        }
    }
}

TUT: cavity: add an example for the multiFieldValue function object
---
 src/functionObjects/field/Make/files          |   3 +-
 .../multiFieldValue/multiFieldValue.C         | 208 ++++++++++--------
 .../multiFieldValue/multiFieldValue.H         |  73 +++---
 .../multiFieldValueTemplates.C                |   8 +-
 .../pisoFoam/RAS/cavity/Allclean              |   2 +
 .../pisoFoam/RAS/cavity/Allrun-parallel       |  17 ++
 .../RAS/cavity/system/FOmultiFieldValue       | 129 +++++++++++
 .../pisoFoam/RAS/cavity/system/controlDict    |   3 +-
 8 files changed, 316 insertions(+), 127 deletions(-)
 rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValue.C (56%)
 rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValue.H (77%)
 rename src/functionObjects/field/{fieldValues => }/multiFieldValue/multiFieldValueTemplates.C (94%)
 create mode 100644 tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue

diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files
index 290a84dfe3b..c285367b665 100644
--- a/src/functionObjects/field/Make/files
+++ b/src/functionObjects/field/Make/files
@@ -20,7 +20,6 @@ fieldValues/fieldValue/fieldValue.C
 fieldValues/fieldValue/fieldValueNew.C
 fieldValues/volFieldValue/volFieldValue.C
 fieldValues/surfaceFieldValue/surfaceFieldValue.C
-fieldValues/multiFieldValue/multiFieldValue.C
 
 heatTransferCoeff/heatTransferCoeff.C
 heatTransferCoeff/heatTransferCoeffModels/heatTransferCoeffModel/heatTransferCoeffModel.C
@@ -31,6 +30,8 @@ heatTransferCoeff/heatTransferCoeffModels/ReynoldsAnalogy/ReynoldsAnalogy.C
 
 limitFields/limitFields.C
 
+multiFieldValue/multiFieldValue.C
+
 nearWallFields/nearWallFields.C
 nearWallFields/findCellParticle.C
 nearWallFields/findCellParticleCloud.C
diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C b/src/functionObjects/field/multiFieldValue/multiFieldValue.C
similarity index 56%
rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C
rename to src/functionObjects/field/multiFieldValue/multiFieldValue.C
index 251a9a47da7..45cf5bb8d15 100644
--- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C
+++ b/src/functionObjects/field/multiFieldValue/multiFieldValue.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2021 OpenCFD Ltd.
+    Copyright (C) 2015-2022 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -63,48 +63,36 @@ Foam::functionObjects::fieldValues::multiFieldValue::operationTypeNames_
 
 void Foam::functionObjects::fieldValues::multiFieldValue::writeFileHeader
 (
+    const wordList& foNames,
+    const List<wordList>& entries,
+    const List<wordList>& types,
     Ostream& os
 ) const
 {
-    const wordList& fields0 = functions_[0].fields();
+    const word groupPrefix("Group");
 
-    DynamicList<word> commonFields(fields0.size());
-
-    for (const word& fieldName : fields0)
+    forAll(entries, i)
     {
-        bool common = true;
+        writeCommented(os, groupPrefix + Foam::name(i));
+        os  << nl;
 
-        for (label functioni=1; functioni < functions_.size(); ++functioni)
+        forAll(entries[i], functioni)
         {
-            if (!functions_[functioni].fields().found(fieldName))
-            {
-                common = false;
-                break;
-            }
-        }
-
-        if (common)
-        {
-            commonFields.append(fieldName);
+            writeCommented
+            (
+                os,
+                "  - " + foNames[functioni] + ":" + entries[i][functioni]
+            );
+            os  << nl;
         }
     }
 
-    forAll(functions_, functioni)
-    {
-        writeHeaderValue
-        (
-            os,
-            "Source" + Foam::name(functioni),
-            functions_[functioni].name()
-        );
-    }
-
     writeHeaderValue(os, "Operation", operationTypeNames_[operation_]);
     writeCommented(os, "Time");
 
-    for (const word& fieldName : commonFields)
+    forAll(entries, entryi)
     {
-        os  << tab << fieldName;
+        writeTabbed(os, groupPrefix + Foam::name(entryi));
     }
 
     os  << endl;
@@ -125,10 +113,7 @@ Foam::functionObjects::fieldValues::multiFieldValue::multiFieldValue
     operation_(opSubtract),
     functions_()
 {
-    if (read(dict))
-    {
-        writeFileHeader(file());
-    }
+    read(dict);
 }
 
 
@@ -139,52 +124,73 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::read
     const dictionary& dict
 )
 {
-    if (stateFunctionObject::read(dict) && writeFile::read(dict))
+    if (!stateFunctionObject::read(dict) || !writeFile::read(dict))
     {
-        const dictionary& functionsDict = dict.subDict("functions");
-        functions_.resize(functionsDict.size());
+        return false;
+    }
 
-        if (functions_.empty())
-        {
-            WarningInFunction
-                << "No functions specified"
-                << endl;
-            return false;
-        }
+    operation_ = operationTypeNames_.get("operation", dict);
+
+    const dictionary& functionsDict = dict.subDict("functions");
+    functions_.resize(functionsDict.size());
+
+    if (functions_.empty())
+    {
+        WarningInFunction
+            << "No functions specified"
+            << endl;
+        return false;
+    }
+
+    resultFields_.resize(functions_.size());
 
-        label functioni = 0;
-        for (const entry& dEntry : functionsDict)
+    label functioni = 0;
+    for (const entry& dEntry : functionsDict)
+    {
+        if (!dEntry.isDict())
         {
-            if (!dEntry.isDict())
-            {
-                FatalIOErrorInFunction(dict)
-                    << "Functions must be specified in dictionary format"
-                    << exit(FatalIOError);
-            }
+            FatalIOErrorInFunction(dict)
+                << "Functions must be specified in dictionary format"
+                << exit(FatalIOError);
+        }
 
-            const dictionary& localDict = dEntry.dict();
+        const dictionary& localDict = dEntry.dict();
 
-            functions_.set
+        functions_.set
+        (
+            functioni,
+            functionObject::New
             (
-                functioni,
-                fieldValue::New
-                (
-                    IOobject::scopedName(name(), localDict.dictName()),
-                    time(),
-                    localDict,
-                    false
-                )
-            );
+                IOobject::scopedName(name(), localDict.dictName()),
+                time(),
+                localDict
+            ).ptr()
+        );
 
-            ++functioni;
-        }
+        // Deactivate logging for child function objects
+        //functions_[functioni].log = false;
 
-        operation_ = operationTypeNames_.get("operation", dict);
+        // Get result field names; not specified implies all
+        resultFields_[functioni] =
+            localDict.getOrDefault<wordList>("resultFields", wordList());
 
-        return true;
+        Info<< type() << ' ' << name() << ':' << nl;
+        if (resultFields_[functioni].size())
+        {
+            Info<< "    " << functions_[functioni].name()
+                << " " << resultFields_[functioni];
+        }
+        else
+        {
+            Info<< "    " << functions_[functioni].name()
+                << " - using all available entries";
+        }
+        Info<< nl << endl;
+
+        ++functioni;
     }
 
-    return false;
+    return true;
 }
 
 
@@ -201,19 +207,25 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write()
     wordList entries0;
     label nEntries = -1;
 
-    wordList names(nFunction);
+    wordList foNames(nFunction);
     List<wordList> entries;
     List<wordList> types;
 
     forAll(functions_, functioni)
     {
         auto& f = functions_[functioni];
-        names[functioni] = f.name();
+        foNames[functioni] = f.name();
 
-        // Note: results are not available until the call to write()
+        // Note: replicating functionObjectList execute() and write()
+        // - results may be written on either
+        f.execute();
         f.write();
 
-        const wordList e(objectResultEntries(f.name()));
+        wordList e = resultFields_[functioni];
+        if (e.empty())
+        {
+            e = objectResultEntries(f.name());
+        }
 
         if (functioni == 0)
         {
@@ -237,54 +249,72 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::write()
                 << "Inconsistent number of result entries" << nl
                 << "    " << f0Name << " entries:" << entries0 << nl
                 << "    " << f.name() << " entries:" << e
-                << abort(FatalError);
+                << exit(FatalError);
         }
 
         forAll(e, entryi)
         {
             entries[entryi][functioni] = e[entryi];
             types[entryi][functioni] = objectResultType(f.name(), e[entryi]);
+
+            if (types[entryi][functioni] == word::null)
+            {
+                FatalErrorInFunction
+                    << "Unable to find function object result" << nl
+                    << "    function object   : " << f.name() << nl
+                    << "    result name       : " << e[entryi] << nl
+                    << "    available results : "
+                        << objectResultEntries(f.name())
+                    << exit(FatalError);
+            }
         }
     }
 
+    if (!writtenHeader_)
+    {
+        writeFileHeader(foNames, entries, types, file());
+        writtenHeader_ = true;
+    }
+
     writeCurrentTime(file());
 
-    forAll(entries, entryi)
+    forAll(entries, i)
     {
-        const wordList& entriesi = entries[entryi];
-        const word& t0 = types[entryi][0];
-        const wordList& typesi = types[entryi];
-        forAll(typesi, functioni)
+        const wordList& entryi = entries[i];
+        const word& expectedType = types[i][0];
+        const wordList& foTypes = types[i];
+
+        forAll(foTypes, functioni)
         {
-            const word& t = typesi[functioni];
+            const word& foType = foTypes[functioni];
 
-            if (t != t0)
+            if (foType != expectedType)
             {
                 FatalErrorInFunction
                     << "Inconsistent function result types" << nl
                     << "    " << functions_[0].name()
-                    << " result type:" << t0 << nl
+                    << " result type:" << expectedType << nl
                     << "    " << functions_[functioni].name()
-                    << " result type:" << typesi[functioni]
-                    << abort(FatalError);
+                    << " result type:" << foType
+                    << exit(FatalError);
             }
         }
 
         const bool ok
         (
-            applyOperation<scalar>(t0, names, entriesi)
-         || applyOperation<vector>(t0, names, entriesi)
-         || applyOperation<sphericalTensor>(t0, names, entriesi)
-         || applyOperation<symmTensor>(t0, names, entriesi)
-         || applyOperation<tensor>(t0, names, entriesi)
+            applyOperation<scalar>(expectedType, foNames, entryi)
+         || applyOperation<vector>(expectedType, foNames, entryi)
+         || applyOperation<sphericalTensor>(expectedType, foNames, entryi)
+         || applyOperation<symmTensor>(expectedType, foNames, entryi)
+         || applyOperation<tensor>(expectedType, foNames, entryi)
         );
 
         if (!ok)
         {
             Log << "Operation not applied between functions:" << nl
-                << flatOutput(names, FlatOutput::BareComma{}) << nl
+                << flatOutput(foNames, FlatOutput::BareComma{}) << nl
                 << "with result names:" << nl
-                << flatOutput(entriesi, FlatOutput::BareComma{})
+                << flatOutput(entryi, FlatOutput::BareComma{})
                 << endl;
         }
     }
diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H b/src/functionObjects/field/multiFieldValue/multiFieldValue.H
similarity index 77%
rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H
rename to src/functionObjects/field/multiFieldValue/multiFieldValue.H
index d6b73499eb2..02a939ff125 100644
--- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H
+++ b/src/functionObjects/field/multiFieldValue/multiFieldValue.H
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2021 OpenCFD Ltd.
+    Copyright (C) 2021-2022 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -30,10 +30,9 @@ Group
     grpFieldFunctionObjects
 
 Description
-    Computes a selected operation between multiple \c fieldValue function
-    objects.
+    Computes a selected operation between multiple function objects.
 
-    The operation is applied to all results of each \c fieldValue object.
+    The operation is applied to all results of each object.
 
 Note
     Each object must generate the same number and type of results.
@@ -43,11 +42,9 @@ Usage
     \verbatim
     multiFieldValue1
     {
-        // Mandatory entries (unmodifiable)
-        type    multiFieldValue;
-        libs    (fieldFunctionObjects);
-
-        // Mandatory entries (runtime modifiable)
+        // Mandatory entries
+        type        multiFieldValue;
+        libs        (fieldFunctionObjects);
         operation   average;
 
         // List of fieldValue function objects as dictionaries
@@ -56,10 +53,14 @@ Usage
             region1
             {
                 ...
+                // Optional
+                resultFields        (field1 field2);
             }
             region2
             {
                 ...
+                // Optional
+                resultFields        (field1 field2);
             }
 
             ...
@@ -67,41 +68,41 @@ Usage
             regionN
             {
                 ...
+                // Optional
+                resultFields        (field1 field2);
             }
         }
 
-        // Optional (inherited) entries
+        // Inherited entries
         ...
     }
     \endverbatim
 
     where the entries mean:
     \table
-      Property     | Description                         | Type | Req'd | Dflt
-      type         | Type name: multiFieldValue          | word |  yes  | -
-      libs         | Library name: fieldFunctionObjects  | word |  yes  | -
-      operation    | Operation type to apply to values   | word |  yes  | -
-      functions    | List of fieldValue function objects | dict |  yes  | -
+      Property     | Description                         | Type | Reqd | Deflt
+      type         | Type name: multiFieldValue          | word |  yes | -
+      libs         | Library name: fieldFunctionObjects  | word |  yes | -
+      operation    | Operation type to apply to values   | word |  yes | -
+      functions    | List of function objects            | dict |  yes | -
     \endtable
 
     Options for the \c operation entry:
     \plaintable
-       add           | add
-       subtract      | subtract
-       min           | minimum
-       max           | maximum
-       average       | average
+       sum           | Sum of values
+       add           | Add values (same as sum)
+       subtract      | Subtract values from first entry
+       min           | Minimum value
+       max           | Maximum value
+       average       | Average value
     \endplaintable
 
-    The inherited entries are elaborated in:
-     - \link fieldValue.H \endlink
-
-    Usage by the \c postProcess utility is not available.
+    The \c resultFields entry can be used to set the name of the function object
+    result fields to process. If omitted, all available values are employed.
 
-See also
-    - Foam::functionObject
-    - Foam::functionObjects::fieldValue
-    - ExtendedCodeGuide::functionObjects::field::multiFieldValue
+    The inherited entries are elaborated in:
+      - \link stateFunctionObject.H \endlink
+      - \link writeFile.H \endlink
 
 SourceFiles
     multiFieldValue.C
@@ -114,7 +115,6 @@ SourceFiles
 
 #include "stateFunctionObject.H"
 #include "writeFile.H"
-#include "fieldValue.H"
 #include "Enum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -161,8 +161,11 @@ private:
         //- Operation to apply to values
         operationType operation_;
 
-        //- List of fieldValue function objects
-        PtrList<fieldValue> functions_;
+        //- List of function objects
+        PtrList<functionObject> functions_;
+
+        //- List of result fields per function object
+        List<wordList> resultFields_;
 
 
     // Private Member Functions
@@ -183,7 +186,13 @@ protected:
     // Protected Member Functions
 
         //- Output file header information
-        virtual void writeFileHeader(Ostream& os) const;
+        virtual void writeFileHeader
+        (
+            const wordList& foNames,
+            const List<wordList>& entries,
+            const List<wordList>& types,
+            Ostream& os
+        ) const;
 
 
 public:
diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C b/src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C
similarity index 94%
rename from src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C
rename to src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C
index 714cb1c48b6..5f6c99c084e 100644
--- a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C
+++ b/src/functionObjects/field/multiFieldValue/multiFieldValueTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2021 OpenCFD Ltd.
+    Copyright (C) 2015-2022 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,7 +34,7 @@ template<class Type>
 bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation
 (
     const word& resultType,
-    const wordList& names,
+    const wordList& foNames,
     const wordList& entryNames
 )
 {
@@ -45,10 +45,10 @@ bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation
 
     Type result = Zero;
 
-    Field<Type> values(names.size());
+    Field<Type> values(foNames.size());
     forAll(values, i)
     {
-        values[i] = this->getObjectResult<Type>(names[i], entryNames[i]);
+        values[i] = this->getObjectResult<Type>(foNames[i], entryNames[i]);
     }
 
     const word& opName = operationTypeNames_[operation_];
diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean b/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean
index fb1f3847301..a89ac03ac12 100755
--- a/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean
+++ b/tutorials/incompressible/pisoFoam/RAS/cavity/Allclean
@@ -5,4 +5,6 @@ cd "${0%/*}" || exit                                # Run from this directory
 
 cleanCase0
 
+rm -rf procs.old
+
 #------------------------------------------------------------------------------
diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel b/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel
index f128afc39ba..cbbadfe17df 100755
--- a/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel
+++ b/tutorials/incompressible/pisoFoam/RAS/cavity/Allrun-parallel
@@ -13,4 +13,21 @@ runParallel topoSet
 
 runParallel $(getApplication)
 
+runApplication reconstructPar
+
+
+latestTime=$(foamListTimes -latestTime)
+
+mv -f "$latestTime" "$latestTime".bak
+
+mkdir procs.old
+
+mv -f processor* procs.old
+
+runParallel -s "decompose" redistributePar -decompose -time 9.5
+
+runParallel -s 2 $(getApplication)
+
+runParallel -s "reconstruct" redistributePar -reconstruct -latestTime
+
 #------------------------------------------------------------------------------
diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue
new file mode 100644
index 00000000000..43d98042bfc
--- /dev/null
+++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/FOmultiFieldValue
@@ -0,0 +1,129 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2112                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+sampleEpsilon1
+{
+    type            sets;
+    libs            (sampling);
+    interpolationScheme cellPointFace;
+    setFormat       raw;
+    fields          ( epsilon );
+
+    sets
+    (
+        cloud
+        {
+            type    cloud;
+            axis    xyz;
+            points
+            (
+                (0.0025 0.05 0.005)
+            );
+        }
+    );
+}
+
+
+multiFieldValue_add
+{
+    // Mandatory entries
+    type    multiFieldValue;
+    libs    (fieldFunctionObjects);
+
+    operation   add;
+
+    functions
+    {
+        movingWallEpsilon
+        {
+            type            surfaceFieldValue;
+            operation       areaAverage;
+            regionType      patch;
+            name            movingWall;
+            fields          (epsilon);
+
+            writeFields     no;
+            writeToFile     no;
+            log             no;
+            resultFields    (areaAverage(movingWall,epsilon));
+        }
+        fixedWallsEpsilon
+        {
+            type            surfaceFieldValue;
+            operation       areaAverage;
+            regionType      patch;
+            name            fixedWalls;
+            fields          (epsilon);
+
+            writeFields     no;
+            writeToFile     no;
+            log             yes;
+        }
+        averageEpsilon
+        {
+            type            valueAverage;
+            functionObject  sampleEpsilon1;
+            fields          (average(epsilon));
+            writeToFile     no;
+            log             no;
+        }
+    }
+
+    // Inherited entries
+    writePrecision  10;
+    writeToFile     true;
+    useUserTime     true;
+
+    region          region0;
+    enabled         true;
+    log             true;
+    timeStart       0;
+    timeEnd         1000;
+    executeControl  timeStep;
+    executeInterval 1;
+    writeControl    writeTime;
+    writeInterval   -1;
+}
+
+
+multiFieldValue_sum
+{
+    ${multiFieldValue_add}
+    operation    sum;
+}
+
+
+multiFieldValue_subtract
+{
+    ${multiFieldValue_add}
+    operation    subtract;
+}
+
+
+multiFieldValue_min
+{
+    ${multiFieldValue_add}
+    operation    min;
+}
+
+
+multiFieldValue_max
+{
+    ${multiFieldValue_add}
+    operation    max;
+}
+
+
+multiFieldValue_average
+{
+    ${multiFieldValue_add}
+    operation    average;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict b/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict
index 44799398a52..03b72d8ef56 100644
--- a/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict
+++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/controlDict
@@ -16,7 +16,7 @@ FoamFile
 
 application     pisoFoam;
 
-startFrom       startTime;
+startFrom       latestTime;
 
 startTime       0;
 
@@ -68,6 +68,7 @@ functions
     #include "FOlog"
     #include "FOmag"
     #include "FOmagSqr"
+    #include "FOmultiFieldValue"
     #include "FOmultiply"
     #include "FOmomentum"
     #include "FOnearWallFields"
-- 
GitLab