diff --git a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H
index d5cc69f8ba0c402cfc6a19119249891d298f92fd..4615278aa00d2d80b22ebb424042a0140304c6c4 100644
--- a/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H
+++ b/src/lagrangian/intermediate/parcels/include/makeParcelCloudFunctionObjects.H
@@ -37,6 +37,7 @@ License
 #include "ParticleTrap.H"
 #include "PatchCollisionDensity.H"
 #include "PatchPostProcessing.H"
+#include "RemoveParcels.H"
 #include "VoidFraction.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -52,6 +53,7 @@ License
     makeCloudFunctionObjectType(ParticleTrap, CloudType);                      \
     makeCloudFunctionObjectType(PatchCollisionDensity, CloudType);             \
     makeCloudFunctionObjectType(PatchPostProcessing, CloudType);               \
+    makeCloudFunctionObjectType(RemoveParcels, CloudType);                     \
     makeCloudFunctionObjectType(VoidFraction, CloudType);
 
 
diff --git a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H
index ca86c65d63191fb64f0a53e6ae571716f3a979c6..a11f3de2e2cd9f2c1fa1ae93b58e907fd2ae0468 100644
--- a/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H
+++ b/src/lagrangian/intermediate/parcels/include/makeReactingParcelCloudFunctionObjects.H
@@ -38,6 +38,7 @@ License
 #include "ParticleTrap.H"
 #include "PatchCollisionDensity.H"
 #include "PatchPostProcessing.H"
+#include "RemoveParcels.H"
 #include "VoidFraction.H"
 #include "WeberNumberReacting.H"
 
@@ -54,6 +55,7 @@ License
     makeCloudFunctionObjectType(ParticleTrap, CloudType);                      \
     makeCloudFunctionObjectType(PatchCollisionDensity, CloudType);             \
     makeCloudFunctionObjectType(PatchPostProcessing, CloudType);               \
