From c20b12b62f84aa67c1c8e9272c161ab6322fa0ca Mon Sep 17 00:00:00 2001
From: Mattijs Janssens <m.janssens@opencfd.co.uk>
Date: Mon, 29 Oct 2018 09:44:31 +0000
Subject: [PATCH] Feature patch function1

---
 applications/test/PatchFunction1/Make/files   |   3 +
 applications/test/PatchFunction1/Make/options |  15 +
 .../test/PatchFunction1/MappedField.C         | 401 +++++++++++
 .../test/PatchFunction1/MappedField.H         | 219 ++++++
 .../test/PatchFunction1/MappedFieldI.H        | 148 ++++
 .../test/PatchFunction1/Test-PatchFunction1.C | 107 +++
 .../test/PatchFunction1/function1Properties   |  38 ++
 .../functions/Function1/Table/Table.H         |   3 +-
 .../timeVaryingMappedFixedValueFvPatchField.C | 474 +------------
 .../timeVaryingMappedFixedValueFvPatchField.H |  62 +-
 .../uniformFixedValueFvPatchField.C           |   7 +-
 .../uniformFixedValueFvPatchField.H           |   4 +-
 src/meshTools/Make/files                      |   3 +
 .../ConstantField/ConstantField.C             | 118 ++++
 .../ConstantField/ConstantField.H             | 182 +++++
 .../ConstantField/ConstantFieldI.H            |  67 ++
 .../PatchFunction1/MappedFile}/AverageField.C |   0
 .../PatchFunction1/MappedFile}/AverageField.H |   0
 .../PatchFunction1/MappedFile/MappedFile.C    | 638 ++++++++++++++++++
 .../PatchFunction1/MappedFile/MappedFile.H    | 223 ++++++
 src/meshTools/PatchFunction1/PatchFunction1.C | 232 +++++++
 src/meshTools/PatchFunction1/PatchFunction1.H | 280 ++++++++
 .../PatchFunction1/PatchFunction1New.C        | 127 ++++
 .../UniformValueField/UniformValueField.C     | 100 +++
 .../UniformValueField/UniformValueField.H     | 186 +++++
 .../UniformValueField/UniformValueFieldI.H    |  84 +++
 .../PatchFunction1/coordinateLabelScaling.C   |  42 ++
 .../PatchFunction1/coordinateScaling.C        | 144 ++++
 .../PatchFunction1/coordinateScaling.H        | 142 ++++
 .../PatchFunction1/makePatchFunction1s.C      | 166 +++++
 30 files changed, 3709 insertions(+), 506 deletions(-)
 create mode 100644 applications/test/PatchFunction1/Make/files
 create mode 100644 applications/test/PatchFunction1/Make/options
 create mode 100644 applications/test/PatchFunction1/MappedField.C
 create mode 100644 applications/test/PatchFunction1/MappedField.H
 create mode 100644 applications/test/PatchFunction1/MappedFieldI.H
 create mode 100644 applications/test/PatchFunction1/Test-PatchFunction1.C
 create mode 100644 applications/test/PatchFunction1/function1Properties
 create mode 100644 src/meshTools/PatchFunction1/ConstantField/ConstantField.C
 create mode 100644 src/meshTools/PatchFunction1/ConstantField/ConstantField.H
 create mode 100644 src/meshTools/PatchFunction1/ConstantField/ConstantFieldI.H
 rename src/{finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue => meshTools/PatchFunction1/MappedFile}/AverageField.C (100%)
 rename src/{finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue => meshTools/PatchFunction1/MappedFile}/AverageField.H (100%)
 create mode 100644 src/meshTools/PatchFunction1/MappedFile/MappedFile.C
 create mode 100644 src/meshTools/PatchFunction1/MappedFile/MappedFile.H
 create mode 100644 src/meshTools/PatchFunction1/PatchFunction1.C
 create mode 100644 src/meshTools/PatchFunction1/PatchFunction1.H
 create mode 100644 src/meshTools/PatchFunction1/PatchFunction1New.C
 create mode 100644 src/meshTools/PatchFunction1/UniformValueField/UniformValueField.C
 create mode 100644 src/meshTools/PatchFunction1/UniformValueField/UniformValueField.H
 create mode 100644 src/meshTools/PatchFunction1/UniformValueField/UniformValueFieldI.H
 create mode 100644 src/meshTools/PatchFunction1/coordinateLabelScaling.C
 create mode 100644 src/meshTools/PatchFunction1/coordinateScaling.C
 create mode 100644 src/meshTools/PatchFunction1/coordinateScaling.H
 create mode 100644 src/meshTools/PatchFunction1/makePatchFunction1s.C

