diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index d197acf7ab..584849a332 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -162,6 +162,7 @@ $(faceSources)/boxToFace/boxToFace.C
$(faceSources)/regionToFace/regionToFace.C
$(faceSources)/cylinderToFace/cylinderToFace.C
$(faceSources)/cylinderAnnulusToFace/cylinderAnnulusToFace.C
+$(faceSources)/patchFluxToFace/patchFluxToFace.C
pointSources = sets/pointSources
$(pointSources)/labelToPoint/labelToPoint.C
diff --git a/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.C b/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.C
new file mode 100644
index 0000000000..10a96eb4eb
--- /dev/null
+++ b/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.C
@@ -0,0 +1,183 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2021 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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include "patchFluxToFace.H"
+#include "polyMesh.H"
+#include "faceSet.H"
+#include "Time.H"
+#include "IFstream.H"
+#include "fieldDictionary.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+ defineTypeNameAndDebug(patchFluxToFace, 0);
+ addToRunTimeSelectionTable(topoSetSource, patchFluxToFace, word);
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+void Foam::patchFluxToFace::applyToSet
+(
+ const topoSetSource::setAction action,
+ const scalarField& patchFluxField,
+ topoSet& set
+) const
+{
+ const polyPatch& patch = mesh().boundaryMesh()[patchName_];
+
+ if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
+ {
+ Info<< " Adding all " << fieldName_
+ << (inflow_ ? " inflow" : " outflow") << " faces" << endl;
+
+ forAll(patch, facei)
+ {
+ if
+ (
+ (inflow_ && patchFluxField[facei] < 0)
+ || (!inflow_ && patchFluxField[facei] >= 0)
+ )
+ {
+ set.insert(patch.start() + facei);
+ }
+ }
+ }
+ else if (action == topoSetSource::DELETE)
+ {
+ Info<< " Removing all " << fieldName_
+ << (inflow_ ? " inflow" : " outflow") << " faces" << endl;
+
+ forAll(patch, facei)
+ {
+ if
+ (
+ (inflow_ && patchFluxField[facei] < 0)
+ || (!inflow_ && patchFluxField[facei] >= 0)
+ )
+ {
+ set.erase(patch.start() + facei);
+ }
+ }
+ }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::patchFluxToFace::patchFluxToFace
+(
+ const polyMesh& mesh,
+ const word& fieldName,
+ const word& patchName,
+ const bool inflow
+)
+:
+ topoSetSource(mesh),
+ fieldName_(fieldName),
+ patchName_(patchName),
+ inflow_(inflow)
+{}
+
+
+Foam::patchFluxToFace::patchFluxToFace
+(
+ const polyMesh& mesh,
+ const dictionary& dict
+)
+:
+ topoSetSource(mesh),
+ fieldName_(dict.lookup("field")),
+ patchName_(dict.lookup("patch")),
+ inflow_(dict.lookup("inflow"))
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::patchFluxToFace::~patchFluxToFace()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::patchFluxToFace::applyToSet
+(
+ const topoSetSource::setAction action,
+ topoSet& set
+) const
+{
+ // Try to load field
+ IOobject fieldObject
+ (
+ fieldName_,
+ mesh().time().timeName(),
+ mesh(),
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE,
+ false
+ );
+
+ // Note: should check for surfaceScalarField but that introduces dependency
+ // on volMesh so just use another type with processor-local scope
+ if (!fieldObject.typeHeaderOk(false))
+ {
+ WarningInFunction
+ << "Cannot read flux field " << fieldName_
+ << " from time " << mesh().time().timeName() << endl;
+ }
+ else if (fieldObject.headerClassName() == "surfaceScalarField")
+ {
+ IFstream str(typeFilePath(fieldObject));
+
+ // Read dictionary
+ const fieldDictionary fieldDict
+ (
+ fieldObject,
+ fieldObject.headerClassName()
+ );
+
+ const scalarField patchFluxField
+ (
+ "value",
+ fieldDict.subDict("boundaryField").subDict(patchName_),
+ mesh().boundaryMesh()[patchName_].size()
+ );
+
+ applyToSet(action, patchFluxField, set);
+ }
+ else
+ {
+ WarningInFunction
+ << "Incorrect flux field type " << fieldObject.headerClassName()
+ << endl;
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.H b/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.H
new file mode 100644
index 0000000000..3af61e6651
--- /dev/null
+++ b/src/meshTools/sets/faceSources/patchFluxToFace/patchFluxToFace.H
@@ -0,0 +1,163 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2021 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 .
+
+Class
+ Foam::patchFluxToFace
+
+Description
+ A topoSetSource to select patch faces according to the flux direction.
+
+Usage
+ Example topoSetDict to generate faceSets for inflow and outflow faces
+ on the outlet patch:
+ \verbatim
+ actions
+ (
+ {
+ action new;
+ type faceSet;
+ name inflow;
+ source patchFluxToFace;
+ sourceInfo
+ {
+ field phi;
+ patch outlet;
+ inflow true;
+ }
+ }
+
+ {
+ action new;
+ type faceSet;
+ name outflow;
+ source patchFluxToFace;
+ sourceInfo
+ {
+ field phi;
+ patch outlet;
+ inflow false;
+ }
+ }
+ );
+ \endverbatim
+
+SourceFiles
+ patchFluxToFace.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef patchFluxToFace_H
+#define patchFluxToFace_H
+
+#include "topoSetSource.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+ Class patchFluxToFace Declaration
+\*---------------------------------------------------------------------------*/
+
+class patchFluxToFace
+:
+ public topoSetSource
+{
+ // Private Data
+
+ //- Name of surfaceScalarField
+ word fieldName_;
+
+ //- Name of patch
+ word patchName_;
+
+ //- Switch for inflow/outflow
+ bool inflow_;
+
+
+ // Private Member Functions
+
+ //- Depending on patchFluxField values add to or delete from faceSet.
+ void applyToSet
+ (
+ const topoSetSource::setAction action,
+ const scalarField& patchFluxField,
+ topoSet& set
+ ) const;
+
+
+public:
+
+ //- Runtime type information
+ TypeName("patchFluxToFace");
+
+
+ // Constructors
+
+ //- Construct from components
+ patchFluxToFace
+ (
+ const polyMesh& mesh,
+ const word& fieldName,
+ const word& patchName,
+ const bool inflow
+ );
+
+ //- Construct from dictionary
+ patchFluxToFace
+ (
+ const polyMesh& mesh,
+ const dictionary& dict
+ );
+
+
+ //- Destructor
+ virtual ~patchFluxToFace();
+
+
+ // Member Functions
+
+ virtual sourceType setType() const
+ {
+ return FACESETSOURCE;
+ }
+
+ virtual void applyToSet
+ (
+ const topoSetSource::setAction action,
+ topoSet&
+ ) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //