diff --git a/src/genericPatchFields/Make/files b/src/genericPatchFields/Make/files
index 2ab759cf0cc6c678491b09a82f6f0c598fe3cd9a..2210ca7cdc31fa22b285c9a0a83b6988d294ac2f 100644
--- a/src/genericPatchFields/Make/files
+++ b/src/genericPatchFields/Make/files
@@ -1,5 +1,6 @@
 genericFaPatchField/genericFaPatchFields.C
 genericFvPatchField/genericFvPatchFields.C
 genericPointPatchField/genericPointPatchFields.C
+genericFvsPatchField/genericFvsPatchFields.C
 
 LIB = $(FOAM_LIBBIN)/libgenericPatchFields
diff --git a/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.C b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.C
new file mode 100644
index 0000000000000000000000000000000000000000..e207a58162b6c95342e57c604a112b59a042c77c
--- /dev/null
+++ b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.C
@@ -0,0 +1,837 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2011,2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2011-2016 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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 "genericFvsPatchField.H"
+#include "fvPatchFieldMapper.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::genericFvsPatchField<Type>::genericFvsPatchField
+(
+    const fvPatch& p,
+    const DimensionedField<Type, surfaceMesh>& iF
+)
+:
+    calculatedFvsPatchField<Type>(p, iF)
+{
+    FatalErrorInFunction
+        << "Trying to construct an genericFvsPatchField on patch "
+        << this->patch().name()
+        << " of field " << this->internalField().name()
+        << abort(FatalError);
+}
+
+
+template<class Type>
+Foam::genericFvsPatchField<Type>::genericFvsPatchField
+(
+    const fvPatch& p,
+    const DimensionedField<Type, surfaceMesh>& iF,
+    const dictionary& dict
+)
+:
+    calculatedFvsPatchField<Type>(p, iF, dict),
+    actualTypeName_(dict.lookup("type")),
+    dict_(dict)
+{
+    if (!dict.found("value"))
+    {
+        FatalIOErrorInFunction(dict)
+            << "\n    Cannot find 'value' entry"
+            << " on patch " << this->patch().name()
+            << " of field " << this->internalField().name()
+            << " in file " << this->internalField().objectPath()
+            << nl
+            << "    which is required to set the"
+               " values of the generic patch field." << nl
+            << "    (Actual type " << actualTypeName_ << ")" << nl
+            << "\n    Please add the 'value' entry to the write function "
+               "of the user-defined boundary-condition\n"
+            << exit(FatalIOError);
+    }
+
+    for (const entry& dEntry : dict_)
+    {
+        const keyType& key = dEntry.keyword();
+
+        if (key != "type" && key != "value")
+        {
+            if
+            (
+                dEntry.isStream()
+             && dEntry.stream().size()
+            )
+            {
+                ITstream& is = dEntry.stream();
+
+                // Read first token
+                token firstToken(is);
+
+                if
+                (
+                    firstToken.isWord()
+                 && firstToken.wordToken() == "nonuniform"
+                )
+                {
+                    token fieldToken(is);
+
+                    if (!fieldToken.isCompound())
+                    {
+                        if
+                        (
+                            fieldToken.isLabel()
+                         && fieldToken.labelToken() == 0
+                        )
+                        {
+                            scalarFields_.insert
+                            (
+                                dEntry.keyword(),
+                                autoPtr<scalarField>::New()
+                            );
+                        }
+                        else
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    token following 'nonuniform' "
+                                   "is not a compound"
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+                    }
+                    else if
+                    (
+                        fieldToken.compoundToken().type()
+                     == token::Compound<List<scalar>>::typeName
+                    )
+                    {
+                        auto fPtr = autoPtr<scalarField>::New();
+
+                        fPtr->transfer
+                        (
+                            dynamicCast<token::Compound<List<scalar>>>
+                            (
+                                fieldToken.transferCompoundToken(is)
+                            )
+                        );
+
+                        if (fPtr->size() != this->size())
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    size of field " << key
+                                << " (" << fPtr->size() << ')'
+                                << " is not the same size as the patch ("
+                                << this->size() << ')'
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+
+                        scalarFields_.insert(key, fPtr);
+                    }
+                    else if
+                    (
+                        fieldToken.compoundToken().type()
+                     == token::Compound<List<vector>>::typeName
+                    )
+                    {
+                        auto fPtr = autoPtr<vectorField>::New();
+
+                        fPtr->transfer
+                        (
+                            dynamicCast<token::Compound<List<vector>>>
+                            (
+                                fieldToken.transferCompoundToken(is)
+                            )
+                        );
+
+                        if (fPtr->size() != this->size())
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    size of field " << key
+                                << " (" << fPtr->size() << ')'
+                                << " is not the same size as the patch ("
+                                << this->size() << ')'
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+
+                        vectorFields_.insert(key, fPtr);
+                    }
+                    else if
+                    (
+                        fieldToken.compoundToken().type()
+                     == token::Compound<List<sphericalTensor>>::typeName
+                    )
+                    {
+                        auto fPtr = autoPtr<sphericalTensorField>::New();
+
+                        fPtr->transfer
+                        (
+                            dynamicCast
+                            <
+                                token::Compound<List<sphericalTensor>>
+                            >
+                            (
+                                fieldToken.transferCompoundToken(is)
+                            )
+                        );
+
+                        if (fPtr->size() != this->size())
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    size of field " << key
+                                << " (" << fPtr->size() << ')'
+                                << " is not the same size as the patch ("
+                                << this->size() << ')'
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+
+                        sphericalTensorFields_.insert(key, fPtr);
+                    }
+                    else if
+                    (
+                        fieldToken.compoundToken().type()
+                     == token::Compound<List<symmTensor>>::typeName
+                    )
+                    {
+                        auto fPtr = autoPtr<symmTensorField>::New();
+
+                        fPtr->transfer
+                        (
+                            dynamicCast
+                            <
+                                token::Compound<List<symmTensor>>
+                            >
+                            (
+                                fieldToken.transferCompoundToken(is)
+                            )
+                        );
+
+                        if (fPtr->size() != this->size())
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    size of field " << key
+                                << " (" << fPtr->size() << ')'
+                                << " is not the same size as the patch ("
+                                << this->size() << ')'
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+
+                        symmTensorFields_.insert(key, fPtr);
+                    }
+                    else if
+                    (
+                        fieldToken.compoundToken().type()
+                     == token::Compound<List<tensor>>::typeName
+                    )
+                    {
+                        auto fPtr = autoPtr<tensorField>::New();
+
+                        fPtr->transfer
+                        (
+                            dynamicCast<token::Compound<List<tensor>>>
+                            (
+                                fieldToken.transferCompoundToken(is)
+                            )
+                        );
+
+                        if (fPtr->size() != this->size())
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    size of field " << key
+                                << " (" << fPtr->size() << ')'
+                                << " is not the same size as the patch ("
+                                << this->size() << ')'
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+
+                        tensorFields_.insert(key, fPtr);
+                    }
+                    else
+                    {
+                        FatalIOErrorInFunction(dict)
+                            << "\n    compound " << fieldToken.compoundToken()
+                            << " not supported"
+                            << "\n    on patch " << this->patch().name()
+                            << " of field "
+                            << this->internalField().name()
+                            << " in file "
+                            << this->internalField().objectPath()
+                            << exit(FatalIOError);
+                    }
+                }
+                else if
+                (
+                    firstToken.isWord()
+                 && firstToken.wordToken() == "uniform"
+                )
+                {
+                    token fieldToken(is);
+
+                    if (!fieldToken.isPunctuation())
+                    {
+                        scalarFields_.insert
+                        (
+                            key,
+                            autoPtr<scalarField>::New
+                            (
+                                this->size(),
+                                fieldToken.number()
+                            )
+                        );
+                    }
+                    else
+                    {
+                        // Read as scalarList.
+                        is.putBack(fieldToken);
+
+                        scalarList l(is);
+
+                        if (l.size() == vector::nComponents)
+                        {
+                            vector vs(l[0], l[1], l[2]);
+
+                            vectorFields_.insert
+                            (
+                                key,
+                                autoPtr<vectorField>::New
+                                (
+                                    this->size(),
+                                    vs
+                                )
+                            );
+                        }
+                        else if (l.size() == sphericalTensor::nComponents)
+                        {
+                            sphericalTensor vs(l[0]);
+
+                            sphericalTensorFields_.insert
+                            (
+                                key,
+                                autoPtr<sphericalTensorField>::New
+                                (
+                                    this->size(),
+                                    vs
+                                )
+                            );
+                        }
+                        else if (l.size() == symmTensor::nComponents)
+                        {
+                            symmTensor vs(l[0], l[1], l[2], l[3], l[4], l[5]);
+
+                            symmTensorFields_.insert
+                            (
+                                key,
+                                autoPtr<symmTensorField>::New
+                                (
+                                    this->size(),
+                                    vs
+                                )
+                            );
+                        }
+                        else if (l.size() == tensor::nComponents)
+                        {
+                            tensor vs
+                            (
+                                l[0], l[1], l[2],
+                                l[3], l[4], l[5],
+                                l[6], l[7], l[8]
+                            );
+
+                            tensorFields_.insert
+                            (
+                                key,
+                                autoPtr<tensorField>::New
+                                (
+                                    this->size(),
+                                    vs
+                                )
+                            );
+                        }
+                        else
+                        {
+                            FatalIOErrorInFunction(dict)
+                                << "\n    unrecognised native type " << l
+                                << "\n    on patch " << this->patch().name()
+                                << " of field "
+                                << this->internalField().name()
+                                << " in file "
+                                << this->internalField().objectPath()
+                                << exit(FatalIOError);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+template<class Type>
+Foam::genericFvsPatchField<Type>::genericFvsPatchField
+(
+    const genericFvsPatchField<Type>& ptf,
+    const fvPatch& p,
+    const DimensionedField<Type, surfaceMesh>& iF,
+    const fvPatchFieldMapper& mapper
+)
+:
+    calculatedFvsPatchField<Type>(ptf, p, iF, mapper),
+    actualTypeName_(ptf.actualTypeName_),
+    dict_(ptf.dict_)
+{
+    forAllConstIter
+    (
+        HashPtrTable<scalarField>,
+        ptf.scalarFields_,
+        iter
+    )
+    {
+        scalarFields_.insert
+        (
+            iter.key(),
+            autoPtr<scalarField>::New(*iter(), mapper)
+        );
+    }
+
+    forAllConstIter
+    (
+        HashPtrTable<vectorField>,
+        ptf.vectorFields_,
+        iter
+    )
+    {
+        vectorFields_.insert
+        (
+            iter.key(),
+            autoPtr<vectorField>::New(*iter(), mapper)
+        );
+    }
+
+    forAllConstIter
+    (
+        HashPtrTable<sphericalTensorField>,
+        ptf.sphericalTensorFields_,
+        iter
+    )
+    {
+        sphericalTensorFields_.insert
+        (
+            iter.key(),
+            autoPtr<sphericalTensorField>::New(*iter(), mapper)
+        );
+    }
+
+    forAllConstIter
+    (
+        HashPtrTable<symmTensorField>,
+        ptf.symmTensorFields_,
+        iter
+    )
+    {
+        symmTensorFields_.insert
+        (
+            iter.key(),
+            autoPtr<symmTensorField>::New(*iter(), mapper)
+        );
+    }
+
+    forAllConstIter
+    (
+        HashPtrTable<tensorField>,
+        ptf.tensorFields_,
+        iter
+    )
+    {
+        tensorFields_.insert
+        (
+            iter.key(),
+            autoPtr<tensorField>::New(*iter(), mapper)
+        );
+    }
+}
+
+
+template<class Type>
+Foam::genericFvsPatchField<Type>::genericFvsPatchField
+(
+    const genericFvsPatchField<Type>& ptf
+)
+:
+    calculatedFvsPatchField<Type>(ptf),
+    actualTypeName_(ptf.actualTypeName_),
+    dict_(ptf.dict_),
+    scalarFields_(ptf.scalarFields_),
+    vectorFields_(ptf.vectorFields_),
+    sphericalTensorFields_(ptf.sphericalTensorFields_),
+    symmTensorFields_(ptf.symmTensorFields_),
+    tensorFields_(ptf.tensorFields_)
+{}
+
+
+template<class Type>
+Foam::genericFvsPatchField<Type>::genericFvsPatchField
+(
+    const genericFvsPatchField<Type>& ptf,
+    const DimensionedField<Type, surfaceMesh>& iF
+)
+:
+    calculatedFvsPatchField<Type>(ptf, iF),
+    actualTypeName_(ptf.actualTypeName_),
+    dict_(ptf.dict_),
+    scalarFields_(ptf.scalarFields_),
+    vectorFields_(ptf.vectorFields_),
+    sphericalTensorFields_(ptf.sphericalTensorFields_),
+    symmTensorFields_(ptf.symmTensorFields_),
+    tensorFields_(ptf.tensorFields_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::genericFvsPatchField<Type>::autoMap
+(
+    const fvPatchFieldMapper& m
+)
+{
+    calculatedFvsPatchField<Type>::autoMap(m);
+
+    forAllIter
+    (
+        HashPtrTable<scalarField>,
+        scalarFields_,
+        iter
+    )
+    {
+        iter()->autoMap(m);
+    }
+
+    forAllIter
+    (
+        HashPtrTable<vectorField>,
+        vectorFields_,
+        iter
+    )
+    {
+        iter()->autoMap(m);
+    }
+
+    forAllIter
+    (
+        HashPtrTable<sphericalTensorField>,
+        sphericalTensorFields_,
+        iter
+    )
+    {
+        iter()->autoMap(m);
+    }
+
+    forAllIter
+    (
+        HashPtrTable<symmTensorField>,
+        symmTensorFields_,
+        iter
+    )
+    {
+        iter()->autoMap(m);
+    }
+
+    forAllIter
+    (
+        HashPtrTable<tensorField>,
+        tensorFields_,
+        iter
+    )
+    {
+        iter()->autoMap(m);
+    }
+}
+
+
+template<class Type>
+void Foam::genericFvsPatchField<Type>::rmap
+(
+    const fvsPatchField<Type>& ptf,
+    const labelList& addr
+)
+{
+    calculatedFvsPatchField<Type>::rmap(ptf, addr);
+
+    const genericFvsPatchField<Type>& dptf =
+        refCast<const genericFvsPatchField<Type>>(ptf);
+
+    forAllIter
+    (
+        HashPtrTable<scalarField>,
+        scalarFields_,
+        iter
+    )
+    {
+        HashPtrTable<scalarField>::const_iterator dptfIter =
+            dptf.scalarFields_.find(iter.key());
+
+        if (dptfIter != dptf.scalarFields_.end())
+        {
+            iter()->rmap(*dptfIter(), addr);
+        }
+    }
+
+    forAllIter
+    (
+        HashPtrTable<vectorField>,
+        vectorFields_,
+        iter
+    )
+    {
+        HashPtrTable<vectorField>::const_iterator dptfIter =
+            dptf.vectorFields_.find(iter.key());
+
+        if (dptfIter != dptf.vectorFields_.end())
+        {
+            iter()->rmap(*dptfIter(), addr);
+        }
+    }
+
+    forAllIter
+    (
+        HashPtrTable<sphericalTensorField>,
+        sphericalTensorFields_,
+        iter
+    )
+    {
+        HashPtrTable<sphericalTensorField>::const_iterator dptfIter =
+            dptf.sphericalTensorFields_.find(iter.key());
+
+        if (dptfIter != dptf.sphericalTensorFields_.end())
+        {
+            iter()->rmap(*dptfIter(), addr);
+        }
+    }
+
+    forAllIter
+    (
+        HashPtrTable<symmTensorField>,
+        symmTensorFields_,
+        iter
+    )
+    {
+        HashPtrTable<symmTensorField>::const_iterator dptfIter =
+            dptf.symmTensorFields_.find(iter.key());
+
+        if (dptfIter != dptf.symmTensorFields_.end())
+        {
+            iter()->rmap(*dptfIter(), addr);
+        }
+    }
+
+    forAllIter
+    (
+        HashPtrTable<tensorField>,
+        tensorFields_,
+        iter
+    )
+    {
+        HashPtrTable<tensorField>::const_iterator dptfIter =
+            dptf.tensorFields_.find(iter.key());
+
+        if (dptfIter != dptf.tensorFields_.end())
+        {
+            iter()->rmap(*dptfIter(), addr);
+        }
+    }
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::genericFvsPatchField<Type>::valueInternalCoeffs
+(
+    const tmp<scalarField>&
+) const
+{
+    FatalErrorInFunction
+        << "cannot be called for a genericFvsPatchField"
+           " (actual type " << actualTypeName_ << ")"
+        << "\n    on patch " << this->patch().name()
+        << " of field " << this->internalField().name()
+        << " in file " << this->internalField().objectPath()
+        << "\n    You are probably trying to solve for a field with a "
+           "generic boundary condition."
+        << abort(FatalError);
+
+    return *this;
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::genericFvsPatchField<Type>::valueBoundaryCoeffs
+(
+    const tmp<scalarField>&
+) const
+{
+    FatalErrorInFunction
+        << "cannot be called for a genericFvsPatchField"
+           " (actual type " << actualTypeName_ << ")"
+        << "\n    on patch " << this->patch().name()
+        << " of field " << this->internalField().name()
+        << " in file " << this->internalField().objectPath()
+        << "\n    You are probably trying to solve for a field with a "
+           "generic boundary condition."
+        << abort(FatalError);
+
+    return *this;
+}
+
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::genericFvsPatchField<Type>::gradientInternalCoeffs() const
+{
+    FatalErrorInFunction
+        << "cannot be called for a genericFvsPatchField"
+           " (actual type " << actualTypeName_ << ")"
+        << "\n    on patch " << this->patch().name()
+        << " of field " << this->internalField().name()
+        << " in file " << this->internalField().objectPath()
+        << "\n    You are probably trying to solve for a field with a "
+           "generic boundary condition."
+        << abort(FatalError);
+
+    return *this;
+}
+
+template<class Type>
+Foam::tmp<Foam::Field<Type>>
+Foam::genericFvsPatchField<Type>::gradientBoundaryCoeffs() const
+{
+    FatalErrorInFunction
+        << "cannot be called for a genericFvsPatchField"
+           " (actual type " << actualTypeName_ << ")"
+        << "\n    on patch " << this->patch().name()
+        << " of field " << this->internalField().name()
+        << " in file " << this->internalField().objectPath()
+        << "\n    You are probably trying to solve for a field with a "
+           "generic boundary condition."
+        << abort(FatalError);
+
+    return *this;
+}
+
+
+template<class Type>
+const Foam::word& Foam::genericFvsPatchField<Type>::actualType() const
+{
+    return actualTypeName_;
+}
+
+
+template<class Type>
+void Foam::genericFvsPatchField<Type>::write(Ostream& os) const
+{
+    os.writeEntry("type", actualTypeName_);
+
+    for (const entry& dEntry : dict_)
+    {
+        const keyType& key = dEntry.keyword();
+
+        if (key != "type" && key != "value")
+        {
+            if
+            (
+                dEntry.isStream()
+             && dEntry.stream().size()
+             && dEntry.stream()[0].isWord()
+             && dEntry.stream()[0].wordToken() == "nonuniform"
+            )
+            {
+                if (scalarFields_.found(key))
+                {
+                    scalarFields_.find(key)()
+                        ->writeEntry(key, os);
+                }
+                else if (vectorFields_.found(key))
+                {
+                    vectorFields_.find(key)()
+                        ->writeEntry(key, os);
+                }
+                else if (sphericalTensorFields_.found(key))
+                {
+                    sphericalTensorFields_.find(key)()
+                        ->writeEntry(key, os);
+                }
+                else if (symmTensorFields_.found(key))
+                {
+                    symmTensorFields_.find(key)()
+                        ->writeEntry(key, os);
+                }
+                else if (tensorFields_.found(key))
+                {
+                    tensorFields_.find(key)()
+                        ->writeEntry(key, os);
+                }
+            }
+            else
+            {
+                dEntry.write(os);
+            }
+        }
+    }
+
+    this->writeEntry("value", os);
+}
+
+
+// ************************************************************************* //
diff --git a/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.H b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.H
new file mode 100644
index 0000000000000000000000000000000000000000..43a37f89298b37801384a409e32c55ce37bcfced
--- /dev/null
+++ b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchField.H
@@ -0,0 +1,206 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2011,2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2011-2016 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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::genericFvsPatchField
+
+Description
+    This boundary condition provides a generic version of the \c calculated
+    condition, useful as a fallback for handling unknown patch types.  Not
+    generally applicable as a user-specified condition.
+
+See also
+    Foam::calculatedFvsPatchField
+
+SourceFiles
+    genericFvsPatchField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef genericFvsPatchField_H
+#define genericFvsPatchField_H
+
+#include "calculatedFvsPatchField.H"
+#include "HashPtrTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class genericFvsPatch Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class genericFvsPatchField
+:
+    public calculatedFvsPatchField<Type>
+{
+    // Private data
+
+        const word actualTypeName_;
+        dictionary dict_;
+
+        HashPtrTable<scalarField> scalarFields_;
+        HashPtrTable<vectorField> vectorFields_;
+        HashPtrTable<sphericalTensorField> sphericalTensorFields_;
+        HashPtrTable<symmTensorField> symmTensorFields_;
+        HashPtrTable<tensorField> tensorFields_;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("generic");
+
+
+    // Constructors
+
+        //- Construct from patch and internal field
+        genericFvsPatchField
+        (
+            const fvPatch&,
+            const DimensionedField<Type, surfaceMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        genericFvsPatchField
+        (
+            const fvPatch&,
+            const DimensionedField<Type, surfaceMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given patchField<Type> onto a new patch
+        genericFvsPatchField
+        (
+            const genericFvsPatchField<Type>&,
+            const fvPatch&,
+            const DimensionedField<Type, surfaceMesh>&,
+            const fvPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        genericFvsPatchField
+        (
+            const genericFvsPatchField<Type>&
+        );
+
+        //- Construct and return a clone
+        virtual tmp<fvsPatchField<Type>> clone() const
+        {
+            return tmp<fvsPatchField<Type>>
+            (
+                new genericFvsPatchField<Type>(*this)
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        genericFvsPatchField
+        (
+            const genericFvsPatchField<Type>&,
+            const DimensionedField<Type, surfaceMesh>&
+        );
+
+        //- Construct and return a clone setting internal field reference
+        virtual tmp<fvsPatchField<Type>> clone
+        (
+            const DimensionedField<Type, surfaceMesh>& iF
+        ) const
+        {
+            return tmp<fvsPatchField<Type>>
+            (
+                new genericFvsPatchField<Type>(*this, iF)
+            );
+        }
+
+
+    // Member functions
+
+        // Mapping functions
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap
+            (
+                const fvPatchFieldMapper&
+            );
+
+            //- Reverse map the given fvsPatchField onto this fvsPatchField
+            virtual void rmap
+            (
+                const fvsPatchField<Type>&,
+                const labelList&
+            );
+
+
+        // Evaluation functions
+
+            //- Return the matrix diagonal coefficients corresponding to the
+            //  evaluation of the value of this patchField with given weights
+            virtual tmp<Field<Type>> valueInternalCoeffs
+            (
+                const tmp<scalarField>&
+            ) const;
+
+            //- Return the matrix source coefficients corresponding to the
+            //  evaluation of the value of this patchField with given weights
+            virtual tmp<Field<Type>> valueBoundaryCoeffs
+            (
+                const tmp<scalarField>&
+            ) const;
+
+            //- Return the matrix diagonal coefficients corresponding to the
+            //  evaluation of the gradient of this patchField
+            tmp<Field<Type>> gradientInternalCoeffs() const;
+
+            //- Return the matrix source coefficients corresponding to the
+            //  evaluation of the gradient of this patchField
+            tmp<Field<Type>> gradientBoundaryCoeffs() const;
+
+
+        //- Return the actual type
+        const word& actualType() const;
+
+        //- Write
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "genericFvsPatchField.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.C b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.C
new file mode 100644
index 0000000000000000000000000000000000000000..e367cdf9f194c1912fed5466ccb554f80da2ff2a
--- /dev/null
+++ b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.C
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2011,2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2011 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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 "genericFvsPatchFields.H"
+#include "addToRunTimeSelectionTable.H"
+#include "fvsPatchFields.H"
+#include "volFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+makeFvsPatchFields(generic);
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// ************************************************************************* //
diff --git a/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.H b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.H
new file mode 100644
index 0000000000000000000000000000000000000000..f63bff442dfc9b4fd1ab10cf40a3bf2361e3b94d
--- /dev/null
+++ b/src/genericPatchFields/genericFvsPatchField/genericFvsPatchFields.H
@@ -0,0 +1,51 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2011 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+                            | Copyright (C) 2011 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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/>.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef genericFvsPatchFields_H
+#define genericFvsPatchFields_H
+
+#include "genericFvsPatchField.H"
+#include "fieldTypes.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+makeFvsPatchTypeFieldTypedefs(generic);
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //