ENH: New cloud function object to remove parcels at face zones

Example usage:

    removeParcels1
    {
        type            removeParcels;
        log             yes;
        resetOnWrite    no;
        resetOnStart    no;
        faceZones       (cycLeft cycRight);
    }

Number and mass of particles removed are written to file
This commit is contained in:
Andrew Heather
2020-06-12 10:38:40 +01:00
parent 01221babfc
commit f21d0ea31e
4 changed files with 475 additions and 0 deletions

View File

@ -37,6 +37,7 @@ License
#include "ParticleTrap.H" #include "ParticleTrap.H"
#include "PatchCollisionDensity.H" #include "PatchCollisionDensity.H"
#include "PatchPostProcessing.H" #include "PatchPostProcessing.H"
#include "RemoveParcels.H"
#include "VoidFraction.H" #include "VoidFraction.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -52,6 +53,7 @@ License
makeCloudFunctionObjectType(ParticleTrap, CloudType); \ makeCloudFunctionObjectType(ParticleTrap, CloudType); \
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
makeCloudFunctionObjectType(RemoveParcels, CloudType); \
makeCloudFunctionObjectType(VoidFraction, CloudType); makeCloudFunctionObjectType(VoidFraction, CloudType);

View File

@ -38,6 +38,7 @@ License
#include "ParticleTrap.H" #include "ParticleTrap.H"
#include "PatchCollisionDensity.H" #include "PatchCollisionDensity.H"
#include "PatchPostProcessing.H" #include "PatchPostProcessing.H"
#include "RemoveParcels.H"
#include "VoidFraction.H" #include "VoidFraction.H"
#include "WeberNumberReacting.H" #include "WeberNumberReacting.H"
@ -54,6 +55,7 @@ License
makeCloudFunctionObjectType(ParticleTrap, CloudType); \ makeCloudFunctionObjectType(ParticleTrap, CloudType); \
makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \ makeCloudFunctionObjectType(PatchCollisionDensity, CloudType); \
makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \ makeCloudFunctionObjectType(PatchPostProcessing, CloudType); \
makeCloudFunctionObjectType(RemoveParcels, CloudType); \
makeCloudFunctionObjectType(VoidFraction, CloudType); \ makeCloudFunctionObjectType(VoidFraction, CloudType); \
makeCloudFunctionObjectType(WeberNumberReacting, CloudType); makeCloudFunctionObjectType(WeberNumberReacting, CloudType);

View File

@ -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;
}
}
}
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //