diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files
index efcd5f0047..43a832506c 100644
--- a/src/finiteVolume/Make/files
+++ b/src/finiteVolume/Make/files
@@ -224,6 +224,9 @@ $(derivedFvPatchFields)/plenumPressure/plenumPressureFvPatchScalarField.C
$(derivedFvPatchFields)/interfaceCompression/interfaceCompressionFvPatchScalarField.C
$(derivedFvPatchFields)/swirlFanVelocity/swirlFanVelocityFvPatchField.C
+$(derivedFvPatchFields)/mappedField/Sampled/makeSampledPatchFunction1s.C
+
+
fvsPatchFields = fields/fvsPatchFields
$(fvsPatchFields)/fvsPatchField/fvsPatchFields.C
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C
new file mode 100644
index 0000000000..130337d0c8
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C
@@ -0,0 +1,353 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include "fvMesh.H"
+#include "volFields.H"
+#include "interpolationCell.H"
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+template
+Type Foam::PatchFunction1Types::Sampled::getAverage
+(
+ const dictionary& dict,
+ const bool mandatory
+)
+{
+ if (mandatory)
+ {
+ return dict.get("average");
+ }
+
+ return Zero;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+template
+Foam::PatchFunction1Types::Sampled::Sampled
+(
+ const polyPatch& pp,
+ const word& type,
+ const word& entryName,
+ const dictionary& dict,
+ const bool faceValues
+)
+:
+ PatchFunction1(pp, entryName, dict, faceValues),
+ mappedPatchBase(pp, dict),
+ fieldName_(dict.get("field")),
+ setAverage_(dict.lookupOrDefault("setAverage", false)),
+ average_(getAverage(dict, setAverage_)),
+ interpolationScheme_(interpolationCell::typeName)
+{
+ if (this->mode() == mappedPatchBase::NEARESTCELL)
+ {
+ dict.readEntry("interpolationScheme", interpolationScheme_);
+ }
+}
+
+
+template
+Foam::PatchFunction1Types::Sampled::Sampled
+(
+ const Sampled& ut
+)
+:
+ PatchFunction1(ut),
+ mappedPatchBase(ut),
+ fieldName_(ut.fieldName_),
+ setAverage_(ut.setAverage_),
+ average_(ut.average_),
+ interpolationScheme_(ut.interpolationScheme_)
+{}
+
+
+template
+Foam::PatchFunction1Types::Sampled::Sampled
+(
+ const Sampled& ut,
+ const polyPatch& pp
+)
+:
+ PatchFunction1(ut, pp),
+ mappedPatchBase(pp, ut),
+ fieldName_(ut.fieldName_),
+ setAverage_(ut.setAverage_),
+ average_(ut.average_),
+ interpolationScheme_(ut.interpolationScheme_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+template
+const Foam::GeometricField&
+Foam::PatchFunction1Types::Sampled::sampleField() const
+{
+ typedef GeometricField fieldType;
+
+ if (this->sameRegion())
+ {
+ const polyMesh& thisMesh =
+ this->mappedPatchBase::patch_.boundaryMesh().mesh();
+ return thisMesh.template lookupObject(fieldName_);
+ }
+ else
+ {
+ const fvMesh& nbrMesh = refCast(this->sampleMesh());
+ return nbrMesh.template lookupObject(fieldName_);
+ }
+}
+
+
+template
+bool Foam::PatchFunction1Types::Sampled::haveSampleField() const
+{
+ typedef GeometricField fieldType;
+
+ if (this->sameRegion())
+ {
+ const polyMesh& thisMesh =
+ this->mappedPatchBase::patch_.boundaryMesh().mesh();
+ return thisMesh.template foundObject(fieldName_);
+ }
+ else
+ {
+ const fvMesh& nbrMesh = refCast(this->sampleMesh());
+ return nbrMesh.template foundObject(fieldName_);
+ }
+}
+
+
+template
+Foam::tmp>
+Foam::PatchFunction1Types::Sampled::value
+(
+ const scalar x
+) const
+{
+ typedef GeometricField fieldType;
+
+ // Since we're inside initEvaluate/evaluate there might be processor
+ // comms underway. Change the tag we use.
+ int oldTag = UPstream::msgType();
+ UPstream::msgType() = oldTag + 1;
+
+ const fvMesh& thisMesh = refCast
+ (
+ this->mappedPatchBase::patch_.boundaryMesh().mesh()
+ );
+ const fvMesh& nbrMesh = refCast(this->sampleMesh());
+
+
+ // Result of obtaining remote values
+ auto tnewValues = tmp>::New();
+ auto& newValues = tnewValues.ref();
+
+ if (!haveSampleField())
+ {
+ // Restore tag
+ UPstream::msgType() = oldTag;
+ newValues.setSize(this->mappedPatchBase::patch_.size());
+ newValues = Zero;
+ return this->transform(tnewValues);
+ }
+
+ switch (this->mode())
+ {
+ case mappedPatchBase::NEARESTCELL:
+ {
+ const mapDistribute& distMap = this->map();
+
+ if (interpolationScheme_ != interpolationCell::typeName)
+ {
+ // Send back sample points to the processor that holds the cell
+ vectorField samples(this->samplePoints());
+ distMap.reverseDistribute
+ (
+ (
+ this->sameRegion()
+ ? thisMesh.nCells()
+ : nbrMesh.nCells()
+ ),
+ point::max,
+ samples
+ );
+
+ auto interpolator =
+ interpolation::New
+ (
+ interpolationScheme_,
+ sampleField()
+ );
+
+ const auto& interp = *interpolator;
+
+ newValues.setSize(samples.size(), pTraits::max);
+ forAll(samples, celli)
+ {
+ if (samples[celli] != point::max)
+ {
+ newValues[celli] = interp.interpolate
+ (
+ samples[celli],
+ celli
+ );
+ }
+ }
+ }
+ else
+ {
+ newValues = sampleField();
+ }
+ distMap.distribute(newValues);
+
+ break;
+ }
+ case mappedPatchBase::NEARESTPATCHFACE:
+ case mappedPatchBase::NEARESTPATCHFACEAMI:
+ {
+ const label nbrPatchID =
+ nbrMesh.boundaryMesh().findPatchID(this->samplePatch());
+
+ if (nbrPatchID < 0)
+ {
+ FatalErrorInFunction
+ << "Unable to find sample patch " << this->samplePatch()
+ << " in region " << this->sampleRegion()
+ << " for patch " << this->mappedPatchBase::patch_.name() << nl
+ << abort(FatalError);
+ }
+
+ const fieldType& nbrField = sampleField();
+
+ newValues = nbrField.boundaryField()[nbrPatchID];
+ this->distribute(newValues);
+
+ break;
+ }
+ case mappedPatchBase::NEARESTFACE:
+ {
+ Field allValues(nbrMesh.nFaces(), Zero);
+
+ const fieldType& nbrField = sampleField();
+
+ for (const fvPatchField& pf : nbrField.boundaryField())
+ {
+ label faceStart = pf.patch().start();
+
+ forAll(pf, facei)
+ {
+ allValues[faceStart++] = pf[facei];
+ }
+ }
+
+ this->distribute(allValues);
+ newValues.transfer(allValues);
+
+ break;
+ }
+ default:
+ {
+ FatalErrorInFunction
+ << "Unknown sampling mode: " << this->mode() << nl
+ << abort(FatalError);
+ }
+ }
+
+ // Enforce average. Either by scaling (if scaling factor > 0.5) or by
+ // offsetting.
+ if (setAverage_ && returnReduce(newValues.size(), sumOp