diff --git a/applications/test/PatchFunction1/Make/files b/applications/test/PatchFunction1/Make/files
new file mode 100644
index 00000000000..71ad5833517
--- /dev/null
+++ b/applications/test/PatchFunction1/Make/files
@@ -0,0 +1,3 @@
+Test-PatchFunction1.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-PatchFunction1
diff --git a/applications/test/PatchFunction1/Make/options b/applications/test/PatchFunction1/Make/options
new file mode 100644
index 00000000000..b8e72a86c6e
--- /dev/null
+++ b/applications/test/PatchFunction1/Make/options
@@ -0,0 +1,15 @@
+EXE_INC = \
+    -DFULLDEBUG -g -O0 \
+    -I$(LIB_SRC)/lagrangian/intermediate/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
+    -I$(LIB_SRC)/thermophysicalModels/thermophysicalFunctions/lnInclude \
+    -I$(LIB_SRC)/finiteVolume/lnInclude \
+    -I$(LIB_SRC)/meshTools/lnInclude
+
+EXE_LIBS = \
+    -llagrangianIntermediate \
+    -lradiationModels \
+    -lregionModels \
+    -lfiniteVolume \
+    -lmeshTools \
+    -lsampling
diff --git a/applications/test/PatchFunction1/MappedField.C b/applications/test/PatchFunction1/MappedField.C
new file mode 100644
index 00000000000..591a4885460
--- /dev/null
+++ b/applications/test/PatchFunction1/MappedField.C
@@ -0,0 +1,401 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "polyMesh.H"
+#include "IFstream.H"
+#include "AverageField.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::PatchFunction1Types::MappedField<Type>::MappedField
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict),
+    fieldTableName_(entryName),
+    setAverage_(dict.lookupOrDefault("setAverage", false)),
+    perturb_(dict.lookupOrDefault("perturb", 1e-5)),
+    pointsName_(dict.lookupOrDefault<word>("points", "points")),
+    mapMethod_
+    (
+        dict.lookupOrDefault<word>
+        (
+            "mapMethod",
+            "planarInterpolation"
+        )
+    ),
+    mapperPtr_(nullptr),
+    sampleTimes_(0),
+    startSampleTime_(-1),
+    startSampledValues_(0),
+    startAverage_(Zero),
+    endSampleTime_(-1),
+    endSampledValues_(0),
+    endAverage_(Zero),
+    offset_()
+{
+    if (dict.found("offset"))
+    {
+        offset_ = Function1<Type>::New("offset", dict);
+    }
+
+    if
+    (
+        mapMethod_ != "planarInterpolation"
+     && mapMethod_ != "nearest"
+    )
+    {
+        FatalIOErrorInFunction(dict)
+            << "mapMethod should be one of 'planarInterpolation'"
+            << ", 'nearest'" << exit(FatalIOError);
+    }
+
+    dict.readIfPresent("fieldTable", fieldTableName_);
+}
+
+
+template<class Type>
+Foam::PatchFunction1Types::MappedField<Type>::MappedField
+(
+    const MappedField<Type>& ut
+)
+:
+    PatchFunction1<Type>(ut),
+    fieldTableName_(ut.fieldTableName_),
+    setAverage_(ut.setAverage_),
+    perturb_(ut.perturb_),
+    pointsName_(ut.pointsName_),
+    mapMethod_(ut.mapMethod_),
+    mapperPtr_(nullptr),
+    sampleTimes_(ut.sampleTimes_),
+    startSampleTime_(ut.startSampleTime_),
+    startSampledValues_(ut.startSampledValues_),
+    startAverage_(ut.startAverage_),
+    endSampleTime_(ut.endSampleTime_),
+    endSampledValues_(ut.endSampledValues_),
+    endAverage_(ut.endAverage_),
+    offset_(ut.offset_.clone())
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::MappedField<Type>::MappedField
+(
+    const MappedField<Type>& ut,
+    const polyPatch& pp
+)
+:
+    PatchFunction1<Type>(ut, pp),
+    fieldTableName_(ut.fieldTableName_),
+    setAverage_(ut.setAverage_),
+    perturb_(ut.perturb_),
+    pointsName_(ut.pointsName_),
+    mapMethod_(ut.mapMethod_),
+    mapperPtr_(nullptr),
+    sampleTimes_(ut.sampleTimes_),
+    startSampleTime_(ut.startSampleTime_),
+    startSampledValues_(ut.startSampledValues_),
+    startAverage_(ut.startAverage_),
+    endSampleTime_(ut.endSampleTime_),
+    endSampledValues_(ut.endSampledValues_),
+    endAverage_(ut.endAverage_),
+    offset_(ut.offset_.clone())
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedField<Type>::autoMap
+(
+    const FieldMapper& mapper
+)
+{
+    if (startSampledValues_.size())
+    {
+        startSampledValues_.autoMap(mapper);
+        endSampledValues_.autoMap(mapper);
+    }
+    // Clear interpolator
+    mapperPtr_.clear();
+    startSampleTime_ = -1;
+    endSampleTime_ = -1;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedField<Type>::rmap
+(
+    const PatchFunction1<Type>& pf1,
+    const labelList& addr
+)
+{
+    const PatchFunction1Types::MappedField<Type>& tiptf =
+        refCast<const PatchFunction1Types::MappedField<Type>>(pf1);
+
+    startSampledValues_.rmap(tiptf.startSampledValues_, addr);
+    endSampledValues_.rmap(tiptf.endSampledValues_, addr);
+
+    // Clear interpolator
+    mapperPtr_.clear();
+    startSampleTime_ = -1;
+    endSampleTime_ = -1;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedField<Type>::checkTable() const
+{
+    const polyMesh& mesh = this->patch_.boundaryMesh().mesh();
+
+    // Initialise
+    if (mapperPtr_.empty())
+    {
+        // Reread values and interpolate
+        fileName samplePointsFile
+        (
+            mesh.time().path()
+           /mesh.time().caseConstant()
+           /"boundaryData"
+           /this->patch_.name()
+           /pointsName_
+        );
+
+        pointField samplePoints((IFstream(samplePointsFile)()));
+
+        DebugInfo
+            << " Read " << samplePoints.size() << " sample points from "
+            << samplePointsFile << endl;
+
+
+        // tbd: run-time selection
+        bool nearestOnly =
+        (
+           !mapMethod_.empty()
+         && mapMethod_ != "planarInterpolation"
+        );
+
+        // Allocate the interpolator
+        mapperPtr_.reset
+        (
+            new pointToPointPlanarInterpolation
+            (
+                samplePoints,
+                this->patch_.faceCentres(),
+                perturb_,
+                nearestOnly
+            )
+        );
+
+        // Read the times for which data is available
+        const fileName samplePointsDir = samplePointsFile.path();
+        sampleTimes_ = Time::findTimes(samplePointsDir);
+
+        DebugInfo
+            << "In directory "
+            << samplePointsDir << " found times "
+            << pointToPointPlanarInterpolation::timeNames(sampleTimes_)
+            << endl;
+    }
+
+
+    // Find current time in sampleTimes
+    label lo = -1;
+    label hi = -1;
+
+    bool foundTime = mapperPtr_().findTime
+    (
+        sampleTimes_,
+        startSampleTime_,
+        mesh.time().value(),
+        lo,
+        hi
+    );
+
+    if (!foundTime)
+    {
+        FatalErrorInFunction
+            << "Cannot find starting sampling values for current time "
+            << mesh.time().value() << nl
+            << "Have sampling values for times "
+            << pointToPointPlanarInterpolation::timeNames(sampleTimes_) << nl
+            << "In directory "
+            <<  mesh.time().constant()/"boundaryData"/this->patch_.name()
+            << "\n    on patch " << this->patch_.name()
+            << " of field " << fieldTableName_
+            << exit(FatalError);
+    }
+
+
+    // Update sampled data fields.
+
+    if (lo != startSampleTime_)
+    {
+        startSampleTime_ = lo;
+
+        if (startSampleTime_ == endSampleTime_)
+        {
+            // No need to reread since are end values
+            if (debug)
+            {
+                Pout<< "checkTable : Setting startValues to (already read) "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[startSampleTime_].name()
+                    << endl;
+            }
+            startSampledValues_ = endSampledValues_;
+            startAverage_ = endAverage_;
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "checkTable : Reading startValues from "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[lo].name()
+                    << endl;
+            }
+
+
+            // Reread values and interpolate
+            fileName valsFile
+            (
+                mesh.time().path()
+               /mesh.time().caseConstant()
+               /"boundaryData"
+               /this->patch_.name()
+               /sampleTimes_[startSampleTime_].name()
+               /fieldTableName_
+            );
+
+            Field<Type> vals;
+
+            if (setAverage_)
+            {
+                AverageField<Type> avals((IFstream(valsFile)()));
+                vals = avals;
+                startAverage_ = avals.average();
+            }
+            else
+            {
+                IFstream(valsFile)() >> vals;
+            }
+
+            if (vals.size() != mapperPtr_().sourceSize())
+            {
+                FatalErrorInFunction
+                    << "Number of values (" << vals.size()
+                    << ") differs from the number of points ("
+                    <<  mapperPtr_().sourceSize()
+                    << ") in file " << valsFile << exit(FatalError);
+            }
+
+            startSampledValues_ = mapperPtr_().interpolate(vals);
+        }
+    }
+
+    if (hi != endSampleTime_)
+    {
+        endSampleTime_ = hi;
+
+        if (endSampleTime_ == -1)
+        {
+            // endTime no longer valid. Might as well clear endValues.
+            if (debug)
+            {
+                Pout<< "checkTable : Clearing endValues" << endl;
+            }
+            endSampledValues_.clear();
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "checkTable : Reading endValues from "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[endSampleTime_].name()
+                    << endl;
+            }
+
+            // Reread values and interpolate
+            fileName valsFile
+            (
+                mesh.time().path()
+               /mesh.time().caseConstant()
+               /"boundaryData"
+               /this->patch_.name()
+               /sampleTimes_[endSampleTime_].name()
+               /fieldTableName_
+            );
+
+            Field<Type> vals;
+
+            if (setAverage_)
+            {
+                AverageField<Type> avals((IFstream(valsFile)()));
+                vals = avals;
+                endAverage_ = avals.average();
+            }
+            else
+            {
+                IFstream(valsFile)() >> vals;
+            }
+
+            if (vals.size() != mapperPtr_().sourceSize())
+            {
+                FatalErrorInFunction
+                    << "Number of values (" << vals.size()
+                    << ") differs from the number of points ("
+                    <<  mapperPtr_().sourceSize()
+                    << ") in file " << valsFile << exit(FatalError);
+            }
+
+            endSampledValues_ = mapperPtr_().interpolate(vals);
+        }
+    }
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedField<Type>::writeData
+(
+    Ostream& os
+) const
+{
+    PatchFunction1<Type>::writeData(os);
+    //os  << token::END_STATEMENT << nl;
+//    uniformValuePtr_->writeData(os);
+    //os  << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/PatchFunction1/MappedField.H b/applications/test/PatchFunction1/MappedField.H
new file mode 100644
index 00000000000..741481bda33
--- /dev/null
+++ b/applications/test/PatchFunction1/MappedField.H
@@ -0,0 +1,219 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Class
+    Foam::PatchFunction1Types::MappedField
+
+Description
+
+SourceFiles
+    MappedField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PatchFunction1Types_MappedField_H
+#define PatchFunction1Types_MappedField_H
+
+#include "PatchFunction1.H"
+#include "pointToPointPlanarInterpolation.H"
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace PatchFunction1Types
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class MappedField Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class MappedField
+:
+    public PatchFunction1<Type>
+{
+    // Private data
+
+        //- Name of the field data table, defaults to the name of the field
+        word fieldTableName_;
+
+        //- If true adjust the mapped field to maintain average value
+        Switch setAverage_;
+
+        //- Fraction of perturbation (fraction of bounding box) to add
+        scalar perturb_;
+
+        //- Name of points file; default = "points"
+        word pointsName_;
+
+        //- Interpolation scheme to use
+        word mapMethod_;
+
+        //- 2D interpolation (for 'planarInterpolation' mapMethod)
+        mutable autoPtr<pointToPointPlanarInterpolation> mapperPtr_;
+
+        //- List of boundaryData time directories
+        mutable instantList sampleTimes_;
+
+        //- Current starting index in sampleTimes
+        mutable label startSampleTime_;
+
+        //- Interpolated values from startSampleTime
+        mutable Field<Type> startSampledValues_;
+
+        //- If setAverage: starting average value
+        mutable Type startAverage_;
+
+        //- Current end index in sampleTimes
+        mutable label endSampleTime_;
+
+        //- Interpolated values from endSampleTime
+        mutable Field<Type> endSampledValues_;
+
+        //- If setAverage: end average value
+        mutable Type endAverage_;
+
+        //- Time varying offset values to interpolated data
+        autoPtr<Function1<Type>> offset_;
+
+
+    // Private Member Functions
+
+        void checkTable() const;
+
+        //- No copy assignment
+        void operator=(const MappedField<Type>&) = delete;
+
+
+public:
+
+    // Runtime type information
+    TypeName("mapped");
+
+
+    // Constructors
+
+        //- Construct from components
+        MappedField
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const Field<Type>& value
+        );
+
+        //- Construct from entry name and dictionary
+        MappedField
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict
+        );
+
+        //- Copy constructor
+        explicit MappedField(const MappedField<Type>& ut);
+
+        //- Copy constructor setting patch
+        explicit MappedField
+        (
+            const MappedField<Type>& ut,
+            const polyPatch& pp
+        );
+
+        //- Construct and return a clone
+        virtual tmp<PatchFunction1<Type>> clone() const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new MappedField<Type>(*this)
+            );
+        }
+
+        //- Construct and return a clone setting patch
+        virtual tmp<PatchFunction1<Type>> clone(const polyPatch& pp) const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new MappedField<Type>(*this, pp)
+            );
+        }
+
+
+    //- Destructor
+    virtual ~MappedField() = default;
+
+
+    // Member Functions
+
+        // Evaluation
+
+            //- Return MappedField value
+            virtual inline tmp<Field<Type>> value(const scalar) const;
+
+            //- Integrate between two values
+            virtual inline tmp<Field<Type>> integrate
+            (
+                const scalar x1,
+                const scalar x2
+            ) const;
+
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const FieldMapper& mapper);
+
+            //- Reverse map the given PatchFunction1 onto this PatchFunction1
+            virtual void rmap
+            (
+                const PatchFunction1<Type>& pf1,
+                const labelList& addr
+            );
+
+
+        // I-O
+
+            //- Write in dictionary format
+            virtual void writeData(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace PatchFunction1Types
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "MappedFieldI.H"
+
+#ifdef NoRepository
+    #include "MappedField.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/test/PatchFunction1/MappedFieldI.H b/applications/test/PatchFunction1/MappedFieldI.H
new file mode 100644
index 00000000000..4e91655817e
--- /dev/null
+++ b/applications/test/PatchFunction1/MappedFieldI.H
@@ -0,0 +1,148 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "MappedField.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::MappedField<Type>::value
+(
+    const scalar x
+) const
+{
+    const polyMesh& mesh = this->patch_.boundaryMesh().mesh();
+    checkTable();
+
+    tmp<Field<Type>> tfld(new Field<Type>(this->patch_.size()));
+    Field<Type>& fld = tfld.ref();
+    Type wantedAverage;
+
+    if (endSampleTime_ == -1)
+    {
+        // Only start value
+        if (debug)
+        {
+            Pout<< "updateCoeffs : Sampled, non-interpolated values"
+                << " from start time:"
+                << sampleTimes_[startSampleTime_].name() << nl;
+        }
+
+        fld = startSampledValues_;
+        wantedAverage = startAverage_;
+    }
+    else
+    {
+        scalar start = sampleTimes_[startSampleTime_].value();
+        scalar end = sampleTimes_[endSampleTime_].value();
+
+        scalar s = (mesh.time().value() - start)/(end - start);
+
+        if (debug)
+        {
+            Pout<< "updateCoeffs : Sampled, interpolated values"
+                << " between start time:"
+                << sampleTimes_[startSampleTime_].name()
+                << " and end time:" << sampleTimes_[endSampleTime_].name()
+                << " with weight:" << s << endl;
+        }
+
+        fld = ((1 - s)*startSampledValues_ + s*endSampledValues_);
+        wantedAverage = (1 - s)*startAverage_ + s*endAverage_;
+    }
+
+    // Enforce average. Either by scaling (if scaling factor > 0.5) or by
+    // offsetting.
+    if (setAverage_)
+    {
+        const scalarField magSf(mag(this->patch_.faceAreas()));
+
+        Type averagePsi = gSum(magSf*fld)/gSum(magSf);
+
+        if (debug)
+        {
+            Pout<< "updateCoeffs :"
+                << " actual average:" << averagePsi
+                << " wanted average:" << wantedAverage
+                << endl;
+        }
+
+        if (mag(averagePsi) < VSMALL)
+        {
+            // Field too small to scale. Offset instead.
+            const Type offset = wantedAverage - averagePsi;
+            if (debug)
+            {
+                Pout<< "updateCoeffs :"
+                    << " offsetting with:" << offset << endl;
+            }
+            fld += offset;
+        }
+        else
+        {
+            const scalar scale = mag(wantedAverage)/mag(averagePsi);
+
+            if (debug)
+            {
+                Pout<< "updateCoeffs :"
+                    << " scaling with:" << scale << endl;
+            }
+            fld *= scale;
+        }
+    }
+
+    // Apply offset to mapped values
+    if (offset_.valid())
+    {
+        const scalar t = mesh.time().timeOutputValue();
+        fld += offset_->value(t);
+    }
+
+    if (debug)
+    {
+        Pout<< "updateCoeffs : set fixedValue to min:" << gMin(fld)
+            << " max:" << gMax(fld)
+            << " avg:" << gAverage(fld) << endl;
+    }
+
+    return this->transform(tfld);
+}
+
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::MappedField<Type>::integrate
+(
+    const scalar x1,
+    const scalar x2
+) const
+{
+    NotImplemented;
+    return tmp<Field<Type>>(nullptr);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/PatchFunction1/Test-PatchFunction1.C b/applications/test/PatchFunction1/Test-PatchFunction1.C
new file mode 100644
index 00000000000..59c6b7c378c
--- /dev/null
+++ b/applications/test/PatchFunction1/Test-PatchFunction1.C
@@ -0,0 +1,107 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Application
+    Test-Function1
+
+Description
+    Tests Function1
+
+\*---------------------------------------------------------------------------*/
+
+#include "fvCFD.H"
+#include "PatchFunction1.H"
+#include "IOdictionary.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+    #include "setRootCase.H"
+    #include "createTime.H"
+    #include "createMesh.H"
+
+    IOdictionary function1Properties
+    (
+        IOobject
+        (
+            "function1Properties",
+            runTime.constant(),
+            mesh,
+            IOobject::MUST_READ_IF_MODIFIED,
+            IOobject::NO_WRITE
+        )
+    );
+
+    autoPtr<PatchFunction1<vector>> function1
+    (
+        PatchFunction1<vector>::New
+        (
+            mesh.boundaryMesh()[0],
+            "function1",
+            function1Properties
+        )
+    );
+
+    scalar x0 = function1Properties.get<scalar>("x0");
+    scalar x1 = function1Properties.get<scalar>("x1");
+
+    Info<< "Data entry type: " << function1().type() << nl << endl;
+
+    Info<< "Inputs" << nl
+        << "    x0 = " << x0 << nl
+        << "    x1 = " << x1 << nl
+        << endl;
+
+    Info<< "Interpolation" << nl
+        << "    f(x0) = " << function1().value(x0) << nl
+        << "    f(x1) = " << function1().value(x1) << nl
+        << endl;
+
+    Info<< "Integration" << nl
+        << "    int(f(x)) lim(x0->x1) = " << function1().integrate(x0, x1) << nl
+        << endl;
+
+    volVectorField fld
+    (
+        IOobject
+        (
+            "value",
+            runTime.timeName(),
+            mesh,
+            IOobject::NO_READ,
+            IOobject::AUTO_WRITE,
+            false
+        ),
+        mesh,
+        dimensionedVector(vector::zero)
+    );
+
+    fld.boundaryFieldRef()[0] == function1().value(x0);
+    fld.write();
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/PatchFunction1/function1Properties b/applications/test/PatchFunction1/function1Properties
new file mode 100644
index 00000000000..516011069eb
--- /dev/null
+++ b/applications/test/PatchFunction1/function1Properties
@@ -0,0 +1,38 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      function1Properties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+x0  0.5;
+x1  1;
+
+
+//- Dictionary notation
+function1 uniformValue;
+
+function1Coeffs
+{
+    function1 (0 1 0);  //table ((0 (0 0 0))(1 (1 1 1)));
+    coordinateSystem
+    {
+        type    cylindrical;
+        origin  (0.05 0.1 0.05);
+        e3      (0 1 0);
+        e1      (1 0 0);
+    }
+    scale1  table ((0 (0 0 0))(1 (1 1 1)));
+}
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/functions/Function1/Table/Table.H b/src/OpenFOAM/primitives/functions/Function1/Table/Table.H
index d46a53e00b0..2ce790a79d8 100644
--- a/src/OpenFOAM/primitives/functions/Function1/Table/Table.H
+++ b/src/OpenFOAM/primitives/functions/Function1/Table/Table.H
@@ -47,8 +47,7 @@ SourceFiles
 #ifndef Table_H
 #define Table_H
 
-#include "Function1.H"
-#include "Tuple2.H"
+#include "TableBase.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C
index 5f0ae2eee04..491c5013656 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C
@@ -39,20 +39,7 @@ timeVaryingMappedFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(p, iF),
-    fieldTableName_(iF.name()),
-    setAverage_(false),
-    perturb_(0),
-    pointsName_("points"),
-    mapMethod_("planarInterpolation"),
-    mapperPtr_(nullptr),
-    sampleTimes_(0),
-    startSampleTime_(-1),
-    startSampledValues_(0),
-    startAverage_(Zero),
-    endSampleTime_(-1),
-    endSampledValues_(0),
-    endAverage_(Zero),
-    offset_()
+    uniformValue_()
 {}
 
 
@@ -66,46 +53,18 @@ timeVaryingMappedFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(p, iF, dict, false),
-    fieldTableName_(iF.name()),
-    setAverage_(dict.lookupOrDefault("setAverage", false)),
-    perturb_(dict.lookupOrDefault("perturb", 1e-5)),
-    pointsName_(dict.lookupOrDefault<word>("points", "points")),
-    mapMethod_
+    uniformValue_
     (
-        dict.lookupOrDefault<word>
+        new PatchFunction1Types::MappedFile<Type>
         (
-            "mapMethod",
-            "planarInterpolation"
+            p.patch(),
+            "uniformValue",
+            dict,
+            iF.name(),          // field table name
+            true                // face values
         )
-    ),
-    mapperPtr_(nullptr),
-    sampleTimes_(0),
-    startSampleTime_(-1),
-    startSampledValues_(0),
-    startAverage_(Zero),
-    endSampleTime_(-1),
-    endSampledValues_(0),
-    endAverage_(Zero),
-    offset_()
-{
-    if (dict.found("offset"))
-    {
-        offset_ = Function1<Type>::New("offset", dict);
-    }
-
-    if
-    (
-        mapMethod_ != "planarInterpolation"
-     && mapMethod_ != "nearest"
     )
-    {
-        FatalIOErrorInFunction(dict)
-            << "mapMethod should be one of 'planarInterpolation'"
-            << ", 'nearest'" << exit(FatalIOError);
-    }
-
-    dict.readIfPresent("fieldTable", fieldTableName_);
-
+{
     if (dict.found("value"))
     {
         fvPatchField<Type>::operator==(Field<Type>("value", dict, p.size()));
@@ -132,20 +91,14 @@ timeVaryingMappedFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
-    fieldTableName_(ptf.fieldTableName_),
-    setAverage_(ptf.setAverage_),
-    perturb_(ptf.perturb_),
-    pointsName_(ptf.pointsName_),
-    mapMethod_(ptf.mapMethod_),
-    mapperPtr_(nullptr),
-    sampleTimes_(0),
-    startSampleTime_(-1),
-    startSampledValues_(0),
-    startAverage_(Zero),
-    endSampleTime_(-1),
-    endSampledValues_(0),
-    endAverage_(Zero),
-    offset_(ptf.offset_.clone())
+    uniformValue_
+    (
+        new PatchFunction1Types::MappedFile<Type>
+        (
+            ptf.uniformValue_,
+            p.patch()
+        )
+    )
 {}
 
 
@@ -157,20 +110,13 @@ timeVaryingMappedFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(ptf),
-    fieldTableName_(ptf.fieldTableName_),
-    setAverage_(ptf.setAverage_),
-    perturb_(ptf.perturb_),
-    pointsName_(ptf.pointsName_),
-    mapMethod_(ptf.mapMethod_),
-    mapperPtr_(nullptr),
-    sampleTimes_(ptf.sampleTimes_),
-    startSampleTime_(ptf.startSampleTime_),
-    startSampledValues_(ptf.startSampledValues_),
-    startAverage_(ptf.startAverage_),
-    endSampleTime_(ptf.endSampleTime_),
-    endSampledValues_(ptf.endSampledValues_),
-    endAverage_(ptf.endAverage_),
-    offset_(ptf.offset_.clone())
+    uniformValue_
+    (
+        new PatchFunction1Types::MappedFile<Type>
+        (
+            ptf.uniformValue_
+        )
+    )
 {}
 
 
@@ -183,20 +129,13 @@ timeVaryingMappedFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(ptf, iF),
-    fieldTableName_(ptf.fieldTableName_),
-    setAverage_(ptf.setAverage_),
-    perturb_(ptf.perturb_),
-    pointsName_(ptf.pointsName_),
-    mapMethod_(ptf.mapMethod_),
-    mapperPtr_(nullptr),
-    sampleTimes_(ptf.sampleTimes_),
-    startSampleTime_(ptf.startSampleTime_),
-    startSampledValues_(ptf.startSampledValues_),
-    startAverage_(ptf.startAverage_),
-    endSampleTime_(ptf.endSampleTime_),
-    endSampledValues_(ptf.endSampledValues_),
-    endAverage_(ptf.endAverage_),
-    offset_(ptf.offset_.clone())
+    uniformValue_
+    (
+        new PatchFunction1Types::MappedFile<Type>
+        (
+            ptf.uniformValue_
+        )
+    )
 {}
 
 
@@ -209,15 +148,7 @@ void Foam::timeVaryingMappedFixedValueFvPatchField<Type>::autoMap
 )
 {
     fixedValueFvPatchField<Type>::autoMap(m);
-    if (startSampledValues_.size())
-    {
-        startSampledValues_.autoMap(m);
-        endSampledValues_.autoMap(m);
-    }
-    // Clear interpolator
-    mapperPtr_.clear();
-    startSampleTime_ = -1;
-    endSampleTime_ = -1;
+    uniformValue_().autoMap(m);
 }
 
 
@@ -233,227 +164,7 @@ void Foam::timeVaryingMappedFixedValueFvPatchField<Type>::rmap
     const timeVaryingMappedFixedValueFvPatchField<Type>& tiptf =
         refCast<const timeVaryingMappedFixedValueFvPatchField<Type>>(ptf);
 
-    startSampledValues_.rmap(tiptf.startSampledValues_, addr);
-    endSampledValues_.rmap(tiptf.endSampledValues_, addr);
-
-    // Clear interpolator
-    mapperPtr_.clear();
-    startSampleTime_ = -1;
-    endSampleTime_ = -1;
-}
-
-
-template<class Type>
-void Foam::timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
-{
-    // Initialise
-    if (mapperPtr_.empty())
-    {
-        // Reread values and interpolate
-        fileName samplePointsFile
-        (
-            this->db().time().path()
-           /this->db().time().caseConstant()
-           /"boundaryData"
-           /this->patch().name()
-           /pointsName_
-        );
-
-        pointField samplePoints((IFstream(samplePointsFile)()));
-
-        DebugInfo
-            << " Read " << samplePoints.size() << " sample points from "
-            << samplePointsFile << endl;
-
-
-        // tbd: run-time selection
-        bool nearestOnly =
-        (
-           !mapMethod_.empty()
-         && mapMethod_ != "planarInterpolation"
-        );
-
-        // Allocate the interpolator
-        mapperPtr_.reset
-        (
-            new pointToPointPlanarInterpolation
-            (
-                samplePoints,
-                this->patch().patch().faceCentres(),
-                perturb_,
-                nearestOnly
-            )
-        );
-
-        // Read the times for which data is available
-        const fileName samplePointsDir = samplePointsFile.path();
-        sampleTimes_ = Time::findTimes(samplePointsDir);
-
-        DebugInfo
-            << "In directory "
-            << samplePointsDir << " found times "
-            << pointToPointPlanarInterpolation::timeNames(sampleTimes_)
-            << endl;
-    }
-
-
-    // Find current time in sampleTimes
-    label lo = -1;
-    label hi = -1;
-
-    bool foundTime = mapperPtr_().findTime
-    (
-        sampleTimes_,
-        startSampleTime_,
-        this->db().time().value(),
-        lo,
-        hi
-    );
-
-    if (!foundTime)
-    {
-        FatalErrorInFunction
-            << "Cannot find starting sampling values for current time "
-            << this->db().time().value() << nl
-            << "Have sampling values for times "
-            << pointToPointPlanarInterpolation::timeNames(sampleTimes_) << nl
-            << "In directory "
-            <<  this->db().time().constant()/"boundaryData"/this->patch().name()
-            << "\n    on patch " << this->patch().name()
-            << " of field " << fieldTableName_
-            << exit(FatalError);
-    }
-
-
-    // Update sampled data fields.
-
-    if (lo != startSampleTime_)
-    {
-        startSampleTime_ = lo;
-
-        if (startSampleTime_ == endSampleTime_)
-        {
-            // No need to reread since are end values
-            if (debug)
-            {
-                Pout<< "checkTable : Setting startValues to (already read) "
-                    << "boundaryData"
-                      /this->patch().name()
-                      /sampleTimes_[startSampleTime_].name()
-                    << endl;
-            }
-            startSampledValues_ = endSampledValues_;
-            startAverage_ = endAverage_;
-        }
-        else
-        {
-            if (debug)
-            {
-                Pout<< "checkTable : Reading startValues from "
-                    << "boundaryData"
-                      /this->patch().name()
-                      /sampleTimes_[lo].name()
-                    << endl;
-            }
-
-
-            // Reread values and interpolate
-            fileName valsFile
-            (
-                this->db().time().path()
-               /this->db().time().caseConstant()
-               /"boundaryData"
-               /this->patch().name()
-               /sampleTimes_[startSampleTime_].name()
-               /fieldTableName_
-            );
-
-            Field<Type> vals;
-
-            if (setAverage_)
-            {
-                AverageField<Type> avals((IFstream(valsFile)()));
-                vals = avals;
-                startAverage_ = avals.average();
-            }
-            else
-            {
-                IFstream(valsFile)() >> vals;
-            }
-
-            if (vals.size() != mapperPtr_().sourceSize())
-            {
-                FatalErrorInFunction
-                    << "Number of values (" << vals.size()
-                    << ") differs from the number of points ("
-                    <<  mapperPtr_().sourceSize()
-                    << ") in file " << valsFile << exit(FatalError);
-            }
-
-            startSampledValues_ = mapperPtr_().interpolate(vals);
-        }
-    }
-
-    if (hi != endSampleTime_)
-    {
-        endSampleTime_ = hi;
-
-        if (endSampleTime_ == -1)
-        {
-            // endTime no longer valid. Might as well clear endValues.
-            if (debug)
-            {
-                Pout<< "checkTable : Clearing endValues" << endl;
-            }
-            endSampledValues_.clear();
-        }
-        else
-        {
-            if (debug)
-            {
-                Pout<< "checkTable : Reading endValues from "
-                    << "boundaryData"
-                      /this->patch().name()
-                      /sampleTimes_[endSampleTime_].name()
-                    << endl;
-            }
-
-            // Reread values and interpolate
-            fileName valsFile
-            (
-                this->db().time().path()
-               /this->db().time().caseConstant()
-               /"boundaryData"
-               /this->patch().name()
-               /sampleTimes_[endSampleTime_].name()
-               /fieldTableName_
-            );
-
-            Field<Type> vals;
-
-            if (setAverage_)
-            {
-                AverageField<Type> avals((IFstream(valsFile)()));
-                vals = avals;
-                endAverage_ = avals.average();
-            }
-            else
-            {
-                IFstream(valsFile)() >> vals;
-            }
-
-            if (vals.size() != mapperPtr_().sourceSize())
-            {
-                FatalErrorInFunction
-                    << "Number of values (" << vals.size()
-                    << ") differs from the number of points ("
-                    <<  mapperPtr_().sourceSize()
-                    << ") in file " << valsFile << exit(FatalError);
-            }
-
-            endSampledValues_ = mapperPtr_().interpolate(vals);
-        }
-    }
+    uniformValue_().rmap(tiptf.uniformValue_(), addr);
 }
 
 
@@ -466,93 +177,8 @@ void Foam::timeVaryingMappedFixedValueFvPatchField<Type>::updateCoeffs()
     }
 
 
-    checkTable();
-
-    // Interpolate between the sampled data
-
-    Type wantedAverage;
-
-    if (endSampleTime_ == -1)
-    {
-        // Only start value
-        if (debug)
-        {
-            Pout<< "updateCoeffs : Sampled, non-interpolated values"
-                << " from start time:"
-                << sampleTimes_[startSampleTime_].name() << nl;
-        }
-
-        this->operator==(startSampledValues_);
-        wantedAverage = startAverage_;
-    }
-    else
-    {
-        scalar start = sampleTimes_[startSampleTime_].value();
-        scalar end = sampleTimes_[endSampleTime_].value();
-
-        scalar s = (this->db().time().value() - start)/(end - start);
-
-        if (debug)
-        {
-            Pout<< "updateCoeffs : Sampled, interpolated values"
-                << " between start time:"
-                << sampleTimes_[startSampleTime_].name()
-                << " and end time:" << sampleTimes_[endSampleTime_].name()
-                << " with weight:" << s << endl;
-        }
-
-        this->operator==((1 - s)*startSampledValues_ + s*endSampledValues_);
-        wantedAverage = (1 - s)*startAverage_ + s*endAverage_;
-    }
-
-    // Enforce average. Either by scaling (if scaling factor > 0.5) or by
-    // offsetting.
-    if (setAverage_)
-    {
-        const Field<Type>& fld = *this;
-
-        Type averagePsi =
-            gSum(this->patch().magSf()*fld)
-           /gSum(this->patch().magSf());
-
-        if (debug)
-        {
-            Pout<< "updateCoeffs :"
-                << " actual average:" << averagePsi
-                << " wanted average:" << wantedAverage
-                << endl;
-        }
-
-        if (mag(averagePsi) < VSMALL)
-        {
-            // Field too small to scale. Offset instead.
-            const Type offset = wantedAverage - averagePsi;
-            if (debug)
-            {
-                Pout<< "updateCoeffs :"
-                    << " offsetting with:" << offset << endl;
-            }
-            this->operator==(fld + offset);
-        }
-        else
-        {
-            const scalar scale = mag(wantedAverage)/mag(averagePsi);
-
-            if (debug)
-            {
-                Pout<< "updateCoeffs :"
-                    << " scaling with:" << scale << endl;
-            }
-            this->operator==(scale*fld);
-        }
-    }
-
-    // Apply offset to mapped values
-    if (offset_.valid())
-    {
-        const scalar t = this->db().time().timeOutputValue();
-        this->operator==(*this + offset_->value(t));
-    }
+    const scalar t = this->db().time().timeOutputValue();
+    fvPatchField<Type>::operator==(uniformValue_->value(t));
 
     if (debug)
     {
@@ -572,35 +198,7 @@ void Foam::timeVaryingMappedFixedValueFvPatchField<Type>::write
 ) const
 {
     fvPatchField<Type>::write(os);
-
-    os.writeEntryIfDifferent
-    (
-        "fieldTable",
-        this->internalField().name(),
-        fieldTableName_
-    );
-
-    if (setAverage_)
-    {
-        os.writeEntry("setAverage", setAverage_);
-    }
-
-    os.writeEntryIfDifferent<scalar>("perturb", 1e-5, perturb_);
-
-    os.writeEntryIfDifferent<word>("points", "points", pointsName_);
-
-    os.writeEntryIfDifferent<word>
-    (
-        "mapMethod",
-        "planarInterpolation",
-        mapMethod_
-    );
-
-    if (offset_.valid())
-    {
-        offset_->writeData(os);
-    }
-
+    uniformValue_->writeData(os);
     this->writeEntry("value", os);
 }
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.H
index d832ee1ae87..ae967f0b796 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.H
@@ -76,10 +76,7 @@ SourceFiles
 #define timeVaryingMappedFixedValueFvPatchField_H
 
 #include "fixedValueFvPatchFields.H"
-#include "FixedList.H"
-#include "instantList.H"
-#include "pointToPointPlanarInterpolation.H"
-#include "Function1.H"
+#include "MappedFile.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -97,47 +94,7 @@ class timeVaryingMappedFixedValueFvPatchField
 {
     // Private data
 
-        //- Name of the field data table, defaults to the name of the field
-        word fieldTableName_;
-
-        //- If true adjust the mapped field to maintain average value
-        Switch setAverage_;
-
-        //- Fraction of perturbation (fraction of bounding box) to add
-        scalar perturb_;
-
-        //- Name of points file; default = "points"
-        word pointsName_;
-
-        //- Interpolation scheme to use
-        word mapMethod_;
-
-        //- 2D interpolation (for 'planarInterpolation' mapMethod)
-        autoPtr<pointToPointPlanarInterpolation> mapperPtr_;
-
-        //- List of boundaryData time directories
-        instantList sampleTimes_;
-
-        //- Current starting index in sampleTimes
-        label startSampleTime_;
-
-        //- Interpolated values from startSampleTime
-        Field<Type> startSampledValues_;
-
-        //- If setAverage: starting average value
-        Type startAverage_;
-
-        //- Current end index in sampleTimes
-        label endSampleTime_;
-
-        //- Interpolated values from endSampleTime
-        Field<Type> endSampledValues_;
-
-        //- If setAverage: end average value
-        Type endAverage_;
-
-        //- Time varying offset values to interpolated data
-        autoPtr<Function1<Type>> offset_;
+        autoPtr<PatchFunction1Types::MappedFile<Type>> uniformValue_;
 
 
 public:
@@ -210,15 +167,6 @@ public:
 
     // Member functions
 
-        // Access
-
-            //- Return startSampledValues
-            const Field<Type> startSampledValues()
-            {
-                 return startSampledValues_;
-            }
-
-
         // Mapping functions
 
             //- Map (and resize as needed) from self given a mapping object
@@ -235,12 +183,6 @@ public:
             );
 
 
-        // Utility functions
-
-            //- Find boundary data inbetween current time and interpolate
-            void checkTable();
-
-
         // Evaluation functions
 
             //- Update the coefficients associated with the patch field
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.C
index dc4d7c8a932..853502055ae 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.C
@@ -61,7 +61,7 @@ Foam::uniformFixedValueFvPatchField<Type>::uniformFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(p, iF, dict, false),
-    uniformValue_(Function1<Type>::New("uniformValue", dict))
+    uniformValue_(PatchFunction1<Type>::New(p.patch(), "uniformValue", dict))
 {
     this->evaluate();
 }
@@ -77,7 +77,7 @@ Foam::uniformFixedValueFvPatchField<Type>::uniformFixedValueFvPatchField
 )
 :
     fixedValueFvPatchField<Type>(p, iF),   // Don't map
-    uniformValue_(ptf.uniformValue_.clone())
+    uniformValue_(ptf.uniformValue_.clone(p.patch()))
 {
     // Evaluate since value not mapped
     this->evaluate();
@@ -106,7 +106,7 @@ Foam::uniformFixedValueFvPatchField<Type>::uniformFixedValueFvPatchField
     uniformValue_(ptf.uniformValue_.clone())
 {
     // Evaluate the profile if defined
-    if (ptf.uniformValue_.valid())
+    if (uniformValue_.valid())
     {
         this->evaluate();
     }
@@ -125,7 +125,6 @@ void Foam::uniformFixedValueFvPatchField<Type>::updateCoeffs()
 
     const scalar t = this->db().time().timeOutputValue();
     fvPatchField<Type>::operator==(uniformValue_->value(t));
-
     fixedValueFvPatchField<Type>::updateCoeffs();
 }
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.H
index 36f3972980b..0e725abdc1b 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValue/uniformFixedValueFvPatchField.H
@@ -63,7 +63,7 @@ SourceFiles
 #define uniformFixedValueFvPatchField_H
 
 #include "fixedValueFvPatchFields.H"
-#include "Function1.H"
+#include "PatchFunction1.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -81,7 +81,7 @@ class uniformFixedValueFvPatchField
 {
     // Private data
 
-        autoPtr<Function1<Type>> uniformValue_;
+        autoPtr<PatchFunction1<Type>> uniformValue_;
 
 
 public:
diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index 1759739ff91..58c3fa156f1 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -275,6 +275,9 @@ mappedPatches/mappedPolyPatch/mappedVariableThicknessWallPolyPatch.C
 mappedPatches/mappedPointPatch/mappedPointPatch.C
 mappedPatches/mappedPointPatch/mappedWallPointPatch.C
 
+PatchFunction1/makePatchFunction1s.C
+PatchFunction1/coordinateLabelScaling.C
+
 meshStructure/meshStructure.C
 meshStructure/topoDistanceData.C
 meshStructure/pointTopoDistanceData.C
diff --git a/src/meshTools/PatchFunction1/ConstantField/ConstantField.C b/src/meshTools/PatchFunction1/ConstantField/ConstantField.C
new file mode 100644
index 00000000000..a6afaa09f4c
--- /dev/null
+++ b/src/meshTools/PatchFunction1/ConstantField/ConstantField.C
@@ -0,0 +1,118 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "ConstantField.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::PatchFunction1Types::ConstantField<Type>::ConstantField
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const Field<Type>& value,
+    const dictionary& dict,
+    const bool faceValues
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict, faceValues),
+    value_(value)
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::ConstantField<Type>::ConstantField
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const bool faceValues
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict, faceValues),
+    value_(entryName, dict, pp.size())
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::ConstantField<Type>::ConstantField
+(
+    const ConstantField<Type>& cnst
+)
+:
+    PatchFunction1<Type>(cnst),
+    value_(cnst.value_)
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::ConstantField<Type>::ConstantField
+(
+    const ConstantField<Type>& cnst,
+    const polyPatch& pp
+)
+:
+    PatchFunction1<Type>(cnst, pp),
+    value_(cnst.value_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::PatchFunction1Types::ConstantField<Type>::autoMap
+(
+    const FieldMapper& mapper
+)
+{
+    value_.autoMap(mapper);
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::ConstantField<Type>::rmap
+(
+    const PatchFunction1<Type>& pf1,
+    const labelList& addr
+)
+{
+    const auto& cst = refCast<const ConstantField<Type>>(pf1);
+    value_.rmap(cst.value_, addr);
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::ConstantField<Type>::writeData
+(
+    Ostream& os
+) const
+{
+    PatchFunction1<Type>::writeData(os);
+    //os  << token::SPACE << value_ << token::END_STATEMENT << nl;
+    value_.writeEntry(this->name_, os);
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/ConstantField/ConstantField.H b/src/meshTools/PatchFunction1/ConstantField/ConstantField.H
new file mode 100644
index 00000000000..703cfc49c1e
--- /dev/null
+++ b/src/meshTools/PatchFunction1/ConstantField/ConstantField.H
@@ -0,0 +1,182 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2015 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/>.
+
+Class
+    Foam::PatchFunction1Types::ConstantField
+
+Description
+    Templated function that returns a constant value.
+
+    Usage - for entry \<entryName\> returning the value <value>:
+    \verbatim
+        <entryName>    constant  <value>
+    \endverbatim
+
+SourceFiles
+    ConstantField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PatchFunction1Types_ConstantField_H
+#define PatchFunction1Types_ConstantField_H
+
+#include "PatchFunction1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace PatchFunction1Types
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class ConstantField Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class ConstantField
+:
+    public PatchFunction1<Type>
+{
+    // Private data
+
+        //- ConstantField value
+        Field<Type> value_;
+
+
+    // Private Member Functions
+
+        //- No copy assignment
+        void operator=(const ConstantField<Type>&) = delete;
+
+
+public:
+
+    // Runtime type information
+    TypeName("constant");
+
+
+    // Constructors
+
+        //- Construct from components
+        ConstantField
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const Field<Type>& value,
+            const dictionary& dict = dictionary::null,
+            const bool faceValues = true
+        );
+
+        //- Construct from entry name and dictionary
+        ConstantField
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const bool faceValues = true
+        );
+
+        //- Copy constructor
+        explicit ConstantField(const ConstantField<Type>& cnst);
+
+        //- Copy constructor setting patch
+        explicit ConstantField
+        (
+            const ConstantField<Type>& cnst,
+            const polyPatch& pp
+        );
+
+        //- Construct and return a clone
+        virtual tmp<PatchFunction1<Type>> clone() const
+        {
+            return tmp<PatchFunction1<Type>>(new ConstantField<Type>(*this));
+        }
+
+        //- Construct and return a clone setting patch
+        virtual tmp<PatchFunction1<Type>> clone(const polyPatch& pp) const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new ConstantField<Type>(*this, pp)
+            );
+        }
+
+
+    //- Destructor
+    virtual ~ConstantField() = default;
+
+
+    // Member Functions
+
+        // Evaluation
+
+            //- Return constant value
+            virtual inline tmp<Field<Type>> value(const scalar) const;
+
+            //- Integrate between two values
+            virtual inline tmp<Field<Type>> integrate
+            (
+                const scalar x1,
+                const scalar x2
+            ) const;
+
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const FieldMapper& mapper);
+
+            //- Reverse map the given PatchFunction1 onto this PatchFunction1
+            virtual void rmap
+            (
+                const PatchFunction1<Type>& pf1,
+                const labelList& addr
+            );
+
+
+        // I-O
+
+            //- Write in dictionary format
+            virtual void writeData(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace PatchFunction1Types
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "ConstantFieldI.H"
+
+#ifdef NoRepository
+    #include "ConstantField.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/ConstantField/ConstantFieldI.H b/src/meshTools/PatchFunction1/ConstantField/ConstantFieldI.H
new file mode 100644
index 00000000000..cdb8f903b6a
--- /dev/null
+++ b/src/meshTools/PatchFunction1/ConstantField/ConstantFieldI.H
@@ -0,0 +1,67 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "ConstantField.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::ConstantField<Type>::value
+(
+    const scalar x
+) const
+{
+    if (this->coordSys_.active())
+    {
+        return this->transform(value_);
+    }
+    else
+    {
+        return value_;
+    }
+}
+
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::ConstantField<Type>::integrate
+(
+    const scalar x1,
+    const scalar x2
+) const
+{
+    if (this->coordSys_.active())
+    {
+        return (x2 - x1)* this->transform(value_);
+    }
+    else
+    {
+        return (x2 - x1)*value_;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/AverageField.C b/src/meshTools/PatchFunction1/MappedFile/AverageField.C
similarity index 100%
rename from src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/AverageField.C
rename to src/meshTools/PatchFunction1/MappedFile/AverageField.C
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/AverageField.H b/src/meshTools/PatchFunction1/MappedFile/AverageField.H
similarity index 100%
rename from src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/AverageField.H
rename to src/meshTools/PatchFunction1/MappedFile/AverageField.H
diff --git a/src/meshTools/PatchFunction1/MappedFile/MappedFile.C b/src/meshTools/PatchFunction1/MappedFile/MappedFile.C
new file mode 100644
index 00000000000..a13da99ab13
--- /dev/null
+++ b/src/meshTools/PatchFunction1/MappedFile/MappedFile.C
@@ -0,0 +1,638 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "polyMesh.H"
+#include "IFstream.H"
+#include "AverageField.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::PatchFunction1Types::MappedFile<Type>::MappedFile
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const bool faceValues
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict, faceValues),
+    dictConstructed_(true),
+    fieldTableName_(entryName),
+    setAverage_(dict.lookupOrDefault("setAverage", false)),
+    perturb_(dict.lookupOrDefault("perturb", 1e-5)),
+    pointsName_(dict.lookupOrDefault<word>("points", "points")),
+    mapMethod_
+    (
+        dict.lookupOrDefault<word>
+        (
+            "mapMethod",
+            "planarInterpolation"
+        )
+    ),
+    mapperPtr_(nullptr),
+    sampleTimes_(0),
+    startSampleTime_(-1),
+    startSampledValues_(0),
+    startAverage_(Zero),
+    endSampleTime_(-1),
+    endSampledValues_(0),
+    endAverage_(Zero),
+    offset_()
+{
+    if (dict.found("offset"))
+    {
+        offset_ = Function1<Type>::New("offset", dict);
+    }
+
+    if
+    (
+        mapMethod_ != "planarInterpolation"
+     && mapMethod_ != "nearest"
+    )
+    {
+        FatalIOErrorInFunction(dict)
+            << "mapMethod should be one of 'planarInterpolation'"
+            << ", 'nearest'" << exit(FatalIOError);
+    }
+
+    dict.readIfPresent("fieldTable", fieldTableName_);
+}
+
+
+template<class Type>
+Foam::PatchFunction1Types::MappedFile<Type>::MappedFile
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const word& fieldTableName,
+    const bool faceValues
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict, faceValues),
+    dictConstructed_(false),
+    fieldTableName_(fieldTableName),
+    setAverage_(dict.lookupOrDefault("setAverage", false)),
+    perturb_(dict.lookupOrDefault("perturb", 1e-5)),
+    pointsName_(dict.lookupOrDefault<word>("points", "points")),
+    mapMethod_
+    (
+        dict.lookupOrDefault<word>
+        (
+            "mapMethod",
+            "planarInterpolation"
+        )
+    ),
+    mapperPtr_(nullptr),
+    sampleTimes_(0),
+    startSampleTime_(-1),
+    startSampledValues_(0),
+    startAverage_(Zero),
+    endSampleTime_(-1),
+    endSampledValues_(0),
+    endAverage_(Zero),
+    offset_()
+{
+    if (dict.found("offset"))
+    {
+        offset_ = Function1<Type>::New("offset", dict);
+    }
+
+    if
+    (
+        mapMethod_ != "planarInterpolation"
+     && mapMethod_ != "nearest"
+    )
+    {
+        FatalIOErrorInFunction(dict)
+            << "mapMethod should be one of 'planarInterpolation'"
+            << ", 'nearest'" << exit(FatalIOError);
+    }
+}
+
+
+template<class Type>
+Foam::PatchFunction1Types::MappedFile<Type>::MappedFile
+(
+    const MappedFile<Type>& ut
+)
+:
+    PatchFunction1<Type>(ut),
+    dictConstructed_(ut.dictConstructed_),
+    fieldTableName_(ut.fieldTableName_),
+    setAverage_(ut.setAverage_),
+    perturb_(ut.perturb_),
+    pointsName_(ut.pointsName_),
+    mapMethod_(ut.mapMethod_),
+    mapperPtr_(ut.mapperPtr_.clone()),
+    sampleTimes_(ut.sampleTimes_),
+    startSampleTime_(ut.startSampleTime_),
+    startSampledValues_(ut.startSampledValues_),
+    startAverage_(ut.startAverage_),
+    endSampleTime_(ut.endSampleTime_),
+    endSampledValues_(ut.endSampledValues_),
+    endAverage_(ut.endAverage_),
+    offset_(ut.offset_.clone())
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::MappedFile<Type>::MappedFile
+(
+    const MappedFile<Type>& ut,
+    const polyPatch& pp
+)
+:
+    PatchFunction1<Type>(ut, pp),
+    dictConstructed_(ut.dictConstructed_),
+    fieldTableName_(ut.fieldTableName_),
+    setAverage_(ut.setAverage_),
+    perturb_(ut.perturb_),
+    pointsName_(ut.pointsName_),
+    mapMethod_(ut.mapMethod_),
+    mapperPtr_(ut.mapperPtr_.clone()),
+    sampleTimes_(ut.sampleTimes_),
+    startSampleTime_(ut.startSampleTime_),
+    startSampledValues_(ut.startSampledValues_),
+    startAverage_(ut.startAverage_),
+    endSampleTime_(ut.endSampleTime_),
+    endSampledValues_(ut.endSampledValues_),
+    endAverage_(ut.endAverage_),
+    offset_(ut.offset_.clone())
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedFile<Type>::autoMap
+(
+    const FieldMapper& mapper
+)
+{
+    PatchFunction1<Type>::autoMap(mapper);
+
+    if (startSampledValues_.size())
+    {
+        startSampledValues_.autoMap(mapper);
+        endSampledValues_.autoMap(mapper);
+    }
+    // Clear interpolator
+    mapperPtr_.clear();
+    startSampleTime_ = -1;
+    endSampleTime_ = -1;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedFile<Type>::rmap
+(
+    const PatchFunction1<Type>& pf1,
+    const labelList& addr
+)
+{
+    PatchFunction1<Type>::rmap(pf1, addr);
+
+    const PatchFunction1Types::MappedFile<Type>& tiptf =
+        refCast<const PatchFunction1Types::MappedFile<Type>>(pf1);
+
+    startSampledValues_.rmap(tiptf.startSampledValues_, addr);
+    endSampledValues_.rmap(tiptf.endSampledValues_, addr);
+
+    // Clear interpolator
+    mapperPtr_.clear();
+    startSampleTime_ = -1;
+    endSampleTime_ = -1;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedFile<Type>::checkTable
+(
+    const scalar t
+) const
+{
+    const polyMesh& mesh = this->patch_.boundaryMesh().mesh();
+
+    // Initialise
+    if (mapperPtr_.empty())
+    {
+        // Reread values and interpolate
+        fileName samplePointsFile
+        (
+            mesh.time().path()
+           /mesh.time().caseConstant()
+           /"boundaryData"
+           /this->patch_.name()
+           /pointsName_
+        );
+
+        pointField samplePoints((IFstream(samplePointsFile)()));
+
+        DebugInfo
+            << "Read " << samplePoints.size() << " sample points from "
+            << samplePointsFile << endl;
+
+
+        // tbd: run-time selection
+        bool nearestOnly =
+        (
+           !mapMethod_.empty()
+         && mapMethod_ != "planarInterpolation"
+        );
+
+        // Allocate the interpolator
+        if (this->faceValues_)
+        {
+            mapperPtr_.reset
+            (
+                new pointToPointPlanarInterpolation
+                (
+                    samplePoints,
+                    this->localPosition(this->patch_.faceCentres()),
+                    perturb_,
+                    nearestOnly
+                )
+            );
+        }
+        else
+        {
+            mapperPtr_.reset
+            (
+                new pointToPointPlanarInterpolation
+                (
+                    samplePoints,
+                    this->localPosition(this->patch_.localPoints()),
+                    perturb_,
+                    nearestOnly
+                )
+            );
+        }
+
+
+
+        // Read the times for which data is available
+        const fileName samplePointsDir = samplePointsFile.path();
+        sampleTimes_ = Time::findTimes(samplePointsDir);
+
+        DebugInfo
+            << "In directory "
+            << samplePointsDir << " found times "
+            << pointToPointPlanarInterpolation::timeNames(sampleTimes_)
+            << endl;
+    }
+
+
+    // Find current time in sampleTimes
+    label lo = -1;
+    label hi = -1;
+
+    bool foundTime = mapperPtr_().findTime
+    (
+        sampleTimes_,
+        startSampleTime_,
+        t,  //mesh.time().value(),
+        lo,
+        hi
+    );
+
+    if (!foundTime)
+    {
+        FatalErrorInFunction
+            << "Cannot find starting sampling values for index "
+            << t << nl
+            << "Have sampling values for "
+            << pointToPointPlanarInterpolation::timeNames(sampleTimes_) << nl
+            << "In directory "
+            <<  mesh.time().constant()/"boundaryData"/this->patch_.name()
+            << "\n    on patch " << this->patch_.name()
+            << " of field " << fieldTableName_
+            << exit(FatalError);
+    }
+
+
+    // Update sampled data fields.
+
+    if (lo != startSampleTime_)
+    {
+        startSampleTime_ = lo;
+
+        if (startSampleTime_ == endSampleTime_)
+        {
+            // No need to reread since are end values
+            if (debug)
+            {
+                Pout<< "checkTable : Setting startValues to (already read) "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[startSampleTime_].name()
+                    << endl;
+            }
+            startSampledValues_ = endSampledValues_;
+            startAverage_ = endAverage_;
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "checkTable : Reading startValues from "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[lo].name()
+                    << endl;
+            }
+
+
+            // Reread values and interpolate
+            fileName valsFile
+            (
+                mesh.time().path()
+               /mesh.time().caseConstant()
+               /"boundaryData"
+               /this->patch_.name()
+               /sampleTimes_[startSampleTime_].name()
+               /fieldTableName_
+            );
+
+            Field<Type> vals;
+
+            if (setAverage_)
+            {
+                AverageField<Type> avals((IFstream(valsFile)()));
+                vals = avals;
+                startAverage_ = avals.average();
+            }
+            else
+            {
+                IFstream(valsFile)() >> vals;
+            }
+
+            if (vals.size() != mapperPtr_().sourceSize())
+            {
+                FatalErrorInFunction
+                    << "Number of values (" << vals.size()
+                    << ") differs from the number of points ("
+                    <<  mapperPtr_().sourceSize()
+                    << ") in file " << valsFile << exit(FatalError);
+            }
+
+            startSampledValues_ = mapperPtr_().interpolate(vals);
+        }
+    }
+
+    if (hi != endSampleTime_)
+    {
+        endSampleTime_ = hi;
+
+        if (endSampleTime_ == -1)
+        {
+            // endTime no longer valid. Might as well clear endValues.
+            if (debug)
+            {
+                Pout<< "checkTable : Clearing endValues" << endl;
+            }
+            endSampledValues_.clear();
+        }
+        else
+        {
+            if (debug)
+            {
+                Pout<< "checkTable : Reading endValues from "
+                    << "boundaryData"
+                      /this->patch_.name()
+                      /sampleTimes_[endSampleTime_].name()
+                    << endl;
+            }
+
+            // Reread values and interpolate
+            fileName valsFile
+            (
+                mesh.time().path()
+               /mesh.time().caseConstant()
+               /"boundaryData"
+               /this->patch_.name()
+               /sampleTimes_[endSampleTime_].name()
+               /fieldTableName_
+            );
+
+            Field<Type> vals;
+
+            if (setAverage_)
+            {
+                AverageField<Type> avals((IFstream(valsFile)()));
+                vals = avals;
+                endAverage_ = avals.average();
+            }
+            else
+            {
+                IFstream(valsFile)() >> vals;
+            }
+
+            if (vals.size() != mapperPtr_().sourceSize())
+            {
+                FatalErrorInFunction
+                    << "Number of values (" << vals.size()
+                    << ") differs from the number of points ("
+                    <<  mapperPtr_().sourceSize()
+                    << ") in file " << valsFile << exit(FatalError);
+            }
+
+            endSampledValues_ = mapperPtr_().interpolate(vals);
+        }
+    }
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::MappedFile<Type>::value
+(
+    const scalar x
+) const
+{
+    checkTable(x);
+
+    auto tfld = tmp<Field<Type>>::New(startSampledValues_.size());
+    Field<Type>& fld = tfld.ref();
+    Type wantedAverage;
+
+    if (endSampleTime_ == -1)
+    {
+        // Only start value
+        if (debug)
+        {
+            Pout<< "MappedFile<Type>::value : Sampled, non-interpolated values"
+                << " from start time:"
+                << sampleTimes_[startSampleTime_].name() << nl;
+        }
+
+        fld = startSampledValues_;
+        wantedAverage = startAverage_;
+    }
+    else
+    {
+        scalar start = sampleTimes_[startSampleTime_].value();
+        scalar end = sampleTimes_[endSampleTime_].value();
+
+        scalar s = (x - start)/(end - start);
+
+        if (debug)
+        {
+            Pout<< "MappedFile<Type>::value : Sampled, interpolated values"
+                << " between start time:"
+                << sampleTimes_[startSampleTime_].name()
+                << " and end time:" << sampleTimes_[endSampleTime_].name()
+                << " with weight:" << s << endl;
+        }
+
+        fld = ((1 - s)*startSampledValues_ + s*endSampledValues_);
+        wantedAverage = (1 - s)*startAverage_ + s*endAverage_;
+    }
+
+    // Enforce average. Either by scaling (if scaling factor > 0.5) or by
+    // offsetting.
+    if (setAverage_)
+    {
+        Type averagePsi;
+        if (this->faceValues_)
+        {
+            const scalarField magSf(mag(this->patch_.faceAreas()));
+            averagePsi = gSum(magSf*fld)/gSum(magSf);
+        }
+        else
+        {
+            averagePsi = gAverage(fld);
+        }
+
+        if (debug)
+        {
+            Pout<< "MappedFile<Type>::value :"
+                << " actual average:" << averagePsi
+                << " wanted average:" << wantedAverage
+                << endl;
+        }
+
+        if (mag(averagePsi) < VSMALL)
+        {
+            // Field too small to scale. Offset instead.
+            const Type offset = wantedAverage - averagePsi;
+            if (debug)
+            {
+                Pout<< "MappedFile<Type>::value :"
+                    << " offsetting with:" << offset << endl;
+            }
+            fld += offset;
+        }
+        else
+        {
+            const scalar scale = mag(wantedAverage)/mag(averagePsi);
+
+            if (debug)
+            {
+                Pout<< "MappedFile<Type>::value :"
+                    << " scaling with:" << scale << endl;
+            }
+            fld *= scale;
+        }
+    }
+
+    // Apply offset to mapped values
+    if (offset_.valid())
+    {
+        fld += offset_->value(x);
+    }
+
+    if (debug)
+    {
+        Pout<< "MappedFile<Type>::value : set fixedValue to min:" << gMin(fld)
+            << " max:" << gMax(fld)
+            << " avg:" << gAverage(fld) << endl;
+    }
+
+    return this->transform(tfld);
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::MappedFile<Type>::integrate
+(
+    const scalar x1,
+    const scalar x2
+) const
+{
+    NotImplemented;
+    return nullptr;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::MappedFile<Type>::writeData
+(
+    Ostream& os
+) const
+{
+    PatchFunction1<Type>::writeData(os);
+
+    // Check if field name explicitly provided (e.g. through timeVaryingMapped
+    // bc)
+    if (dictConstructed_)
+    {
+        os.writeKeyword(this->name()) << type();
+        os  << token::END_STATEMENT << nl;
+
+        os.writeEntryIfDifferent
+        (
+            "fieldTable",
+            this->name(),
+            fieldTableName_
+        );
+    }
+
+    if (setAverage_)
+    {
+        os.writeEntry("setAverage", setAverage_);
+    }
+
+    os.writeEntryIfDifferent<scalar>("perturb", 1e-5, perturb_);
+
+    os.writeEntryIfDifferent<word>("points", "points", pointsName_);
+
+    os.writeEntryIfDifferent<word>
+    (
+        "mapMethod",
+        "planarInterpolation",
+        mapMethod_
+    );
+
+    if (offset_.valid())
+    {
+        offset_->writeData(os);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/MappedFile/MappedFile.H b/src/meshTools/PatchFunction1/MappedFile/MappedFile.H
new file mode 100644
index 00000000000..89840c2a63d
--- /dev/null
+++ b/src/meshTools/PatchFunction1/MappedFile/MappedFile.H
@@ -0,0 +1,223 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Class
+    Foam::PatchFunction1Types::MappedFile
+
+Description
+
+SourceFiles
+    MappedFile.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PatchFunction1Types_MappedFile_H
+#define PatchFunction1Types_MappedFile_H
+
+#include "PatchFunction1.H"
+#include "pointToPointPlanarInterpolation.H"
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace PatchFunction1Types
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class MappedFile Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class MappedFile
+:
+    public PatchFunction1<Type>
+{
+    // Private data
+
+        //- Whether constructed from dictionary
+        const bool dictConstructed_;
+
+        //- Name of the field data table, defaults to the name of the field
+        word fieldTableName_;
+
+        //- If true adjust the mapped field to maintain average value
+        Switch setAverage_;
+
+        //- Fraction of perturbation (fraction of bounding box) to add
+        scalar perturb_;
+
+        //- Name of points file; default = "points"
+        word pointsName_;
+
+        //- Interpolation scheme to use
+        word mapMethod_;
+
+        //- 2D interpolation (for 'planarInterpolation' mapMethod)
+        mutable autoPtr<pointToPointPlanarInterpolation> mapperPtr_;
+
+        //- List of boundaryData time directories
+        mutable instantList sampleTimes_;
+
+        //- Current starting index in sampleTimes
+        mutable label startSampleTime_;
+
+        //- Interpolated values from startSampleTime
+        mutable Field<Type> startSampledValues_;
+
+        //- If setAverage: starting average value
+        mutable Type startAverage_;
+
+        //- Current end index in sampleTimes
+        mutable label endSampleTime_;
+
+        //- Interpolated values from endSampleTime
+        mutable Field<Type> endSampledValues_;
+
+        //- If setAverage: end average value
+        mutable Type endAverage_;
+
+        //- Time varying offset values to interpolated data
+        autoPtr<Function1<Type>> offset_;
+
+
+    // Private Member Functions
+
+        void checkTable(const scalar t) const;
+
+        //- No copy assignment
+        void operator=(const MappedFile<Type>&) = delete;
+
+
+public:
+
+    // Runtime type information
+    TypeName("mappedFile");
+
+
+    // Constructors
+
+        //- Construct from entry name and dictionary
+        MappedFile
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const bool faceValues = true
+        );
+
+        //- Construct from entry name and dictionary
+        MappedFile
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const word& fieldTableName,
+            const bool faceValues
+        );
+
+        //- Copy constructor
+        explicit MappedFile(const MappedFile<Type>& ut);
+
+        //- Copy constructor setting patch
+        explicit MappedFile
+        (
+            const MappedFile<Type>& ut,
+            const polyPatch& pp
+        );
+
+        //- Construct and return a clone
+        virtual tmp<PatchFunction1<Type>> clone() const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new MappedFile<Type>(*this)
+            );
+        }
+
+        //- Construct and return a clone setting patch
+        virtual tmp<PatchFunction1<Type>> clone(const polyPatch& pp) const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new MappedFile<Type>(*this, pp)
+            );
+        }
+
+
+    //- Destructor
+    virtual ~MappedFile() = default;
+
+
+    // Member Functions
+
+        // Evaluation
+
+            //- Return MappedFile value
+            virtual tmp<Field<Type>> value(const scalar) const;
+
+            //- Integrate between two values
+            virtual tmp<Field<Type>> integrate
+            (
+                const scalar x1,
+                const scalar x2
+            ) const;
+
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const FieldMapper& mapper);
+
+            //- Reverse map the given PatchFunction1 onto this PatchFunction1
+            virtual void rmap
+            (
+                const PatchFunction1<Type>& pf1,
+                const labelList& addr
+            );
+
+
+        // I-O
+
+            //- Write in dictionary format
+            virtual void writeData(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace PatchFunction1Types
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "MappedFile.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/PatchFunction1.C b/src/meshTools/PatchFunction1/PatchFunction1.C
new file mode 100644
index 00000000000..2c41e53b905
--- /dev/null
+++ b/src/meshTools/PatchFunction1/PatchFunction1.C
@@ -0,0 +1,232 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "PatchFunction1.H"
+#include "Time.H"
+#include "polyMesh.H"
+
+// * * * * * * * * * * * * * * * * Constructor * * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::PatchFunction1<Type>::PatchFunction1
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const bool faceValues
+)
+:
+    refCount(),
+    name_(entryName),
+    patch_(pp),
+    faceValues_(faceValues),
+    coordSys_()
+{}
+
+
+template<class Type>
+Foam::PatchFunction1<Type>::PatchFunction1
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const bool faceValues
+)
+:
+    refCount(),
+    name_(entryName),
+    patch_(pp),
+    faceValues_(faceValues),
+    coordSys_(pp.boundaryMesh().mesh().thisDb(), dict)
+{}
+
+
+template<class Type>
+Foam::PatchFunction1<Type>::PatchFunction1(const PatchFunction1<Type>& pf1)
+:
+    refCount(),
+    name_(pf1.name_),
+    patch_(pf1.patch_),
+    faceValues_(pf1.faceValues_),
+    coordSys_(pf1.coordSys_)
+{}
+
+
+template<class Type>
+Foam::PatchFunction1<Type>::PatchFunction1
+(
+    const PatchFunction1<Type>& pf1,
+    const polyPatch& pp
+)
+:
+    refCount(),
+    name_(pf1.name_),
+    patch_(pp),
+    faceValues_(pf1.faceValues_),
+    coordSys_(pf1.coordSys_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+const Foam::word& Foam::PatchFunction1<Type>::name() const
+{
+    return name_;
+}
+
+
+template<class Type>
+void Foam::PatchFunction1<Type>::convertTimeBase(const Time&)
+{}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::PatchFunction1<Type>::value
+(
+    const scalar x
+) const
+{
+    NotImplemented;
+
+    return Field<Type>();
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::PatchFunction1<Type>::integrate
+(
+    const scalar x1,
+    const scalar x2
+) const
+{
+    NotImplemented;
+
+    return Field<Type>();
+}
+
+
+template<class Type>
+Foam::tmp<Foam::pointField>
+Foam::PatchFunction1<Type>::localPosition(const pointField& globalPos) const
+{
+    if (!coordSys_.active())
+    {
+        return globalPos;
+    }
+    else
+    {
+        return coordSys_.coordSys()().localPosition(globalPos);
+    }
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::PatchFunction1<Type>::transform
+(
+    const tmp<Field<Type>>& tfld
+) const
+{
+    if (!coordSys_.active())
+    {
+        return tfld;
+    }
+
+    const pointField& fc =
+    (
+        faceValues_
+      ? this->patch_.faceCentres()
+      : this->patch_.localPoints()
+    );
+    auto tresult = this->coordSys_.transform(fc, tfld());
+    tfld.clear();
+    return tresult;
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::PatchFunction1<Type>::transform
+(
+    const Field<Type>& fld
+) const
+{
+    if (!coordSys_.active())
+    {
+        return fld;
+    }
+
+    const pointField& fc =
+    (
+        faceValues_
+      ? this->patch_.faceCentres()
+      : this->patch_.localPoints()
+    );
+    return this->coordSys_.transform(fc, fld);
+}
+
+
+template<class Type>
+void Foam::PatchFunction1<Type>::autoMap(const FieldMapper& mapper)
+{}
+
+
+template<class Type>
+void Foam::PatchFunction1<Type>::rmap
+(
+    const PatchFunction1<Type>& pf1,
+    const labelList& addr
+)
+{}
+
+
+template<class Type>
+void Foam::PatchFunction1<Type>::writeData(Ostream& os) const
+{
+    coordSys_.writeEntry(os);
+
+    // Leave type() output up to derived type. This is so 'Constant'&Uniform
+    // can do backwards compatibility.
+    //os.writeKeyword(name_) << type();
+}
+
+
+// * * * * * * * * * * * * * *  IOStream operators * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const PatchFunction1<Type>& pf1
+)
+{
+    os.check(FUNCTION_NAME);
+
+    os  << pf1.name_;
+    pf1.writeData(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/PatchFunction1.H b/src/meshTools/PatchFunction1/PatchFunction1.H
new file mode 100644
index 00000000000..a1cfaa79019
--- /dev/null
+++ b/src/meshTools/PatchFunction1/PatchFunction1.H
@@ -0,0 +1,280 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Class
+    Foam::PatchFunction1
+
+Description
+    Top level data entry class for use in dictionaries. Provides a mechanism
+    to specify a variable as a certain type, e.g. constant or time varying, and
+    provide functions to return the (interpolated) value, and integral between
+    limits.
+
+    Extends the Function1 class by adding autoMap and rMap functions
+
+SourceFiles
+    PatchFunction1.C
+    PatchFunction1New.C
+
+SeeAlso
+    Foam::Function1
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PatchFunction1_H
+#define PatchFunction1_H
+
+#include "dictionary.H"
+#include "Field.H"
+#include "polyPatch.H"
+#include "coordinateScaling.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declarations
+class Time;
+
+// Forward declaration of friend functions and operators
+template<class Type>
+class PatchFunction1;
+
+template<class Type>
+Ostream& operator<<
+(
+    Ostream&,
+    const PatchFunction1<Type>&
+);
+
+/*---------------------------------------------------------------------------*\
+                       Class PatchFunction1 Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class PatchFunction1
+:
+    public refCount
+{
+    // Private Member Functions
+
+        //- No copy assignment
+        void operator=(const PatchFunction1<Type>&) = delete;
+
+
+protected:
+
+    // Protected data
+
+        //- Name of entry
+        const word name_;
+
+        //- Reference to the patch
+        const polyPatch& patch_;
+
+        //- Whether to generate face or point values on patch
+        const bool faceValues_;
+
+        //- Optional local co-ordinate system and scaling
+        coordinateScaling<Type> coordSys_;
+
+
+public:
+
+    typedef Field<Type> returnType;
+
+    //- Runtime type information
+    TypeName("PatchFunction1")
+
+    //- Declare runtime constructor selection table
+    declareRunTimeSelectionTable
+    (
+        autoPtr,
+        PatchFunction1,
+        dictionary,
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const bool faceValues
+        ),
+        (pp, entryName, dict, faceValues)
+    );
+
+
+    // Constructors
+
+        //- Construct from polyPatch and entry name
+        PatchFunction1
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const bool faceValues = true
+        );
+
+        //- Construct from polyPatch, dictionary and entry name
+        PatchFunction1
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const bool faceValues = true
+        );
+
+        //- Copy constructor
+        explicit PatchFunction1(const PatchFunction1<Type>& pf1);
+
+        //- Copy constructor setting patch
+        explicit PatchFunction1
+        (
+            const PatchFunction1<Type>& pf1,
+            const polyPatch& pp
+        );
+
+        //- Construct and return a clone
+        virtual tmp<PatchFunction1<Type>> clone() const = 0;
+
+        //- Construct and return a clone setting patch
+        virtual tmp<PatchFunction1<Type>> clone(const polyPatch& pp) const = 0;
+
+
+    //- Selector
+    static autoPtr<PatchFunction1<Type>> New
+    (
+        const polyPatch& pp,
+        const word& entryName,
+        const dictionary& dict,
+        const bool faceValues = true
+    );
+
+
+    //- Destructor
+    virtual ~PatchFunction1() = default;
+
+
+    // Member Functions
+
+        // Access
+
+            //- Return the name of the entry
+            const word& name() const;
+
+
+        // Manipulation
+
+            //- Convert time
+            virtual void convertTimeBase(const Time& t);
+
+
+        // Evaluation
+
+            //- Return value as a function of (scalar) independent variable
+            virtual tmp<Field<Type>> value(const scalar x) const;
+
+            //- Integrate between two (scalar) values
+            virtual tmp<Field<Type>> integrate
+            (
+                const scalar x1,
+                const scalar x2
+            ) const;
+
+            //- Helper: optionally convert coordinates to local coordinates
+            virtual tmp<pointField> localPosition
+            (
+                const pointField& globalPos
+            ) const;
+
+            //- Apply optional transformation
+            virtual tmp<Field<Type>> transform(const Field<Type>& fld) const;
+
+            //- Apply optional transformation
+            virtual tmp<Field<Type>> transform
+            (
+                const tmp<Field<Type>>& tfld
+            ) const;
+
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const FieldMapper& mapper);
+
+            //- Reverse map the given PatchFunction1 onto this PatchFunction1
+            virtual void rmap
+            (
+                const PatchFunction1<Type>& pf1,
+                const labelList& addr
+            );
+
+
+        // I/O
+
+            //- Ostream Operator
+            friend Ostream& operator<< <Type>
+            (
+                Ostream& os,
+                const PatchFunction1<Type>& func
+            );
+
+            //- Write in dictionary format
+            virtual void writeData(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#define makePatchFunction1(Type)                                               \
+                                                                               \
+    defineNamedTemplateTypeNameAndDebug(PatchFunction1<Type>, 0);              \
+                                                                               \
+    defineTemplateRunTimeSelectionTable                                        \
+    (                                                                          \
+        PatchFunction1<Type>,                                                  \
+        dictionary                                                             \
+    );
+
+#define makePatchFunction1Type(SS, Type)                                       \
+                                                                               \
+    defineNamedTemplateTypeNameAndDebug(PatchFunction1Types::SS<Type>, 0);     \
+                                                                               \
+    PatchFunction1<Type>::adddictionaryConstructorToTable                      \
+        <PatchFunction1Types::SS<Type>>                                        \
+        add##SS##Type##ConstructorToTable_;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "PatchFunction1.C"
+    #include "PatchFunction1New.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/PatchFunction1New.C b/src/meshTools/PatchFunction1/PatchFunction1New.C
new file mode 100644
index 00000000000..a77f23b1c2a
--- /dev/null
+++ b/src/meshTools/PatchFunction1/PatchFunction1New.C
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "ConstantField.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::autoPtr<Foam::PatchFunction1<Type>> Foam::PatchFunction1<Type>::New
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const bool faceValues
+)
+{
+    if (dict.isDict(entryName))
+    {
+        const dictionary& coeffsDict(dict.subDict(entryName));
+
+        const word modelType(coeffsDict.lookup("type"));
+
+        auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
+
+        if (!cstrIter.found())
+        {
+            FatalIOErrorInFunction(coeffsDict)
+                << "Unknown PatchFunction1 type "
+                << modelType << " for PatchFunction1 "
+                << entryName << nl << nl
+                << "Valid PatchFunction1 types :" << nl
+                << dictionaryConstructorTablePtr_->sortedToc() << nl
+                << exit(FatalIOError);
+        }
+
+        return cstrIter()(pp, entryName, coeffsDict, faceValues);
+    }
+    else
+    {
+        ITstream& is = dict.lookup(entryName, false);
+
+        token firstToken(is);
+
+        if (!firstToken.isWord())
+        {
+            // Backwards-compatibility for reading straight fields
+            is.putBack(firstToken);
+            const Field<Type> value(pp.size(), pTraits<Type>(is));
+
+            return autoPtr<PatchFunction1<Type>>
+            (
+                new PatchFunction1Types::ConstantField<Type>
+                (
+                    pp,
+                    entryName,
+                    value,
+                    dict,
+                    faceValues
+                )
+            );
+        }
+
+        const word modelType = firstToken.wordToken();
+
+        // Check to see if this looks like a normal field entry
+        if (modelType == "uniform" || modelType == "nonuniform")
+        {
+            return autoPtr<PatchFunction1<Type>>
+            (
+                new PatchFunction1Types::ConstantField<Type>
+                (
+                    pp,
+                    entryName,
+                    dict
+                )
+            );
+        }
+
+        auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
+
+        if (!cstrIter.found())
+        {
+            FatalIOErrorInFunction(dict)
+                << "Unknown PatchFunction1 type "
+                << modelType << " for PatchFunction1 "
+                << entryName << nl << nl
+                << "Valid PatchFunction1 types :" << nl
+                << dictionaryConstructorTablePtr_->sortedToc() << nl
+                << exit(FatalIOError);
+        }
+
+        return cstrIter()
+        (
+            pp,
+            entryName,
+            dict.found(entryName + "Coeffs")
+          ? dict.subDict(entryName + "Coeffs")
+          : dict,
+            faceValues
+        );
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.C b/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.C
new file mode 100644
index 00000000000..fa7161f35ce
--- /dev/null
+++ b/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.C
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "UniformValueField.H"
+#include "polyMesh.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::PatchFunction1Types::UniformValueField<Type>::UniformValueField
+(
+    const polyPatch& pp,
+    const word& entryName,
+    const dictionary& dict,
+    const bool faceValues
+)
+:
+    PatchFunction1<Type>(pp, entryName, dict, faceValues),
+    uniformValuePtr_(Function1<Type>::New(entryName, dict))
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::UniformValueField<Type>::UniformValueField
+(
+    const UniformValueField<Type>& ut
+)
+:
+    PatchFunction1<Type>(ut),
+    uniformValuePtr_(ut.uniformValuePtr_.clone())
+{}
+
+
+template<class Type>
+Foam::PatchFunction1Types::UniformValueField<Type>::UniformValueField
+(
+    const UniformValueField<Type>& ut,
+    const polyPatch& pp
+)
+:
+    PatchFunction1<Type>(ut, pp),
+    uniformValuePtr_(ut.uniformValuePtr_.clone())
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::PatchFunction1Types::UniformValueField<Type>::autoMap
+(
+    const FieldMapper& mapper
+)
+{}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::UniformValueField<Type>::rmap
+(
+    const PatchFunction1<Type>& pf1,
+    const labelList& addr
+)
+{}
+
+
+template<class Type>
+void Foam::PatchFunction1Types::UniformValueField<Type>::writeData
+(
+    Ostream& os
+) const
+{
+    PatchFunction1<Type>::writeData(os);
+    //os  << token::END_STATEMENT << nl;
+    uniformValuePtr_->writeData(os);
+    //os  << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.H b/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.H
new file mode 100644
index 00000000000..4b021d61d95
--- /dev/null
+++ b/src/meshTools/PatchFunction1/UniformValueField/UniformValueField.H
@@ -0,0 +1,186 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Class
+    Foam::PatchFunction1Types::UniformValueField
+
+Description
+    Templated function that returns a uniform field based on a run-time
+    selectable Function1 entry.
+
+    Usage - for entry \<entryName\> returning the value <value>:
+    \verbatim
+        <entryName>    uniformValue
+    \endverbatim
+
+SourceFiles
+    UniformValueField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PatchFunction1Types_UniformValueField_H
+#define PatchFunction1Types_UniformValueField_H
+
+#include "PatchFunction1.H"
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace PatchFunction1Types
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class UniformValueField Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class UniformValueField
+:
+    public PatchFunction1<Type>
+{
+    // Private data
+
+        //- Source of uniform values (in local co-ordinate system)
+        autoPtr<Foam::Function1<Type>> uniformValuePtr_;
+
+
+    // Private Member Functions
+
+        //- No copy assignment
+        void operator=(const UniformValueField<Type>&) = delete;
+
+
+public:
+
+    // Runtime type information
+    TypeName("uniformValue");
+
+
+    // Constructors
+
+//        //- Construct from components
+//        UniformValueField
+//        (
+//            const polyPatch& pp,
+//            const word& entryName,
+//            const Field<Type>& value,
+//            const bool faceValues = true
+//        );
+
+        //- Construct from entry name and dictionary
+        UniformValueField
+        (
+            const polyPatch& pp,
+            const word& entryName,
+            const dictionary& dict,
+            const bool faceValues = true
+        );
+
+        //- Copy constructor
+        explicit UniformValueField(const UniformValueField<Type>& ut);
+
+        //- Copy constructor setting patch
+        explicit UniformValueField
+        (
+            const UniformValueField<Type>& ut,
+            const polyPatch& pp
+        );
+
+        //- Construct and return a clone
+        virtual tmp<PatchFunction1<Type>> clone() const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new UniformValueField<Type>(*this)
+            );
+        }
+
+        //- Construct and return a clone setting patch
+        virtual tmp<PatchFunction1<Type>> clone(const polyPatch& pp) const
+        {
+            return tmp<PatchFunction1<Type>>
+            (
+                new UniformValueField<Type>(*this, pp)
+            );
+        }
+
+
+    //- Destructor
+    virtual ~UniformValueField() = default;
+
+
+    // Member Functions
+
+        // Evaluation
+
+            //- Return UniformValueField value
+            virtual inline tmp<Field<Type>> value(const scalar) const;
+
+            //- Integrate between two values
+            virtual inline tmp<Field<Type>> integrate
+            (
+                const scalar x1,
+                const scalar x2
+            ) const;
+
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const FieldMapper& mapper);
+
+            //- Reverse map the given PatchFunction1 onto this PatchFunction1
+            virtual void rmap
+            (
+                const PatchFunction1<Type>& pf1,
+                const labelList& addr
+            );
+
+
+        // I-O
+
+            //- Write in dictionary format
+            virtual void writeData(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace PatchFunction1Types
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "UniformValueFieldI.H"
+
+#ifdef NoRepository
+    #include "UniformValueField.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/UniformValueField/UniformValueFieldI.H b/src/meshTools/PatchFunction1/UniformValueField/UniformValueFieldI.H
new file mode 100644
index 00000000000..480ea6d8893
--- /dev/null
+++ b/src/meshTools/PatchFunction1/UniformValueField/UniformValueFieldI.H
@@ -0,0 +1,84 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "UniformValueField.H"
+#include "SubField.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::UniformValueField<Type>::value
+(
+    const scalar x
+) const
+{
+    label sz =
+    (
+        this->faceValues_
+      ? this->patch_.size()
+      : this->patch_.nPoints()
+    );
+
+    tmp<Field<Type>> tfld
+    (
+        tmp<Field<Type>>::New
+        (
+            sz,
+            uniformValuePtr_->value(x)
+        )
+    );
+    return this->transform(tfld);
+}
+
+
+template<class Type>
+inline Foam::tmp<Foam::Field<Type>>
+Foam::PatchFunction1Types::UniformValueField<Type>::integrate
+(
+    const scalar x1,
+    const scalar x2
+) const
+{
+    label sz =
+    (
+        this->faceValues_
+      ? this->patch_.size()
+      : this->patch_.nPoints()
+    );
+
+    tmp<Field<Type>> tfld
+    (
+        tmp<Field<Type>>::New
+        (
+            sz,
+            uniformValuePtr_->integrate(x1, x2)
+        )
+    );
+    return this->transform(tfld);
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/coordinateLabelScaling.C b/src/meshTools/PatchFunction1/coordinateLabelScaling.C
new file mode 100644
index 00000000000..dfc10e5935c
--- /dev/null
+++ b/src/meshTools/PatchFunction1/coordinateLabelScaling.C
@@ -0,0 +1,42 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "coordinateScaling.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<>
+Foam::tmp<Foam::Field<Foam::label>>
+Foam::coordinateScaling<Foam::label>::transform
+(
+    const pointField& pos,
+    const Field<label>& local
+) const
+{
+    return local;
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/coordinateScaling.C b/src/meshTools/PatchFunction1/coordinateScaling.C
new file mode 100644
index 00000000000..11e9e89d321
--- /dev/null
+++ b/src/meshTools/PatchFunction1/coordinateScaling.C
@@ -0,0 +1,144 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2018 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::coordinateScaling<Type>::coordinateScaling()
+:
+    active_(false)
+{}
+
+
+template<class Type>
+Foam::coordinateScaling<Type>::coordinateScaling
+(
+    const objectRegistry& obr,
+    const dictionary& dict
+)
+:
+    coordSys_
+    (
+        dict.found(coordinateSystem::typeName_())
+      ? coordinateSystem::New(obr, dict)
+      : nullptr
+    ),
+    scale_(3),
+    active_(coordSys_.valid())
+{
+    for (direction dir = 0; dir < vector::nComponents; dir++)
+    {
+        const word key("scale" + Foam::name(dir+1));
+
+        if (dict.found(key))
+        {
+            scale_.set(dir, Function1<Type>::New(key, dict));
+            active_ = true;
+        }
+    }
+}
+
+
+template<class Type>
+Foam::coordinateScaling<Type>::coordinateScaling(const coordinateScaling& cs)
+:
+    coordSys_(cs.coordSys_.clone()),
+    scale_(cs.scale_),
+    active_(cs.active_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::coordinateScaling<Type>::~coordinateScaling()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>> Foam::coordinateScaling<Type>::transform
+(
+    const pointField& pos,
+    const Field<Type>& p0
+) const
+{
+    tmp<Field<Type>> tfld(new Field<Type>(p0));
+    Field<Type>& fld = tfld.ref();
+
+    if (coordSys_.valid())
+    {
+        const vectorField local(coordSys_->localPosition(pos));
+        for (direction dir = 0; dir < vector::nComponents; dir++)
+        {
+            if (scale_.set(dir))
+            {
+                fld = cmptMultiply
+                (
+                    fld,
+                    scale_[dir].value(local.component(dir))
+                );
+            }
+        }
+
+        return coordSys_->transform(pos, fld);
+    }
+    else
+    {
+        for (direction dir = 0; dir < vector::nComponents; dir++)
+        {
+            if (scale_.set(dir))
+            {
+                fld = cmptMultiply
+                (
+                    fld,
+                    scale_[dir].value(pos.component(dir))
+                );
+            }
+        }
+        return fld;
+    }
+}
+
+
+template<class Type>
+void Foam::coordinateScaling<Type>::writeEntry(Ostream& os) const
+{
+    if (coordSys_.valid())
+    {
+        coordSys_->writeEntry(coordinateSystem::typeName_(), os);
+    }
+    forAll(scale_, dir)
+    {
+        if (scale_.set(dir))
+        {
+            scale_[dir].writeData(os);
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/coordinateScaling.H b/src/meshTools/PatchFunction1/coordinateScaling.H
new file mode 100644
index 00000000000..7fb897ffd42
--- /dev/null
+++ b/src/meshTools/PatchFunction1/coordinateScaling.H
@@ -0,0 +1,142 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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/>.
+
+Class
+    Foam::coordinateScaling
+
+Description
+    Helper class to wrap coordinate system and component-wise scaling
+
+See also
+    Foam::Function1Types
+
+SourceFiles
+    coordinateScaling.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef coordinateScaling_H
+#define coordinateScaling_H
+
+#include "coordinateSystem.H"
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class coordinateScaling Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class coordinateScaling
+{
+    // Private data
+
+        //- Local co-ordinate system
+        const autoPtr<coordinateSystem> coordSys_;
+
+        //- In local co-ordinate system component-wise scaling
+        PtrList<Function1<Type>> scale_;
+
+        //- Cached whether any scaling or coordinate system
+        bool active_;
+
+
+    // Private Member Functions
+
+        //- No copy assignment
+        void operator=(const coordinateScaling<Type>&) = delete;
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        coordinateScaling();
+
+        //- Construct from registry and dictionary
+        coordinateScaling
+        (
+            const objectRegistry&,
+            const dictionary&
+        );
+
+        //- Construct copy
+        coordinateScaling(const coordinateScaling&);
+
+
+    //- Destructor
+    virtual ~coordinateScaling();
+
+
+    // Member functions
+
+        //- Has any scaling or coordinate transformation
+        bool active() const
+        {
+            return active_;
+        }
+
+        //- Access to optional coordinate system
+        const autoPtr<coordinateSystem>& coordSys() const
+        {
+            return coordSys_;
+        }
+
+        //- Evaluate
+        virtual tmp<Field<Type>> transform
+        (
+            const pointField& pos,
+            const Field<Type>& local
+        ) const;
+
+        //- Write dictionary entry
+        virtual void writeEntry(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+template<>
+tmp<Field<label>> coordinateScaling<label>::transform
+(
+    const pointField& pos,
+    const Field<label>& local
+) const;
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "coordinateScaling.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/meshTools/PatchFunction1/makePatchFunction1s.C b/src/meshTools/PatchFunction1/makePatchFunction1s.C
new file mode 100644
index 00000000000..1b59d549fed
--- /dev/null
+++ b/src/meshTools/PatchFunction1/makePatchFunction1s.C
@@ -0,0 +1,166 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "PatchFunction1.H"
+#include "fieldTypes.H"
+#include "ConstantField.H"
+#include "UniformValueField.H"
+#include "MappedFile.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Table.H"
+
+#define makePatchFunction1s(Type)                                              \
+    makePatchFunction1(Type);                                                  \
+    makePatchFunction1Type(ConstantField, Type);                               \
+    makePatchFunction1Type(MappedFile, Type);                                 \
+    makePatchFunction1Type(UniformValueField, Type);
+
+#define addUniformValueFieldFunction1s(F1Type, Type)                           \
+    PatchFunction1<Type>::adddictionaryConstructorToTable                      \
+    <PatchFunction1Types::UniformValueField<Type>>                             \
+        add##F1Type##UniformValueField##Type##ConstructorToTable_(#F1Type);
+
+namespace Foam
+{
+    makePatchFunction1(label);
+    makePatchFunction1Type(ConstantField, label);
+
+    makePatchFunction1s(scalar);
+    makePatchFunction1s(vector);
+    makePatchFunction1s(sphericalTensor);
+    makePatchFunction1s(symmTensor);
+    makePatchFunction1s(tensor);
+
+
+    //- Option1 : add UniformFieldValue under the same name as Function1
+    //            See makeFunction1s.C. Note that we do not need
+    //            Constant & Uniform
+    addUniformValueFieldFunction1s(zero, scalar);
+    addUniformValueFieldFunction1s(zero, vector);
+    addUniformValueFieldFunction1s(zero, sphericalTensor);
+    addUniformValueFieldFunction1s(zero, symmTensor);
+    addUniformValueFieldFunction1s(zero, tensor);
+
+    addUniformValueFieldFunction1s(one, scalar);
+    addUniformValueFieldFunction1s(one, vector);
+    addUniformValueFieldFunction1s(one, sphericalTensor);
+    addUniformValueFieldFunction1s(one, symmTensor);
+    addUniformValueFieldFunction1s(one, tensor);
+
+    addUniformValueFieldFunction1s(polynomial, scalar);
+    addUniformValueFieldFunction1s(polynomial, vector);
+    addUniformValueFieldFunction1s(polynomial, sphericalTensor);
+    addUniformValueFieldFunction1s(polynomial, symmTensor);
+    addUniformValueFieldFunction1s(polynomial, tensor);
+
+    addUniformValueFieldFunction1s(sine, scalar);
+    addUniformValueFieldFunction1s(sine, vector);
+    addUniformValueFieldFunction1s(sine, sphericalTensor);
+    addUniformValueFieldFunction1s(sine, symmTensor);
+    addUniformValueFieldFunction1s(sine, tensor);
+
+    addUniformValueFieldFunction1s(square, scalar);
+    addUniformValueFieldFunction1s(square, vector);
+    addUniformValueFieldFunction1s(square, sphericalTensor);
+    addUniformValueFieldFunction1s(square, symmTensor);
+    addUniformValueFieldFunction1s(square, tensor);
+
+    addUniformValueFieldFunction1s(csvFile, scalar);
+    addUniformValueFieldFunction1s(csvFile, vector);
+    addUniformValueFieldFunction1s(csvFile, sphericalTensor);
+    addUniformValueFieldFunction1s(csvFile, symmTensor);
+    addUniformValueFieldFunction1s(csvFile, tensor);
+
+    addUniformValueFieldFunction1s(table, scalar);
+    addUniformValueFieldFunction1s(table, vector);
+    addUniformValueFieldFunction1s(table, sphericalTensor);
+    addUniformValueFieldFunction1s(table, symmTensor);
+    addUniformValueFieldFunction1s(table, tensor);
+
+    addUniformValueFieldFunction1s(tableFile, scalar);
+    addUniformValueFieldFunction1s(tableFile, vector);
+    addUniformValueFieldFunction1s(tableFile, sphericalTensor);
+    addUniformValueFieldFunction1s(tableFile, symmTensor);
+    addUniformValueFieldFunction1s(tableFile, tensor);
+
+    addUniformValueFieldFunction1s(scale, scalar);
+    addUniformValueFieldFunction1s(scale, vector);
+    addUniformValueFieldFunction1s(scale, sphericalTensor);
+    addUniformValueFieldFunction1s(scale, symmTensor);
+    addUniformValueFieldFunction1s(scale, tensor);
+
+
+    ////- Option2 : at static initialisation add all Function1 types.
+    ////  This does not work because we cannot guarantee that the Function1
+    ////  static initialisation has happened already.
+    //template<class Type>
+    //class addToUniform
+    //{
+    //public:
+    //    addToUniform()
+    //    {
+    //        // Get the Function1 table
+    //        typedef typename Function1<Type>::dictionaryConstructorTable
+    //            F1Type;
+    //        Function1<Type>::constructdictionaryConstructorTables();
+    //        const F1Type& F1Table =
+    //            *Function1<Type>::dictionaryConstructorTablePtr_;
+    //
+    //        // Get the PatchFunction1 table
+    //        typedef typename PatchFunction1<Type>::dictionaryConstructorTable
+    //            PF1Type;
+    //
+    //        PatchFunction1<Type>::constructdictionaryConstructorTables();
+    //        PF1Type& PF1Table =
+    //            *PatchFunction1<Type>::dictionaryConstructorTablePtr_;
+    //
+    //        // Get the UniformValueField constructor
+    //        auto cstrIter =
+    //            PatchFunction1<Type>::dictionaryConstructorTablePtr_->cfind
+    //            (
+    //                PatchFunction1Types::UniformValueField<Type>::typeName
+    //            );
+    //
+    //        // Add the UniformValueField under the Function1 name
+    //        forAllConstIter(typename F1Type, F1Table, iter)
+    //        {
+    //            //bool ok =
+    //            PF1Table.insert(iter.key(), cstrIter());
+    //            //if (!ok)
+    //            //{
+    //            //    std::cout<< "** problem" << std::endl;
+    //            //}
+    //        }
+    //    }
+    //};
+    //static const addToUniform<scalar> addScalar;
+    //static const addToUniform<vector> addVector;
+    //static const addToUniform<sphericalTensor> addSphericalTensor;
+    //static const addToUniform<symmTensor> addSymmTensor;
+    //static const addToUniform<tensor> addTensor;
+}
+
+
+// ************************************************************************* //
-- 
GitLab