diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
index 9152d17fdeba143063f3608efe860e851c6a3ee7..1ef718a700202a7d0fad8a21f5e3c7917a67752e 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.C
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.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-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -83,18 +83,21 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::operationTypeNames_
     { operationType::opCoV, "CoV" },
     { operationType::opAreaNormalAverage, "areaNormalAverage" },
     { operationType::opAreaNormalIntegrate, "areaNormalIntegrate" },
+    { operationType::opUniformity, "uniformity" },
 
     // Using weighting
     { operationType::opWeightedSum, "weightedSum" },
     { operationType::opWeightedAverage, "weightedAverage" },
     { operationType::opWeightedAreaAverage, "weightedAreaAverage" },
     { operationType::opWeightedAreaIntegrate, "weightedAreaIntegrate" },
+    { operationType::opWeightedUniformity, "weightedUniformity" },
 
     // Using absolute weighting
     { operationType::opAbsWeightedSum, "absWeightedSum" },
     { operationType::opAbsWeightedAverage, "absWeightedAverage" },
     { operationType::opAbsWeightedAreaAverage, "absWeightedAreaAverage" },
     { operationType::opAbsWeightedAreaIntegrate, "absWeightedAreaIntegrate" },
+    { operationType::opAbsWeightedUniformity, "absWeightedUniformity" },
 };
 
 const Foam::Enum
@@ -117,10 +120,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::obr() const
     {
         return mesh_.lookupObject<objectRegistry>(regionName_);
     }
-    else
-    {
-        return mesh_;
-    }
+
+    return mesh_;
 }
 
 
@@ -599,7 +600,7 @@ void Foam::functionObjects::fieldValues::surfaceFieldValue::initialise
         }
     }
 
-    // Backwards compatibility for v1612+ and older
+    // Backwards compatibility for v1612 and older
     List<word> orientedFields;
     if (dict.readIfPresent("orientedFields", orientedFields))
     {
@@ -696,6 +697,45 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
 
             return gSum(pos0(nv)*mag(values) - neg(nv)*mag(values));
         }
+
+        case opUniformity:
+        case opWeightedUniformity:
+        case opAbsWeightedUniformity:
+        {
+            const scalar areaTotal = gSum(mag(Sf));
+            tmp<scalarField> areaVal(values * mag(Sf));
+
+            scalar mean, numer;
+
+            if (canWeight(weightField))
+            {
+                // Weighted quantity = (Weight * phi * dA)
+
+                tmp<scalarField> weight(weightingFactor(weightField));
+
+                // Mean weighted value (area-averaged)
+                mean = gSum(weight()*areaVal()) / areaTotal;
+
+                // Abs. deviation from weighted mean value
+                numer = gSum(mag(weight*areaVal - (mean * mag(Sf))));
+            }
+            else
+            {
+                // Unweighted quantity = (1 * phi * dA)
+
+                // Mean value (area-averaged)
+                mean = gSum(areaVal()) / areaTotal;
+
+                // Abs. deviation from mean value
+                numer = gSum(mag(areaVal - (mean * mag(Sf))));
+            }
+
+            // Uniformity index
+            const scalar ui = 1 - numer/(2*mag(mean*areaTotal) + ROOTVSMALL);
+
+            return min(max(ui, 0), 1);
+        }
+
         default:
         {
             // Fall through to other operations
@@ -742,6 +782,45 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::processValues
             const scalar val = gSum(values & Sf);
             return vector(val, 0, 0);
         }
+
+        case opUniformity:
+        case opWeightedUniformity:
+        case opAbsWeightedUniformity:
+        {
+            const scalar areaTotal = gSum(mag(Sf));
+            tmp<scalarField> areaVal(values & Sf);
+
+            scalar mean, numer;
+
+            if (canWeight(weightField))
+            {
+                // Weighted quantity = (Weight * phi . dA)
+
+                tmp<scalarField> weight(weightingFactor(weightField));
+
+                // Mean weighted value (area-averaged)
+                mean = gSum(weight()*areaVal()) / areaTotal;
+
+                // Abs. deviation from weighted mean value
+                numer = gSum(mag(weight*areaVal - (mean * mag(Sf))));
+            }
+            else
+            {
+                // Unweighted quantity = (1 * phi . dA)
+
+                // Mean value (area-averaged)
+                mean = gSum(areaVal()) / areaTotal;
+
+                // Abs. deviation from mean value
+                numer = gSum(mag(areaVal - (mean * mag(Sf))));
+            }
+
+            // Uniformity index
+            const scalar ui = 1 - numer/(2*mag(mean*areaTotal) + ROOTVSMALL);
+
+            return vector(min(max(ui, 0), 1), 0, 0);
+        }
+
         default:
         {
             // Fall through to other operations
@@ -762,11 +841,9 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
     {
         return mag(weightField);
     }
-    else
-    {
-        // pass through
-        return weightField;
-    }
+
+    // pass through
+    return weightField;
 }
 
 