+    makeCloudFunctionObjectType(RemoveParcels, CloudType);                     \
     makeCloudFunctionObjectType(VoidFraction, CloudType);                      \
     makeCloudFunctionObjectType(WeberNumberReacting, CloudType);
 
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C
new file mode 100644
index 0000000000000000000000000000000000000000..62a7d40910f399237b5028fcae6e264675eb917a
--- /dev/null
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.C
@@ -0,0 +1,287 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "RemoveParcels.H"
+#include "fvMesh.H"
+#include "faceZone.H"
+#include "OFstream.H"
+#include "surfaceFields.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class CloudType>
+void Foam::RemoveParcels<CloudType>::makeLogFile
+(
+    const word& zoneName,
+    const label zoneI,
+    const label nFaces,
+    const scalar totArea
+)
+{
+    // Create the output file if not already created
+    if (log_)
+    {
+        DebugInfo<< "Creating output file." << endl;
+
+        if (Pstream::master())
+        {
+            // Create directory if does not exist
+            mkDir(this->writeTimeDir());
+
+            // Open new file at start up
+            outputFilePtr_.set
+            (
+                zoneI,
+                new OFstream
+                (
+                    this->writeTimeDir()/(type() + '_' + zoneName + ".dat")
+                )
+            );
+
+            outputFilePtr_[zoneI]
+                << "# Source    : " << type() << nl
+                << "# Face zone : " << zoneName << nl
+                << "# Faces     : " << nFaces << nl
+                << "# Area      : " << totArea << nl
+                << "# Time" << tab << "nParcels" << tab << "mass" << endl;
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+template<class CloudType>
+void Foam::RemoveParcels<CloudType>::postEvolve
+(
+    const typename parcelType::trackingData& td
+)
+{
+    Info<< this->modelName() << " output:" << nl;
+
+    const fvMesh& mesh = this->owner().mesh();
+    const faceZoneMesh& fzm = mesh.faceZones();
+
+    forAll(faceZoneIDs_, i)
+    {
+        const word& zoneName = fzm[faceZoneIDs_[i]].name();
+
+        scalar zoneMass = returnReduce(mass_[i], sumOp<scalar>());
+        label zoneNParcels = returnReduce(nParcels_[i], sumOp<label>());
+
+        Info<< "    faceZone " << zoneName
+            << ": removed " << zoneNParcels
+            << " parcels with mass " << zoneMass
+            << nl;
+    }
+
+    CloudFunctionObject<CloudType>::postEvolve(td);
+}
+
+
+template<class CloudType>
+void Foam::RemoveParcels<CloudType>::write()
+{
+    const fvMesh& mesh = this->owner().mesh();
+    const Time& time = mesh.time();
+
+
+    List<scalar> allZoneMass(faceZoneIDs_.size(), 0.0);
+    List<label> allZoneNParcels(faceZoneIDs_.size(), 0);
+
+    forAll(faceZoneIDs_, i)
+    {
+        allZoneMass[i] = returnReduce(mass_[i], sumOp<scalar>());
+        allZoneNParcels[i] = returnReduce(nParcels_[i], sumOp<label>());
+
+        if (outputFilePtr_.set(i))
+        {
+            OFstream& os = outputFilePtr_[i];
+            os  << time.timeName() << token::TAB
+                << allZoneNParcels[i] << token::TAB
+                << allZoneMass[i] << endl;
+        }
+    }
+
+    Info<< endl;
+
+    if (resetOnWrite_)
+    {
+        forAll(mass_, i)
+        {
+            mass_[i] = 0.0;
+            nParcels_[i] = 0.0;
+        }
+    }
+
+    this->setModelProperty("mass", allZoneMass);
+    this->setModelProperty("nParcels", allZoneNParcels);
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class CloudType>
+Foam::RemoveParcels<CloudType>::RemoveParcels
+(
+    const dictionary& dict,
+    CloudType& owner,
+    const word& modelName
+)
+:
+    CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
+    faceZoneIDs_(),
+    nParcels_(),
+    mass_(),
+    typeId_(this->coeffDict().template getOrDefault<label>("parcelType", -1)),
+    log_(this->coeffDict().getBool("log")),
+    resetOnWrite_(this->coeffDict().getBool("resetOnWrite")),
+    resetOnStart_(this->coeffDict().getBool("resetOnStart")),
+    outputFilePtr_()
+{
+    const wordList faceZoneNames(this->coeffDict().lookup("faceZones"));
+
+    nParcels_.setSize(faceZoneNames.size(), 0);
+    mass_.setSize(faceZoneNames.size(), 0.0);
+
+    if (!resetOnStart_ && Pstream::master())
+    {
+        this->getModelProperty("mass", mass_);
+        this->getModelProperty("nParcels", nParcels_);
+    }
+
+    outputFilePtr_.setSize(faceZoneNames.size());
+
+    DynamicList<label> zoneIDs;
+    const faceZoneMesh& fzm = owner.mesh().faceZones();
+    const surfaceScalarField& magSf = owner.mesh().magSf();
+    const polyBoundaryMesh& pbm = owner.mesh().boundaryMesh();
+
+    forAll(faceZoneNames, i)
+    {
+        const word& zoneName = faceZoneNames[i];
+        label zonei = fzm.findZoneID(zoneName);
+
+        if (zonei != -1)
+        {
+            zoneIDs.append(zonei);
+            const faceZone& fz = fzm[zonei];
+
+            label nFaces = returnReduce(fz.size(), sumOp<label>());
+            Info<< "        " << zoneName << " faces: " << nFaces << nl;
+
+            scalar totArea = 0.0;
+            for (label facei : fz)
+            {
+                if (facei < owner.mesh().nInternalFaces())
+                {
+                    totArea += magSf[facei];
+                }
+                else
+                {
+                    label bFacei = facei - owner.mesh().nInternalFaces();
+                    label patchi = pbm.patchID()[bFacei];
+                    const polyPatch& pp = pbm[patchi];
+
+                    if
+                    (
+                        !magSf.boundaryField()[patchi].coupled()
+                     || refCast<const coupledPolyPatch>(pp).owner()
+                    )
+                    {
+                        label localFacei = pp.whichFace(facei);
+                        totArea += magSf.boundaryField()[patchi][localFacei];
+                    }
+                }
+            }
+            totArea = returnReduce(totArea, sumOp<scalar>());
+
+            makeLogFile(zoneName, i, nFaces, totArea);
+        }
+    }
+
+    faceZoneIDs_.transfer(zoneIDs);
+}
+
+
+template<class CloudType>
+Foam::RemoveParcels<CloudType>::RemoveParcels
+(
+    const RemoveParcels<CloudType>& rpf
+)
+:
+    CloudFunctionObject<CloudType>(rpf),
+    faceZoneIDs_(rpf.faceZoneIDs_),
+    nParcels_(rpf.nParcels_),
+    mass_(rpf.mass_),
+    typeId_(rpf.typeId_),
+    log_(rpf.log_),
+    resetOnWrite_(rpf.resetOnWrite_),
+    resetOnStart_(rpf.resetOnStart_),
+    outputFilePtr_()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class CloudType>
+void Foam::RemoveParcels<CloudType>::postFace
+(
+    const parcelType& p,
+    bool& keepParticle
+)
+{
+    if ((typeId_ >= 0) && (p.typeId() != typeId_))
+    {
+        // Not processing this particle type
+        return;
+    }
+
+    if
+    (
+        this->owner().solution().output()
+     || this->owner().solution().transient()
+    )
+    {
+        const faceZoneMesh& fzm = this->owner().mesh().faceZones();
+
+        forAll(faceZoneIDs_, i)
+        {
+            const faceZone& fz = fzm[faceZoneIDs_[i]];
+            if (fz.found(p.face()))
+            {
+                nParcels_[i]++;
+                mass_[i] += p.mass()*p.nParticle();
+                keepParticle = false;
+                break;
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H
new file mode 100644
index 0000000000000000000000000000000000000000..c89f5adffebd8d8c027658fd6f4041f6ebd06b7d
--- /dev/null
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/RemoveParcels/RemoveParcels.H
@@ -0,0 +1,184 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 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::RemoveParcels
+
+Group
+    grpLagrangianIntermediateFunctionObjects
+
+Description
+    Removes parcels that hit user-specified face zone faces
+
+    Example usage:
+    \verbatim
+    removeParcels1
+    {
+        type            removeParcels;
+        log             yes;
+        resetOnWrite    no;
+        resetOnStart    no;
+        faceZones       (cycLeft cycRight);
+    }
+    \endverbatim
+
+SourceFiles
+    RemoveParcels.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef RemoveParcels_H
+#define RemoveParcels_H
+
+#include "CloudFunctionObject.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class OFstream;
+
+/*---------------------------------------------------------------------------*\
+                     Class RemoveParcels Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class CloudType>
+class RemoveParcels
+:
+    public CloudFunctionObject<CloudType>
+{
+        //- Convenience typedef for parcel type
+        typedef typename CloudType::parcelType parcelType;
+
+
+    // Private Data
+
+        //- Face zone IDs
+        labelList faceZoneIDs_;
+
+        //- Number of parcels removed per face zone
+        List<label> nParcels_;
+
+        //- Mass of parcels removed per face zone
+        List<scalar> mass_;
+
+        //- Type ID of parcels to remove; all selected if not set (<0)
+        label typeId_;
+
+        //- Flag to indicate whether data should be written to file
+        bool log_;
+
+        //- Flag to reset counters on write
+        bool resetOnWrite_;
+
+        //- Flag to reset on start
+        bool resetOnStart_;
+
+        //- Output file pointer per zone
+        PtrList<OFstream> outputFilePtr_;
+
+
+    // Private Member Functions
+
+        //- Helper function to create log files
+        void makeLogFile
+        (
+            const word& zoneName,
+            const label zoneI,
+            const label nFaces,
+            const scalar totArea
+        );
+
+
+protected:
+
+    // Protected Member Functions
+
+        //- Write post-processing info
+        void write();
+
+
+public:
+
+    //- Runtime type information
+    TypeName("removeParcels");
+
+
+    // Constructors
+
+        //- Construct from dictionary
+        RemoveParcels
+        (
+            const dictionary& dict,
+            CloudType& owner,
+            const word& modelName
+        );
+
+        //- Construct copy
+        RemoveParcels(const RemoveParcels<CloudType>& ppm);
+
+        //- Construct and return a clone
+        virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
+        {
+            return autoPtr<CloudFunctionObject<CloudType>>
+            (
+                new RemoveParcels<CloudType>(*this)
+            );
+        }
+
+
+    //- Destructor
+    virtual ~RemoveParcels() = default;
+
+
+    // Member Functions
+
+        //- Post-evolve hook
+        virtual void postEvolve
+        (
+            const typename parcelType::trackingData& td
+        );
+
+        //- Post-face hook
+        virtual void postFace(const parcelType& p, bool& keepParticle);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "RemoveParcels.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //