diff --git a/src/functionObjects/field/ddt2/ddt2.C b/src/functionObjects/field/ddt2/ddt2.C
index c0e0ceeb761c4c6298c2c3f17cd2f2c5ce8f0dc2..d1f39168d2449d38a4f099147efa7f5b84fb119c 100644
--- a/src/functionObjects/field/ddt2/ddt2.C
+++ b/src/functionObjects/field/ddt2/ddt2.C
@@ -121,51 +121,6 @@ int Foam::functionObjects::ddt2::process(const word& fieldName)
 }
 
 
-void Foam::functionObjects::ddt2::process()
-{
-    results_.clear();
-
-    wordHashSet candidates = subsetStrings(selectFields_, mesh_.names());
-    DynamicList<word> missing(selectFields_.size());
-    DynamicList<word> ignored(selectFields_.size());
-
-    // check exact matches first
-    forAll(selectFields_, i)
-    {
-        const wordRe& select = selectFields_[i];
-        if (!select.isPattern())
-        {
-            const word& fieldName = static_cast<const word&>(select);
-
-            if (!candidates.erase(fieldName))
-            {
-                missing.append(fieldName);
-            }
-            else if (process(fieldName) < 1)
-            {
-                ignored.append(fieldName);
-            }
-        }
-    }
-
-    forAllConstIter(wordHashSet, candidates, iter)
-    {
-        process(iter.key());
-    }
-
-    if (missing.size())
-    {
-        WarningInFunction
-            << "Missing field " << missing << endl;
-    }
-    if (ignored.size())
-    {
-        WarningInFunction
-            << "Unprocessed field " << ignored << endl;
-    }
-}
-
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::functionObjects::ddt2::ddt2
@@ -204,6 +159,8 @@ bool Foam::functionObjects::ddt2::read(const dictionary& dict)
         return false;
     }
 
+    fvMeshFunctionObject::read(dict);
+
     dict.lookup("fields") >> selectFields_;
     uniqWords(selectFields_);
 
@@ -236,7 +193,45 @@ bool Foam::functionObjects::ddt2::read(const dictionary& dict)
 bool Foam::functionObjects::ddt2::execute()
 {
     results_.clear();
-    process();
+
+    wordHashSet candidates = subsetStrings(selectFields_, mesh_.names());
+    DynamicList<word> missing(selectFields_.size());
+    DynamicList<word> ignored(selectFields_.size());
+
+    // check exact matches first
+    forAll(selectFields_, i)
+    {
+        const wordRe& select = selectFields_[i];
+        if (!select.isPattern())
+        {
+            const word& fieldName = static_cast<const word&>(select);
+
+            if (!candidates.erase(fieldName))
+            {
+                missing.append(fieldName);
+            }
+            else if (process(fieldName) < 1)
+            {
+                ignored.append(fieldName);
+            }
+        }
+    }
+
+    forAllConstIter(wordHashSet, candidates, iter)
+    {
+        process(iter.key());
+    }
+
+    if (missing.size())
+    {
+        WarningInFunction
+            << "Missing field " << missing << endl;
+    }
+    if (ignored.size())
+    {
+        WarningInFunction
+            << "Unprocessed field " << ignored << endl;
+    }
 
     return true;
 }