@@ -788,10 +865,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
     {
         return mag(weightField * mag(Sf));
     }
-    else
-    {
-        return (weightField * mag(Sf));
-    }
+
+    return (weightField * mag(Sf));
 }
 
 
@@ -813,10 +888,8 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::weightingFactor
     {
         return mag(weightField & Sf);
     }
-    else
-    {
-        return (weightField & Sf);
-    }
+
+    return (weightField & Sf);
 }
 
 
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
index b34a0529168d51dc740043975760bba8a88fe732..2ada28a0faab446f1fe5697ec682241d7d680c06 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
@@ -145,6 +145,21 @@ Note
         - take care when using isoSurfaces - these might have duplicate
           triangles and so integration might be wrong
 
+    Uniformity
+    \f[
+        UI(\phi) = 1 - \frac{1}{2 \overline{\phi} A}
+        \int{\left| W \phi \cdot \hat{n} - \bar{W} \bar{\phi}\right| d\vec{A}}
+        \,,\;
+        \bar{\phi} = \frac{\int{W \phi \cdot d\vec{A}}}{\int{W \cdot d\vec{A}}}
+    \f]
+
+    A velocity uniformity index is calculated with no weighting (W=1) and
+    \f$ \phi = \vec{U} \f$.
+
+    A scalar concentration uniformity index is calculated with either
+    \f$ \rho \vec{U} \f$ or \f$ \vec{U} \f$ for weighting and
+    \f$ \phi = conc \f$.
+
 See also
     Foam::fieldValues
     Foam::functionObject
@@ -232,6 +247,7 @@ public:
             opCoV,                  //!< Coefficient of variation
             opAreaNormalAverage,    //!< Area average in normal direction
             opAreaNormalIntegrate,  //!< Area integral in normal direction
+            opUniformity,           //!< Uniformity index
 
             // Weighted variants
 
@@ -247,6 +263,9 @@ public:
             //! Weighted area integral
             opWeightedAreaIntegrate = (opAreaIntegrate | typeWeighted),
 
+            //! Weighted uniformity index
+            opWeightedUniformity = (opUniformity | typeWeighted),
+
             // Variants using absolute weighting
 
             //! Sum using abs weighting
@@ -261,6 +280,10 @@ public:
             //! Area integral using abs weighting
             opAbsWeightedAreaIntegrate =
                 (opWeightedAreaIntegrate | typeAbsolute),
+
+            //! Uniformity index using abs weighting
+            opAbsWeightedUniformity =
+                (opWeightedUniformity | typeAbsolute),
         };
 
         //- Operation type names
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
index cdc54e8afb50655447b3ea350b55d75b5ce9a4c4..0dbb882e84568c0751bbd60ddffa14daf83be48b 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
@@ -275,10 +275,28 @@ processSameTypeValues
 
         case opAreaNormalAverage:
         case opAreaNormalIntegrate:
+        case opUniformity:
         {
             // Handled in specializations only
             break;
         }
