diff --git a/etc/caseDicts/postProcessing/pressure/pressureDifference.cfg b/etc/caseDicts/postProcessing/pressure/pressureDifference.cfg
index b601f5b97b6ef0d2c32602bed17cfc6cb83432c4..b8f8e057c52750a3d8dbe19dbf1897ca3ddf89e3 100644
--- a/etc/caseDicts/postProcessing/pressure/pressureDifference.cfg
+++ b/etc/caseDicts/postProcessing/pressure/pressureDifference.cfg
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 \*---------------------------------------------------------------------------*/
 
-type            fieldValueDelta;
+type            multiFieldValue;
 libs            ("libfieldFunctionObjects.so");
 
 operation       subtract;
@@ -15,17 +15,20 @@ writeControl    timeStep;
 writeInterval   1;
 log             false;
 
-region1
+functions
 {
-    #includeEtc "caseDicts/postProcessing/surfaceFieldValue/surfaceRegion.cfg"
-    operation       areaAverage;
-    fields          (p);
-}
-region2
-{
-    #includeEtc "caseDicts/postProcessing/surfaceFieldValue/surfaceRegion.cfg"
-    operation       areaAverage;
-    fields          (p);
+    region1
+    {
+        #includeEtc "caseDicts/postProcessing/surfaceFieldValue/surfaceRegion.cfg"
+        operation       areaAverage;
+        fields          (p);
+    }
+    region2
+    {
+        #includeEtc "caseDicts/postProcessing/surfaceFieldValue/surfaceRegion.cfg"
+        operation       areaAverage;
+        fields          (p);
+    }
 }
 
 // ************************************************************************* //
diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files
index 1ca2168217c384887478b799111d13973fa2f704..ddcb030299f769bc4f80739a4c0da4e4551bfdc6 100644
--- a/src/functionObjects/field/Make/files
+++ b/src/functionObjects/field/Make/files
@@ -16,9 +16,9 @@ fieldMinMax/fieldMinMax.C
 
 fieldValues/fieldValue/fieldValue.C
 fieldValues/fieldValue/fieldValueNew.C
-fieldValues/fieldValueDelta/fieldValueDelta.C
 fieldValues/volFieldValue/volFieldValue.C
 fieldValues/surfaceFieldValue/surfaceFieldValue.C
+fieldValues/multiFieldValue/multiFieldValue.C
 
 heatTransferCoeff/heatTransferCoeff.C
 heatTransferCoeff/heatTransferCoeffModels/heatTransferCoeffModel/heatTransferCoeffModel.C
diff --git a/src/functionObjects/field/fieldValues/fieldValue/fieldValue.C b/src/functionObjects/field/fieldValues/fieldValue/fieldValue.C
index f981f090d00960afae22ae097d9125d454d21fb5..21be1ff6cd992bc01438aff961a30e9c270c7fec 100644
--- a/src/functionObjects/field/fieldValues/fieldValue/fieldValue.C
+++ b/src/functionObjects/field/fieldValues/fieldValue/fieldValue.C
@@ -37,7 +37,7 @@ namespace Foam
 namespace functionObjects
 {
     defineTypeNameAndDebug(fieldValue, 0);
-    defineRunTimeSelectionTable(fieldValue, dictionary);
+    defineRunTimeSelectionTable(fieldValue, runTime);
 }
 }
 
@@ -55,7 +55,7 @@ Foam::functionObjects::fieldValue::fieldValue
     fvMeshFunctionObject(name, runTime, dict),
     writeFile(obr_, name, valueType, dict),
     writeFields_(false),
-    regionName_(word::null),
+    regionName_(),
     scaleFactor_(1.0),
     dict_(dict),
     fields_()
@@ -75,7 +75,7 @@ Foam::functionObjects::fieldValue::fieldValue
     fvMeshFunctionObject(name, obr, dict),
     writeFile(obr_, name, valueType, dict),
     writeFields_(false),
-    regionName_(word::null),
+    regionName_(),
     scaleFactor_(1.0),
     dict_(dict),
     fields_()
@@ -88,19 +88,21 @@ Foam::functionObjects::fieldValue::fieldValue
 
 bool Foam::functionObjects::fieldValue::read(const dictionary& dict)
 {
-    if (dict != dict_)
+    if (fvMeshFunctionObject::read(dict) && writeFile::read(dict))
     {
-        dict_ = dict;
-    }
+        if (dict != dict_)
+        {
+            dict_ = dict;
+        }
 
-    fvMeshFunctionObject::read(dict);
-    writeFile::read(dict);
+        dict.readEntry("writeFields", writeFields_);
+        scaleFactor_ = dict.getOrDefault<scalar>("scaleFactor", 1.0);
+        dict.readEntry("fields", fields_);
 
-    dict.readEntry("writeFields", writeFields_);
-    scaleFactor_ = dict.getOrDefault<scalar>("scaleFactor", 1.0);
-    dict.readEntry("fields", fields_);
+        return true;
+    }
 
-    return true;
+    return false;
 }
 
 
diff --git a/src/functionObjects/field/fieldValues/fieldValue/fieldValue.H b/src/functionObjects/field/fieldValues/fieldValue/fieldValue.H
index 5e008f622894dba2ec760ebd539a9e6c7caa5f03..a182e300224a71dcb34b6956c6593b3346a60d1e 100644
--- a/src/functionObjects/field/fieldValues/fieldValue/fieldValue.H
+++ b/src/functionObjects/field/fieldValues/fieldValue/fieldValue.H
@@ -98,7 +98,6 @@ class fieldValue
     public fvMeshFunctionObject,
     public writeFile
 {
-
 protected:
 
     // Protected Data
@@ -141,16 +140,15 @@ public:
         (
             autoPtr,
             fieldValue,
-            dictionary,
+            runTime,
             (
                 const word& name,
-                const objectRegistry& obr,
+                const Time& runTime,
                 const dictionary& dict
             ),
-            (name, obr, dict)
+            (name, runTime, dict)
         );
 
-
     // Constructors
 
         //- Construct from Time and dictionary
@@ -175,7 +173,7 @@ public:
         static autoPtr<fieldValue> New
         (
             const word& name,
-            const objectRegistry& obr,
+            const Time& runTime,
             const dictionary& dict,
             const bool output = true
         );
diff --git a/src/functionObjects/field/fieldValues/fieldValue/fieldValueNew.C b/src/functionObjects/field/fieldValues/fieldValue/fieldValueNew.C
index 39ebdca2539877b956cc091c9def99afcd4f784c..0868e0b86fe28f28ad418623763db0aac1c244dc 100644
--- a/src/functionObjects/field/fieldValues/fieldValue/fieldValueNew.C
+++ b/src/functionObjects/field/fieldValues/fieldValue/fieldValueNew.C
@@ -34,7 +34,7 @@ Foam::autoPtr<Foam::functionObjects::fieldValue>
 Foam::functionObjects::fieldValue::New
 (
     const word& name,
-    const objectRegistry& obr,
+    const Time& runTime,
     const dictionary& dict,
     const bool output
 )
@@ -46,7 +46,7 @@ Foam::functionObjects::fieldValue::New
         Info<< "Selecting " << typeName << ' ' << modelType << endl;
     }
 
-    auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
+    auto cstrIter = runTimeConstructorTablePtr_->cfind(modelType);
 
     if (!cstrIter.found())
     {
@@ -55,12 +55,13 @@ Foam::functionObjects::fieldValue::New
             dict,
             typeName,
             modelType,
-            *dictionaryConstructorTablePtr_
+            *runTimeConstructorTablePtr_
         ) << exit(FatalIOError);
     }
 
-    return autoPtr<fieldValue>(cstrIter()(name, obr, dict));
+    return autoPtr<fieldValue>(cstrIter()(name, runTime, dict));
 }
 
 
+
 // ************************************************************************* //
diff --git a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.C b/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.C
deleted file mode 100644
index 09f4f91833a5cbc207f075a9e13177647590b50d..0000000000000000000000000000000000000000
--- a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.C
+++ /dev/null
@@ -1,227 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | www.openfoam.com
-     \\/     M anipulation  |
--------------------------------------------------------------------------------
-    Copyright (C) 2012-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2020 OpenCFD Ltd.
--------------------------------------------------------------------------------
-License
-    This file is part of OpenFOAM.
-
-    OpenFOAM is free software: you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "fieldValueDelta.H"
-#include "addToRunTimeSelectionTable.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace functionObjects
-{
-namespace fieldValues
-{
-    defineTypeNameAndDebug(fieldValueDelta, 0);
-    addToRunTimeSelectionTable(functionObject, fieldValueDelta, dictionary);
-}
-}
-}
-
-
-const Foam::Enum
-<
-    Foam::functionObjects::fieldValues::fieldValueDelta::operationType
->
-Foam::functionObjects::fieldValues::fieldValueDelta::operationTypeNames_
-({
-    { operationType::opAdd, "add" },
-    { operationType::opSubtract, "subtract" },
-    { operationType::opMin, "min" },
-    { operationType::opMax, "max" },
-    { operationType::opAverage, "average" },
-});
-
-
-// * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
-
-void Foam::functionObjects::fieldValues::fieldValueDelta::writeFileHeader
-(
-    Ostream& os
-) const
-{
-    const wordList& fields1 = region1Ptr_->fields();
-    const wordList& fields2 = region2Ptr_->fields();
-
-    DynamicList<word> commonFields(fields1.size());
-    forAll(fields1, fieldi)
-    {
-        label index = fields2.find(fields1[fieldi]);
-        if (index != -1)
-        {
-            commonFields.append(fields1[fieldi]);
-        }
-    }
-
-    writeHeaderValue(os, "Source1", region1Ptr_->name());
-    writeHeaderValue(os, "Source2", region2Ptr_->name());
-    writeHeaderValue(os, "Operation", operationTypeNames_[operation_]);
-    writeCommented(os, "Time");
-
-    forAll(commonFields, i)
-    {
-        os  << tab << commonFields[i];
-    }
-
-    os  << endl;
-}
-
-
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-Foam::functionObjects::fieldValues::fieldValueDelta::fieldValueDelta
-(
-    const word& name,
-    const Time& runTime,
-    const dictionary& dict
-)
-:
-    fvMeshFunctionObject(name, runTime, dict),
-    writeFile(obr_, name, typeName, dict),
-    operation_(opSubtract),
-    region1Ptr_(nullptr),
-    region2Ptr_(nullptr)
-{
-    read(dict);
-    writeFileHeader(file());
-}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::functionObjects::fieldValues::fieldValueDelta::read
-(
-    const dictionary& dict
-)
-{
-    fvMeshFunctionObject::read(dict);
-    writeFile::read(dict);
-
-    region1Ptr_.reset
-    (
-        fieldValue::New
-        (
-            name() + ".region1",
-            obr_,
-            dict.subDict("region1"),
-            false
-        ).ptr()
-    );
-    region2Ptr_.reset
-    (
-        fieldValue::New
-        (
-            name() + ".region2",
-            obr_,
-            dict.subDict("region2"),
-            false
-        ).ptr()
-    );
-
-    operation_ = operationTypeNames_.get("operation", dict);
-
-    return true;
-}
-
-
-bool Foam::functionObjects::fieldValues::fieldValueDelta::write()
-{
-    region1Ptr_->write();
-    region2Ptr_->write();
-
-    writeCurrentTime(file());
-
-    Log << type() << " " << name() << " write:" << endl;
-
-    const word& name1 = region1Ptr_->name();
-    const word& name2 = region2Ptr_->name();
-
-    const wordList entries1 = objectResultEntries(name1);
-    const wordList entries2 = objectResultEntries(name2);
-
-    if (entries1.size() != entries2.size())
-    {
-        FatalErrorInFunction
-            << name() << ": objects must generate the same number of results"
-            << nl
-            << "    " << name1 << " objects: " << entries1 << nl
-            << "    " << name2 << " objects: " << entries2 << nl
-            << exit(FatalError);
-    }
-
-    forAll(entries1, i)
-    {
-        const word& entry1(entries1[i]);
-        const word& entry2(entries2[i]);
-        const word type1 = objectResultType(name1, entry1);
-        const word type2 = objectResultType(name2, entry2);
-
-        if (type1 != type2)
-        {
-            FatalErrorInFunction
-                << name()
-                << ": input values for operation must be of the same type"
-                << nl
-                << "    " << entry1 << ": " << type1 << nl
-                << "    " << entry2 << ": " << type2 << nl
-                << exit(FatalError);
-        }
-
-        bool found = false;
-
-        applyOperation<scalar>(type1, name1, name2, entry1, entry2, found);
-        applyOperation<vector>(type1, name1, name2, entry1, entry2, found);
-        applyOperation<sphericalTensor>
-            (type1, name1, name2, entry1, entry2, found);
-        applyOperation<symmTensor>(type1, name1, name2, entry1, entry2, found);
-        applyOperation<tensor>(type1, name1, name2, entry1, entry2, found);
-
-        if (!found)
-        {
-            Log << "Operation between "
-                << name1 << " with result " << entry1 << " and "
-                << name2 << " with result " << entry2 << " not applied"
-                << endl;
-        }
-    }
-
-    Log << (entries1.empty() ? "    none" : "") << endl;
-
-    file()<< endl;
-
-    return true;
-}
-
-
-bool Foam::functionObjects::fieldValues::fieldValueDelta::execute()
-{
-    return true;
-}
-
-
-// ************************************************************************* //
diff --git a/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C
new file mode 100644
index 0000000000000000000000000000000000000000..251a9a47da7c226dbdf14d3040e087a9a7a57a93
--- /dev/null
+++ b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.C
@@ -0,0 +1,306 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2012-2016 OpenFOAM Foundation
+    Copyright (C) 2015-2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "multiFieldValue.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+namespace fieldValues
+{
+    defineTypeNameAndDebug(multiFieldValue, 0);
+    addToRunTimeSelectionTable(functionObject, multiFieldValue, dictionary);
+}
+}
+}
+
+
+const Foam::Enum
+<
+    Foam::functionObjects::fieldValues::multiFieldValue::operationType
+>
+Foam::functionObjects::fieldValues::multiFieldValue::operationTypeNames_
+({
+    { operationType::opSum, "sum" },
+    { operationType::opAdd, "add" },
+    { operationType::opSubtract, "subtract" },
+    { operationType::opMin, "min" },
+    { operationType::opMax, "max" },
+    { operationType::opAverage, "average" },
+});
+
+
+// * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
+
+void Foam::functionObjects::fieldValues::multiFieldValue::writeFileHeader
+(
+    Ostream& os
+) const
+{
+    const wordList& fields0 = functions_[0].fields();
+
+    DynamicList<word> commonFields(fields0.size());
+
+    for (const word& fieldName : fields0)
+    {
+        bool common = true;
+
+        for (label functioni=1; functioni < functions_.size(); ++functioni)
+        {
+            if (!functions_[functioni].fields().found(fieldName))
+            {
+                common = false;
+                break;
+            }
+        }
+
+        if (common)
+        {
+            commonFields.append(fieldName);
+        }
+    }
+
+    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)
+    {
+        os  << tab << fieldName;
+    }
+
+    os  << endl;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::functionObjects::fieldValues::multiFieldValue::multiFieldValue
+(
+    const word& name,
+    const Time& runTime,
+    const dictionary& dict
+)
+:
+    stateFunctionObject(name, runTime),
+    writeFile(runTime, name, typeName, dict),
+    operation_(opSubtract),
+    functions_()
+{
+    if (read(dict))
+    {
+        writeFileHeader(file());
+    }
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::functionObjects::fieldValues::multiFieldValue::read
+(
+    const dictionary& dict
+)
+{
+    if (stateFunctionObject::read(dict) && writeFile::read(dict))
+    {
+        const dictionary& functionsDict = dict.subDict("functions");
+        functions_.resize(functionsDict.size());
+
+        if (functions_.empty())
+        {
+            WarningInFunction
+                << "No functions specified"
+                << endl;
+            return false;
+        }
+
+        label functioni = 0;
+        for (const entry& dEntry : functionsDict)
+        {
+            if (!dEntry.isDict())
+            {
+                FatalIOErrorInFunction(dict)
+                    << "Functions must be specified in dictionary format"
+                    << exit(FatalIOError);
+            }
+
+            const dictionary& localDict = dEntry.dict();
+
+            functions_.set
+            (
+                functioni,
+                fieldValue::New
+                (
+                    IOobject::scopedName(name(), localDict.dictName()),
+                    time(),
+                    localDict,
+                    false
+                )
+            );
+
+            ++functioni;
+        }
+
+        operation_ = operationTypeNames_.get("operation", dict);
+
+        return true;
+    }
+
+    return false;
+}
+
+
+bool Foam::functionObjects::fieldValues::multiFieldValue::write()
+{
+    if (functions_.empty())
+    {
+        return false;
+    }
+
+    Log << type() << " " << name() << " write:" << endl;
+
+    const label nFunction = functions_.size();
+    wordList entries0;
+    label nEntries = -1;
+
+    wordList names(nFunction);
+    List<wordList> entries;
+    List<wordList> types;
+
+    forAll(functions_, functioni)
+    {
+        auto& f = functions_[functioni];
+        names[functioni] = f.name();
+
+        // Note: results are not available until the call to write()
+        f.write();
+
+        const wordList e(objectResultEntries(f.name()));
+
+        if (functioni == 0)
+        {
+            entries0 = e;
+            nEntries = e.size();
+            entries.resize(nEntries);
+            types.resize(nEntries);
+
+            forAll(entries, entryi)
+            {
+                entries[entryi].resize(nFunction);
+                types[entryi].resize(nFunction);
+            }
+        }
+
+        if (e.size() != nEntries)
+        {
+            const word& f0Name = functions_[0].name();
+
+            FatalErrorInFunction
+                << "Inconsistent number of result entries" << nl
+                << "    " << f0Name << " entries:" << entries0 << nl
+                << "    " << f.name() << " entries:" << e
+                << abort(FatalError);
+        }
+
+        forAll(e, entryi)
+        {
+            entries[entryi][functioni] = e[entryi];
+            types[entryi][functioni] = objectResultType(f.name(), e[entryi]);
+        }
+    }
+
+    writeCurrentTime(file());
+
+    forAll(entries, entryi)
+    {
+        const wordList& entriesi = entries[entryi];
+        const word& t0 = types[entryi][0];
+        const wordList& typesi = types[entryi];
+        forAll(typesi, functioni)
+        {
+            const word& t = typesi[functioni];
+
+            if (t != t0)
+            {
+                FatalErrorInFunction
+                    << "Inconsistent function result types" << nl
+                    << "    " << functions_[0].name()
+                    << " result type:" << t0 << nl
+                    << "    " << functions_[functioni].name()
+                    << " result type:" << typesi[functioni]
+                    << abort(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)
+        );
+
+        if (!ok)
+        {
+            Log << "Operation not applied between functions:" << nl
+                << flatOutput(names, FlatOutput::BareComma{}) << nl
+                << "with result names:" << nl
+                << flatOutput(entriesi, FlatOutput::BareComma{})
+                << endl;
+        }
+    }
+
+    Log << (nEntries == 0 ? "    none" : "") << endl;
+
+    file()<< endl;
+
+    return true;
+}
+
+
+bool Foam::functionObjects::fieldValues::multiFieldValue::execute()
+{
+    return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.H b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H
similarity index 63%
rename from src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.H
rename to src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H
index 8f6eea9cb988a96136abc47de9140ee569f7472f..d6b73499eb20c136fe34346e2b19e6e29982f45a 100644
--- a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDelta.H
+++ b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValue.H
@@ -5,8 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2012-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2020 OpenCFD Ltd.
+    Copyright (C) 2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,35 +24,50 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::functionObjects::fieldValues::fieldValueDelta
+    Foam::functionObjects::fieldValues::multiFieldValue
 
 Group
     grpFieldFunctionObjects
 
 Description
-    Computes a selected operation between two \c fieldValue function objects.
+    Computes a selected operation between multiple \c fieldValue function
+    objects.
 
     The operation is applied to all results of each \c fieldValue object.
-    Accordingly, each object must generate the same number and type of results.
+
+Note
+    Each object must generate the same number and type of results.
 
 Usage
     Minimal example by using \c system/controlDict.functions:
     \verbatim
-    fieldValueDelta1
+    multiFieldValue1
     {
         // Mandatory entries (unmodifiable)
-        type            fieldValueDelta;
-        libs            (fieldFunctionObjects);
+        type    multiFieldValue;
+        libs    (fieldFunctionObjects);
 
         // Mandatory entries (runtime modifiable)
-        operation       subtract;
-        region1
-        {
-            ...
-        }
-        region2
+        operation   average;
+
+        // List of fieldValue function objects as dictionaries
+        functions
         {
+            region1
+            {
+                ...
+            }
+            region2
+            {
+                ...
+            }
+
             ...
+
+            regionN
+            {
+                ...
+            }
         }
 
         // Optional (inherited) entries
@@ -63,12 +77,11 @@ Usage
 
     where the entries mean:
     \table
-      Property     | Description                        | Type | Req'd | Dflt
-      type         | Type name: fieldValueDelta         | word |  yes  | -
-      libs         | Library name: fieldFunctionObjects | word |  yes  | -
-      operation    | Operation type to apply to values  | word |  yes  | -
-      region1      | Region1 properties                 | dict |  yes  | -
-      region2      | Region2 properties                 | dict |  yes  | -
+      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  | -
     \endtable
 
     Options for the \c operation entry:
@@ -88,16 +101,16 @@ Usage
 See also
     - Foam::functionObject
     - Foam::functionObjects::fieldValue
-    - ExtendedCodeGuide::functionObjects::field::fieldValueDelta
+    - ExtendedCodeGuide::functionObjects::field::multiFieldValue
 
 SourceFiles
-    fieldValueDelta.C
-    fieldValueDeltaTemplates.C
+    multiFieldValue.C
+    multiFieldValueTemplates.C
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef functionObjects_fieldValueDelta_H
-#define functionObjects_fieldValueDelta_H
+#ifndef functionObjects_multiFieldValue_H
+#define functionObjects_multiFieldValue_H
 
 #include "stateFunctionObject.H"
 #include "writeFile.H"
@@ -114,23 +127,27 @@ namespace fieldValues
 {
 
 /*---------------------------------------------------------------------------*\
-                       Class fieldValueDelta Declaration
+                       Class multiFieldValue Declaration
 \*---------------------------------------------------------------------------*/
 
-class fieldValueDelta
+class multiFieldValue
 :
-    public fvMeshFunctionObject,
-    public writeFile
+    public functionObjects::stateFunctionObject,
+    public functionObjects::writeFile
 {
 public:
+
+    // Public Data Types
+
         //- Operation type enumeration
         enum operationType
         {
-            opAdd,              //!< Add
-            opSubtract,         //!< Subtract
-            opMin,              //!< Minimum
-            opMax,              //!< Maximum
-            opAverage           //!< Average
+            opSum,              //!< Sum of values
+            opAdd,              //!< Add values (same as sum)
+            opSubtract,         //!< Subtract values from first entry
+            opMin,              //!< Minimum value
+            opMax,              //!< Maximum value
+            opAverage           //!< Average value
         };
 
         //- Operation type names
@@ -144,25 +161,20 @@ private:
         //- Operation to apply to values
         operationType operation_;
 
-        //- Field value region object 1
-        autoPtr<fieldValue> region1Ptr_;
-
-        //- Field value region object 2
-        autoPtr<fieldValue> region2Ptr_;
+        //- List of fieldValue function objects
+        PtrList<fieldValue> functions_;
 
 
     // Private Member Functions
 
-        //- Templated function to apply the operation
+        //- Templated function to apply the operation.
+        //  \return true if Type and resultType are correct
         template<class Type>
-        void applyOperation
+        bool applyOperation
         (
             const word& resultType,
-            const word& name1,
-            const word& name2,
-            const word& entryName1,
-            const word& entryName2,
-            bool& found
+            const wordList& names,
+            const wordList& entryNames
         );
 
 
@@ -177,13 +189,13 @@ protected:
 public:
 
     //- Run-time type information
-    TypeName("fieldValueDelta");
+    TypeName("multiFieldValue");
 
 
     // Constructors
 
         //- Construct from Time and dictionary
-        fieldValueDelta
+        multiFieldValue
         (
             const word& name,
             const Time& runTime,
@@ -191,20 +203,20 @@ public:
         );
 
         //- No copy construct
-        fieldValueDelta(const fieldValueDelta&) = delete;
+        multiFieldValue(const multiFieldValue&) = delete;
 
         //- No copy assignment
-        void operator=(const fieldValueDelta&) = delete;
+        void operator=(const multiFieldValue&) = delete;
 
 
     //- Destructor
-    virtual ~fieldValueDelta() = default;
+    virtual ~multiFieldValue() = default;
 
 
     // Public Member Functions
 
         //- Read from dictionary
-        virtual bool read(const dictionary&);
+        virtual bool read(const dictionary& dict);
 
         //- Do nothing
         virtual bool execute();
@@ -223,7 +235,7 @@ public:
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #ifdef NoRepository
-    #include "fieldValueDeltaTemplates.C"
+    #include "multiFieldValueTemplates.C"
 #endif
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDeltaTemplates.C b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C
similarity index 74%
rename from src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDeltaTemplates.C
rename to src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C
index 3ef57feddb124b02e2a30f1cb4b3caf3bf7ca91a..714cb1c48b642ce818e45218690d3e9d2ba9e28a 100644
--- a/src/functionObjects/field/fieldValues/fieldValueDelta/fieldValueDeltaTemplates.C
+++ b/src/functionObjects/field/fieldValues/multiFieldValue/multiFieldValueTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2016 OpenCFD Ltd.
+    Copyright (C) 2015-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,56 +26,63 @@ License
 
 \*---------------------------------------------------------------------------*/
 
+#include "FlatOutput.H"
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-void Foam::functionObjects::fieldValues::fieldValueDelta::applyOperation
+bool Foam::functionObjects::fieldValues::multiFieldValue::applyOperation
 (
     const word& resultType,
-    const word& name1,
-    const word& name2,
-    const word& entryName1,
-    const word& entryName2,
-    bool& found
+    const wordList& names,
+    const wordList& entryNames
 )
 {
     if (pTraits<Type>::typeName != resultType)
     {
-        return;
+        return false;
     }
 
     Type result = Zero;
 
-    Type value1 = this->getObjectResult<Type>(name1, entryName1);
-    Type value2 = this->getObjectResult<Type>(name2, entryName2);
+    Field<Type> values(names.size());
+    forAll(values, i)
+    {
+        values[i] = this->getObjectResult<Type>(names[i], entryNames[i]);
+    }
 
     const word& opName = operationTypeNames_[operation_];
 
     switch (operation_)
     {
+        case opSum:
         case opAdd:
         {
-            result = value1 + value2;
+            result = sum(values);
             break;
         }
         case opSubtract:
         {
-            result = value1 - value2;
+            result = values[0];
+            for (label i = 1; i < values.size(); ++i)
+            {
+                result -= values[i];
+            }
             break;
         }
         case opMin:
         {
-            result = min(value1, value2);
+            result = min(values);
             break;
         }
         case opMax:
         {
-            result = max(value1, value2);
+            result = max(values);
             break;
         }
         case opAverage:
         {
-            result = 0.5*(value1 + value2);
+            result = average(values);
             break;
         }
         default:
@@ -87,8 +94,9 @@ void Foam::functionObjects::fieldValues::fieldValueDelta::applyOperation
         }
     }
 
-    const word resultName(opName + '(' + entryName1 + ',' + entryName2 + ')');
-
+    OStringStream os;
+    os << opName << flatOutput(entryNames, FlatOutput::ParenComma{});
+    const word resultName(os.str());
     Log << "    " << resultName << " = " << result << endl;
 
     this->file()<< tab << result;
@@ -96,7 +104,7 @@ void Foam::functionObjects::fieldValues::fieldValueDelta::applyOperation
     // Write state/results information
     this->setResult(resultName, result);
 
-    found = true;
+    return true;
 }
 
 
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
index 64713a635ab82ea0d71e8328073eae60104f1d3f..4d9ff3ab05553466f88e7f2d738581f66cf66773 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
@@ -45,7 +45,7 @@ namespace functionObjects
 namespace fieldValues
 {
     defineTypeNameAndDebug(surfaceFieldValue, 0);
-    addToRunTimeSelectionTable(fieldValue, surfaceFieldValue, dictionary);
+    addToRunTimeSelectionTable(fieldValue, surfaceFieldValue, runTime);
     addToRunTimeSelectionTable(functionObject, surfaceFieldValue, dictionary);
 }
 }
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
index f18041e68a9766ba3b274d4394f1ae9c02e7ef1f..9f355a25bb46abbccca09a26bc65a016566c79cf 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2017-2020 OpenCFD Ltd.
+    Copyright (C) 2017-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -40,7 +40,7 @@ namespace functionObjects
 namespace fieldValues
 {
     defineTypeNameAndDebug(volFieldValue, 0);
-    addToRunTimeSelectionTable(fieldValue, volFieldValue, dictionary);
+    addToRunTimeSelectionTable(fieldValue, volFieldValue, runTime);
     addToRunTimeSelectionTable(functionObject, volFieldValue, dictionary);
 }
 }
diff --git a/tutorials/lagrangian/reactingParcelFoam/filter/system/controlDict b/tutorials/lagrangian/reactingParcelFoam/filter/system/controlDict
index 735b83ad32f736ebd730187f1b1cbdba0bc58cac..c196a53845cab42872d6e054221fb0d190cd3d88 100644
--- a/tutorials/lagrangian/reactingParcelFoam/filter/system/controlDict
+++ b/tutorials/lagrangian/reactingParcelFoam/filter/system/controlDict
@@ -1,7 +1,7 @@
 /*--------------------------------*- C++ -*----------------------------------*\
 | =========                 |                                                 |
 | \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
-|  \\    /   O peration     | Version:  v2012                                 |
+|  \\    /   O peration     | Version:  v2106                                 |
 |   \\  /    A nd           | Website:  www.openfoam.com                      |
 |    \\/     M anipulation  |                                                 |
 \*---------------------------------------------------------------------------*/
@@ -55,6 +55,7 @@ functions
     #include "dataCloud"
     #include "vtkCloud"
     #include "vtkWrite"
+    #include "pressureDifference"
 }
 
 
diff --git a/tutorials/lagrangian/reactingParcelFoam/filter/system/pressureDifference b/tutorials/lagrangian/reactingParcelFoam/filter/system/pressureDifference
new file mode 100644
index 0000000000000000000000000000000000000000..64332980a9b7d374282ccdd3808798650663e240
--- /dev/null
+++ b/tutorials/lagrangian/reactingParcelFoam/filter/system/pressureDifference
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+
+pressureDifference
+{
+    type    multiFieldValue;
+    libs    (fieldFunctionObjects);
+
+    operation   subtract;
+
+    functions
+    {
+        inlet
+        {
+            type            surfaceFieldValue;
+            operation       areaAverage;
+            regionType      patch;
+            name            inlet;
+            fields          (p);
+
+            writeFields     no;
+            writeToFile     no;
+            log             no;
+        }
+        outlet
+        {
+            type            surfaceFieldValue;
+            operation       areaAverage;
+            regionType      patch;
+            name            outlet;
+            fields          (p);
+
+            writeFields     no;
+            writeToFile     no;
+            log             no;
+        }
+    }
+}
+
+
+// ************************************************************************* //