@@ -244,9 +239,13 @@ bool Foam::functionObjects::ddt2::execute()
 
 bool Foam::functionObjects::ddt2::write()
 {
+    if (results_.size())
+    {
+        Log << type() << ' ' << name() << " write:" << endl;
+    }
+
     // Consistent output order
     const wordList outputList = results_.sortedToc();
-
     forAll(outputList, i)
     {
         const word& fieldName = outputList[i];
@@ -255,8 +254,7 @@ bool Foam::functionObjects::ddt2::write()
         {
             const regIOobject& io = lookupObject<regIOobject>(fieldName);
 
-            Log << type() << " " << name()
-                << " write: writing field " << fieldName << endl;
+            Log << "    " << fieldName << endl;
 
             io.write();
         }
diff --git a/src/functionObjects/field/ddt2/ddt2.H b/src/functionObjects/field/ddt2/ddt2.H
index e713ecb8a431cd04bf8cbb08f589b1e17adb2f94..0f4b69bea34188ad80e1f9383af379eb745c572a 100644
--- a/src/functionObjects/field/ddt2/ddt2.H
+++ b/src/functionObjects/field/ddt2/ddt2.H
@@ -68,7 +68,7 @@ Description
 
 SourceFiles
     ddt2.C
-    IOddt2.H
+    ddt2Templates.C
 
 \*---------------------------------------------------------------------------*/
 
@@ -137,9 +137,6 @@ class ddt2
         //- Process by trying to apply for various volume field types.
         int process(const word& inputName);
 
-        //- Calculate the ddt2 fields
-        void process();
-
 
         //- Disallow default bitwise copy construct
         ddt2(const ddt2&) = delete;
@@ -171,7 +168,7 @@ public:
 
     // Member Functions
 
-        //- Return name of the ddt2 function object
+        //- Read the ddt2 specification
         virtual bool read(const dictionary&);
 
         //- Calculate the ddt2 fields
diff --git a/src/functionObjects/field/ddt2/ddt2Templates.C b/src/functionObjects/field/ddt2/ddt2Templates.C
index 098a5aa8c80b7fd481aeaadc2b45a08b101279b7..3514dbe3b64d7574ff0806bd476686941b797678 100644
--- a/src/functionObjects/field/ddt2/ddt2Templates.C
+++ b/src/functionObjects/field/ddt2/ddt2Templates.C
@@ -27,6 +27,8 @@ License
 #include "dimensionedType.H"
 #include "fvcDdt.H"
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
 template<class FieldType>
 int Foam::functionObjects::ddt2::apply(const word& inputName, int& state)
 {
@@ -76,10 +78,8 @@ int Foam::functionObjects::ddt2::apply(const word& inputName, int& state)
         store(outputName, tddt2);
     }
 
-    volScalarField& output = const_cast<volScalarField&>
-    (
-        lookupObject<volScalarField>(outputName)
-    );
+    volScalarField& output =
+        const_cast<volScalarField&>(lookupObject<volScalarField>(outputName));
 
     if (mag_)
     {
@@ -91,7 +91,7 @@ int Foam::functionObjects::ddt2::apply(const word& inputName, int& state)
     }
 
     // Could add additional statistics here
-    Log << type() << " " << name()
+    Log << type() << ' ' << name()
         << " field " << outputName
         << " average: " << gAverage(output) << endl;
 
diff --git a/src/functionObjects/field/zeroGradient/zeroGradient.C b/src/functionObjects/field/zeroGradient/zeroGradient.C
index 493e70d84f7cdbba4e25440eaff2e063d22cab5a..9f7a2c257e7cedf3aafd93e7a1103e65fe426f8d 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradient.C
+++ b/src/functionObjects/field/zeroGradient/zeroGradient.C
@@ -108,7 +108,45 @@ int Foam::functionObjects::zeroGradient::process(const word& fieldName)
 }
 
 
-void Foam::functionObjects::zeroGradient::process()
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::functionObjects::zeroGradient::zeroGradient
+(
+    const word& name,
+    const Time& runTime,
+    const dictionary& dict
+)
+:
+    fvMeshFunctionObject(name, runTime, dict),
+    selectFields_(),
+    resultName_(string::null),
+    results_()
+{
+    read(dict);
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::functionObjects::zeroGradient::~zeroGradient()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::functionObjects::zeroGradient::read(const dictionary& dict)
+{
+    fvMeshFunctionObject::read(dict);
+
+    dict.lookup("fields") >> selectFields_;
+    uniqWords(selectFields_);
+
+    resultName_ = dict.lookupOrDefault<word>("result", type() + "(@@)");
+    return checkFormatName(resultName_);
+}
+
+
+bool Foam::functionObjects::zeroGradient::execute()
 {
     results_.clear();
 
@@ -150,57 +188,20 @@ void Foam::functionObjects::zeroGradient::process()
         WarningInFunction
             << "Unprocessed field " << ignored << endl;
     }
-}
-
-
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::functionObjects::zeroGradient::zeroGradient
-(
-    const word& name,
-    const Time& runTime,
-    const dictionary& dict
-)
-:
-    fvMeshFunctionObject(name, runTime, dict),
-    selectFields_(),
-    resultName_(string::null),
-    results_()
-{
-    read(dict);
-}
-
-
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::functionObjects::zeroGradient::~zeroGradient()
-{}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-bool Foam::functionObjects::zeroGradient::read(const dictionary& dict)
-{
-    dict.lookup("fields") >> selectFields_;
-    uniqWords(selectFields_);
-
-    resultName_ = dict.lookupOrDefault<word>("result", type() + "(@@)");
-    return checkFormatName(resultName_);
-}
-
-
-bool Foam::functionObjects::zeroGradient::execute()
-{
-    results_.clear();
     return true;
 }
 
 
 bool Foam::functionObjects::zeroGradient::write()
 {
+    if (results_.size())
+    {
+        Log << type() << ' ' << name() << " write:" << endl;
+    }
+
     // Consistent output order
     const wordList outputList = results_.sortedToc();
-
     forAll(outputList, i)
     {
         const word& fieldName = outputList[i];
@@ -209,8 +210,7 @@ bool Foam::functionObjects::zeroGradient::write()
         {
             const regIOobject& io = lookupObject<regIOobject>(fieldName);
 
-            Log << type() << " " << name()
-                << " write: writing field " << fieldName << endl;
+            Log << "    " << fieldName << endl;
 
             io.write();
         }
diff --git a/src/functionObjects/field/zeroGradient/zeroGradient.H b/src/functionObjects/field/zeroGradient/zeroGradient.H
index 80535548d65a3af259c0b2a2e1bc89809abaf8f9..3ceda2cefe63552e8757a09df5ee9535594a4fc6 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradient.H
+++ b/src/functionObjects/field/zeroGradient/zeroGradient.H
@@ -65,8 +65,7 @@ Description
 
 SourceFiles
     zeroGradient.C
-    zeroGradientFunctionObject.C
-    IOzeroGradient.H
+    zeroGradientTemplates.C
 
 \*---------------------------------------------------------------------------*/
 
@@ -114,7 +113,10 @@ class zeroGradient
         static void uniqWords(wordReList&);
 
 
-        //- Accept unless field only has empty/zero-gradient/processor patches
+        //- Accept unless field only has constraint patches
+        //  (ie, empty/zero-gradient/processor).
+        //  This should also avoid fields that were already processed by
+        //  zeroGradient.
         template<class Type>
         static bool accept(const GeometricField<Type, fvPatchField, volMesh>&);
 
@@ -125,9 +127,6 @@ class zeroGradient
         //- Process by trying to apply for various volume field types.
         int process(const word& inputName);
 
-        //- Calculate the zeroGradient fields
-        void process();
-
 
         //- Disallow default bitwise copy construct
         zeroGradient(const zeroGradient&) = delete;
diff --git a/src/functionObjects/field/zeroGradient/zeroGradientTemplates.C b/src/functionObjects/field/zeroGradient/zeroGradientTemplates.C
index 09c32d45fb32af3b1203f01b5c79d8260a5c5b75..c900f9575d04c14352e4c629c6dc49f285c87e8f 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradientTemplates.C
+++ b/src/functionObjects/field/zeroGradient/zeroGradientTemplates.C
@@ -27,6 +27,8 @@ License
 #include "Time.H"
 #include "zeroGradientFvPatchField.H"
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
 template<class Type>
 bool Foam::functionObjects::zeroGradient::accept
 (
@@ -38,10 +40,10 @@ bool Foam::functionObjects::zeroGradient::accept
 
     forAll(patches, patchi)
     {
-        const fvPatchField<Type>& p = patches[patchi];
-        const polyPatch& pp = p.patch().patch();
-
-        return !polyPatch::constraintType(pp.type());
+        if (!polyPatch::constraintType(patches[patchi].patch().patch().type()))
+        {
+            return true;
+        }
     }
 
     return false;
@@ -104,6 +106,7 @@ int Foam::functionObjects::zeroGradient::apply
 
     VolFieldType& output =
         const_cast<VolFieldType&>(lookupObject<VolFieldType>(outputName));
+
     output = input;
     output.correctBoundaryConditions();