+
+        case opWeightedUniformity:
+        case opAbsWeightedUniformity:
+        {
+            if (canWeight(weightField))
+            {
+                // Change weighting from vector -> scalar and dispatch again
+                return processValues<Type, scalar>
+                (
+                    values,
+                    Sf,
+                    weightingFactor(weightField)
+                );
+            }
+
+            break;
+        }
     }
 
     return result;
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/T b/tutorials/compressible/rhoSimpleFoam/squareBend/0/T
index 19455db9e68506e20213916d8c239712fb3f383f..f756375b63e9139a905273f739020b749bb6d5af 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/T
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/T
@@ -20,23 +20,22 @@ internalField   uniform 1000;
 
 boundaryField
 {
-    Default_Boundary_Region
-    {
-        type            zeroGradient;
-    }
-
     inlet
     {
         type            fixedValue;
-        value           uniform 1000;
+        value           $internalField;
     }
 
     outlet
     {
         type            inletOutlet;
-        //type            zeroGradient;
-        value           uniform 1000;
-        inletValue      uniform 1000;
+        value           $internalField;
+        inletValue      $internalField;;
+    }
+
+    ".*"
+    {
+        type            zeroGradient;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/U b/tutorials/compressible/rhoSimpleFoam/squareBend/0/U
index 58e029d88f83eeacb50a0fa21435de95481a2019..49da5cddd07a95360875ba41ba7ec95270dfdb10 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/U
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/U
@@ -33,8 +33,8 @@ boundaryField
     outlet
     {
         type            inletOutlet;
-        value           uniform (0 0 0);
-        inletValue      uniform (0 0 0);
+        value           $internalField;
+        inletValue      $internalField;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/alphat b/tutorials/compressible/rhoSimpleFoam/squareBend/0/alphat
index ef74c232deda9225537f1af037fd3c9e3655e5c8..891f3e7787fe6f360c59734c6e26e000d97819d8 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/alphat
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/alphat
@@ -10,7 +10,6 @@ FoamFile
     version     2.0;
     format      ascii;
     class       volScalarField;
-    location    "0";
     object      alphat;
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -25,17 +24,17 @@ boundaryField
     {
         type            compressible::alphatWallFunction;
         Prt             0.85;
-        value           uniform 0;
+        value           $internalField;
     }
     inlet
     {
         type            calculated;
-        value           uniform 0;
+        value           $internalField;
     }
     outlet
     {
         type            calculated;
-        value           uniform 0;
+        value           $internalField;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/epsilon b/tutorials/compressible/rhoSimpleFoam/squareBend/0/epsilon
index 5b3d2ed84c070622a10558ef33311973ccc1b836..4b75d7acc38265d3ac27a7dc58e1b1b74c83a1fa 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/epsilon
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/epsilon
@@ -10,7 +10,6 @@ FoamFile
     version     2.0;
     format      ascii;
     class       volScalarField;
-    location    "0";
     object      epsilon;
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -27,19 +26,19 @@ boundaryField
         Cmu             0.09;
         kappa           0.41;
         E               9.8;
-        value           uniform 200;
+        value           $internalField;
     }
     inlet
     {
         type            turbulentMixingLengthDissipationRateInlet;
         mixingLength    0.005;
-        value           uniform 200;
+        value           $internalField;
     }
     outlet
     {
         type            inletOutlet;
-        inletValue      uniform 200;
-        value           uniform 200;
+        value           $internalField;
+        inletValue      $internalField;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/k b/tutorials/compressible/rhoSimpleFoam/squareBend/0/k
index 8650f473e478d0ae817e0e548a538b3e52323f8c..8a9421b335cfd6c8b34c32c4bfc49ef1dea66553 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/k
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/k
@@ -10,7 +10,6 @@ FoamFile
     version     2.0;
     format      ascii;
     class       volScalarField;
-    location    "0";
     object      k;
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -24,19 +23,19 @@ boundaryField
     Default_Boundary_Region
     {
         type            kqRWallFunction;
-        value           uniform 1;
+        value           $internalField;
     }
     inlet
     {
         type            turbulentIntensityKineticEnergyInlet;
         intensity       0.05;
-        value           uniform 1;
+        value           $internalField;
     }
     outlet
     {
         type            inletOutlet;
-        inletValue      uniform 1;
-        value           uniform 1;
+        value           $internalField;
+        inletValue      $internalField;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/nut b/tutorials/compressible/rhoSimpleFoam/squareBend/0/nut
index 10aa185190d7497a034bb3236d8f6d1db61d74ce..66f50ded1a9d5e00084613e4212ac800e19fe036 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/nut
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/nut
@@ -10,7 +10,6 @@ FoamFile
     version     2.0;
     format      ascii;
     class       volScalarField;
-    location    "0";
     object      nut;
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -27,17 +26,17 @@ boundaryField
         Cmu             0.09;
         kappa           0.41;
         E               9.8;
-        value           uniform 0;
+        value           $internalField;
     }
     inlet
     {
         type            calculated;
-        value           uniform 0;
+        value           $internalField;
     }
     outlet
     {
         type            calculated;
-        value           uniform 0;
+        value           $internalField;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/0/p b/tutorials/compressible/rhoSimpleFoam/squareBend/0/p
index 86bbf4b54a67dc9292c6376778d47cd9cf244971..52ad466a6bb56f917d47d7dd269b14445bc59de4 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/0/p
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/0/p
@@ -28,17 +28,17 @@ boundaryField
     {
         type            zeroGradient;
         //type            mixed;
-        refValue        uniform 110000;
+        refValue        $internalField;
         refGradient     uniform 0;
         valueFraction   uniform 0.3;
     }
     outlet
     {
         type            fixedValue;
-        value           uniform 110000;
+        value           $internalField;
 
         //type            mixed;
-        //refValue        uniform 110000;
+        //refValue        $internalField;
         //refGradient     uniform 0;
         //valueFraction   uniform 1;
         //type            transonicOutletPressure;
@@ -46,7 +46,12 @@ boundaryField
         //phi             phi;
         //gamma           1.4;
         //psi             psi;
-        //pInf            uniform 110000;
+        //pInf            $internalField;
+    }
+
+    ".*"
+    {
+        type            zeroGradient;
     }
 }
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/system/controlDict b/tutorials/compressible/rhoSimpleFoam/squareBend/system/controlDict
index 6a458462f032cceb8f45a38c7233ae210fac4264..b95b2cb2d2863fa1354e7f836db33c11a204d276 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/system/controlDict
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/system/controlDict
@@ -47,5 +47,12 @@ graphFormat     raw;
 
 runTimeModifiable true;
 
+#include "sampleControls"
+
+functions
+{
+    #include "sampling"
+}
+
 
 // ************************************************************************* //
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/system/fieldTransfer b/tutorials/compressible/rhoSimpleFoam/squareBend/system/fieldTransfer
new file mode 100644
index 0000000000000000000000000000000000000000..459347446d52db8425ecc95f67da8937202ae20b
--- /dev/null
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/system/fieldTransfer
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+
+// ************************************************************************* //
+
+// Transcribe volume fields to surfaces.
+fieldTransfer
+{
+    type    surfMeshes;
+    libs    ("libsampling.so");
+    log     true;
+    writeControl    none;
+    createOnRead    true;
+    executeControl  timeStep;
+    executeInterval 1;
+
+    fields      (p rho U T);
+    derived     (rhoU);
+
+    _plane
+    {
+        type    plane;
+        source  cells;
+
+        planeType   pointAndNormal;
+
+        pointAndNormalDict
+        {
+            normal (-1 0 0);
+            point  (-0.04 0 0);
+        }
+    }
+
+    surfaces
+    (
+        // Top channel
+        plane1
+        {
+            ${_plane}
+            bounds (-1 0 -1) (0 1 1);
+        }
+
+        // Bottom channel
+        plane2
+        {
+            ${_plane}
+            bounds (-1 -1 -1) (0 0 1);
+        }
+    );
+}
+
+// ************************************************************************* //
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampleControls b/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampleControls
new file mode 100644
index 0000000000000000000000000000000000000000..23e1cf4246d806e2ebed072dd335b6c0928ecd36
--- /dev/null
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampleControls
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+
+//   restartTime:
+//     - a 'one-shot' reset at a particular time
+//
+// fields [required]
+//     Pairs of fields to use for calculating the deviation.
+//     The fields must already exist on the surfaces.
+//
+// weightField [optional]
+//     A scalar or vector field for weighting.
+//
+// postOperation [optional]
+//     Modify the results by particular operations.
+//     (none | sqrt)
+//     The sqrt operation is useful when determining RMS values.
+//
+// The 'output/write' control triggers the calculation.
+__surfaceFieldValue
+{
+    type            surfaceFieldValue;
+    libs            ("libfieldFunctionObjects.so");
+    log             on;
+    enabled         true;
+
+    writeControl    timeStep;
+    writeInterval   1;
+
+    writeFields     false;
+    surfaceFormat   vtk;
+    // writeArea       true;
+
+    // resetOnStartUp  true;
+    // resetOnOutput   false;
+    // periodicRestart true;
+    // restartPeriod   0.0005;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampling b/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampling
new file mode 100644
index 0000000000000000000000000000000000000000..fe6f20e9cc8db60e98ced05550982873ac5c2720
--- /dev/null
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/system/sampling
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+// ************************************************************************* //
+
+#include "fieldTransfer"
+
+massflow
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane1;
+
+    operation       areaNormalIntegrate;
+
+    fields          ( rhoU );
+}
+
+areaIntegrate
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane1;
+
+    operation       weightedAreaIntegrate;
+    weightField     rhoU;
+    fields          ( T );
+}
+
+// Inflow uniformity
+UI1
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane1;
+
+    operation       uniformity;
+    fields          ( U T );
+}
+
+
+// Uniformity after the bend
+UI2
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane2;
+
+    operation       uniformity;
+    fields          ( U T );
+}
+
+
+// Inflow uniformity, but use a scalar field for weighting
+// Since this field is quite uniform, there should be no difference
+T_UI1
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane1;
+
+    operation       weightedUniformity;
+    weightField     T;
+    fields          ( U );
+}
+
+
+// rhoU-weighted uniformity, including weighting U too (weird but possible)
+rhoU_UI1
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane1;
+
+    operation       weightedUniformity;
+    weightField     rhoU;
+    fields          ( p rho U rhoU );
+}
+
+
+// rhoU-weighted uniformity
+rhoU_UI2
+{
+    ${__surfaceFieldValue}
+
+    regionType      surface;
+    name            plane2;
+
+    operation       weightedUniformity;
+    weightField     rhoU;
+    fields          ( p rho U rhoU );
+}
+
+// ************************************************************************* //