Commit c4cc33b7 authored by Andrew Heather's avatar Andrew Heather Committed by Andrew Heather
Browse files

ENH: Added new FaceInteraction cloudFunctionObject

Enables particles to interact with mesh faces (decsribed using faceZones).

    faceInteraction1
    {
        type            faceInteraction;
        faceZones
        (
            (blockageFaces    stick)
//            (blockageFaces    escape)
//            (blockageFaces    rebound) // not applicable for this test case (!)
        );

        dMin            0;
        dMax            1;
    }

The faceZones entry is a list of (faceZoneName interactionType), where
interaction type is either stick, escape or rebound.
parent f64e2864
......@@ -31,6 +31,7 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "FaceInteraction.H"
#include "FacePostProcessing.H"
#include "ParticleCollector.H"
#include "ParticleErosion.H"
......@@ -50,6 +51,7 @@ License
\
makeCloudFunctionObject(CloudType); \
\
makeCloudFunctionObjectType(FaceInteraction, CloudType); \
makeCloudFunctionObjectType(FacePostProcessing, CloudType); \
makeCloudFunctionObjectType(ParticleCollector, CloudType); \
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
......
......@@ -31,6 +31,7 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "FaceInteraction.H"
#include "FacePostProcessing.H"
#include "ParticleCollector.H"
#include "ParticleErosion.H"
......@@ -53,6 +54,7 @@ License
\
makeCloudFunctionObject(CloudType); \
\
makeCloudFunctionObjectType(FaceInteraction, CloudType); \
makeCloudFunctionObjectType(FacePostProcessing, CloudType); \
makeCloudFunctionObjectType(ParticleCollector, CloudType); \
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
......
......@@ -30,6 +30,7 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "FaceInteraction.H"
#include "FacePostProcessing.H"
#include "ParticleCollector.H"
#include "ParticleErosion.H"
......@@ -51,6 +52,7 @@ License
\
makeCloudFunctionObject(CloudType); \
\
makeCloudFunctionObjectType(FaceInteraction, CloudType); \
makeCloudFunctionObjectType(FacePostProcessing, CloudType); \
makeCloudFunctionObjectType(ParticleCollector, CloudType); \
makeCloudFunctionObjectType(ParticleErosion, CloudType); \
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "FaceInteraction.H"
#include "faceZoneMesh.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
template<class CloudType>
const Foam::Enum<typename Foam::FaceInteraction<CloudType>::interactionType>
Foam::FaceInteraction<CloudType>::interactionTypeNames_
({
{ interactionType::STICK, "stick" },
{ interactionType::ESCAPE, "escape" },
{ interactionType::REBOUND, "rebound" },
});
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class CloudType>
bool Foam::FaceInteraction<CloudType>::processParticle
(
const parcelType& p,
const label localZonei
)
{
if (!faceZoneBBs_[localZonei].contains(p.position()))
{
// Quick reject if the particle is not in the face zone bound box
return false;
}
if ((p.d() > dMax_) || (p.d() < dMin_))
{
return false;
}
return true;
}
template<class CloudType>
void Foam::FaceInteraction<CloudType>::write()
{
const fvMesh& mesh = this->owner().mesh();
const faceZoneMesh& fzm = mesh.faceZones();
Info<< type() << " output:" << nl;
// Retrieve any stored data
const label nZones = faceZoneIDs_.size();
labelList npe0(nZones, Zero);
labelList nps0(nZones, Zero);
labelList npr0(nZones, Zero);
this->getModelProperty("nEscape", npe0);
this->getModelProperty("nStick", nps0);
this->getModelProperty("nRebound", npr0);
// Accumulate current data
labelList npe(returnReduce(nEscapeParticles_, sumOp<labelList>()));
labelList nps(returnReduce(nStickParticles_, sumOp<labelList>()));
labelList npr(returnReduce(nReboundParticles_, sumOp<labelList>()));
forAll(npe, i)
{
npe[i] = npe[i] + npe0[i];
nps[i] = nps[i] + nps0[i];
npr[i] = npr[i] + npr0[i];
}
// Write to log/file
forAll(faceZoneIDs_, i)
{
const label zonei = faceZoneIDs_[i];
Info<< " Zone : " << fzm[zonei].name() << nl
<< " Escape : " << npe[i] << nl
<< " Stick : " << nps[i] << nl
<< " Rebound : " << npr[i] << nl;
if (this->writeToFile())
{
auto& os = filePtrs_[i];
writeCurrentTime(os);
// Note - writing as scalar for better formatting
os << tab << scalar(npe[i])
<< tab << scalar(nps[i])
<< tab << scalar(npr[i])
<< endl;
}
}
Info<< endl;
// Set restart data
this->setModelProperty("nEscape", npe);
this->setModelProperty("nStick", nps);
this->setModelProperty("nRebound", npr);
nEscapeParticles_ = Zero;
nStickParticles_ = Zero;
nReboundParticles_ = Zero;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::FaceInteraction<CloudType>::FaceInteraction
(
const dictionary& dict,
CloudType& owner,
const word& modelName
)
:
CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
functionObjects::writeFile
(
owner,
this->localPath(),
typeName,
this->coeffDict()
),
faceZoneIDs_(),
faceZoneBBs_(),
faceZoneInteraction_(),
filePtrs_(),
nEscapeParticles_(),
nStickParticles_(),
nReboundParticles_(),
dMin_(this->coeffDict().getOrDefault("dMin", -GREAT)),
dMax_(this->coeffDict().getOrDefault("dMax", GREAT))
{
const List<Tuple2<word, word>> nameAndInteraction
(
this->coeffDict().lookup("faceZones")
);
filePtrs_.setSize(nameAndInteraction.size());
faceZoneBBs_.setSize(nameAndInteraction.size());
faceZoneInteraction_.setSize(nameAndInteraction.size());
DynamicList<label> zoneIDs;
const faceZoneMesh& fzm = owner.mesh().faceZones();
const auto& faces = this->owner().mesh().faces();
const auto& points = this->owner().mesh().points();
label nZone = 0;
for (const auto& zoneInfo : nameAndInteraction)
{
const word& zoneName = zoneInfo.first();
const label zonei = fzm.findZoneID(zoneName);
if (zonei != -1)
{
zoneIDs.append(zonei);
const faceZone& fz = fzm[zonei];
const label nFaces = returnReduce(fz.size(), sumOp<label>());
Info<< " " << zoneName << " faces: " << nFaces << nl;
// Cache the particle action for this faceZone
faceZoneInteraction_[nZone] =
interactionTypeNames_[zoneInfo.second()];
// Cache faceZone bound box
auto& bb = faceZoneBBs_[nZone];
for (const label facei : fz)
{
for (const label fpi : faces[facei])
{
bb.add(points[fpi]);
}
}
reduce(bb.min(), minOp<point>());
reduce(bb.max(), maxOp<point>());
bb.inflate(0.05);
// Create output file for zone
if (this->writeToFile())
{
filePtrs_.set
(
nZone,
this->createFile(modelName + '_' + zoneName)
);
writeHeaderValue(filePtrs_[nZone], "Source", type());
writeHeaderValue(filePtrs_[nZone], "Face zone", zoneName);
writeHeaderValue(filePtrs_[nZone], "Faces", nFaces);
writeCommented(filePtrs_[nZone], "Time");
writeTabbed(filePtrs_[nZone], "Escape");
writeTabbed(filePtrs_[nZone], "Stick");
writeTabbed(filePtrs_[nZone], "Rebound");
filePtrs_[nZone] << nl;
}
++nZone;
}
else
{
WarningInFunction
<< "Unable to find faceZone " << zoneName
<< " - removing" << endl;
}
}
faceZoneIDs_.transfer(zoneIDs);
filePtrs_.setSize(nZone);
faceZoneBBs_.setSize(nZone);
faceZoneInteraction_.setSize(nZone);
nEscapeParticles_.setSize(nZone, Zero);
nStickParticles_.setSize(nZone, Zero);
nReboundParticles_.setSize(nZone, Zero);
}
template<class CloudType>
Foam::FaceInteraction<CloudType>::FaceInteraction
(
const FaceInteraction<CloudType>& pfi
)
:
CloudFunctionObject<CloudType>(pfi),
functionObjects::writeFile(pfi),
faceZoneIDs_(pfi.faceZoneIDs_),
faceZoneBBs_(pfi.faceZoneBBs_),
filePtrs_(),
nEscapeParticles_(pfi.nEscapeParticles_),
nStickParticles_(pfi.nStickParticles_),
nReboundParticles_(pfi.nReboundParticles_),
dMin_(pfi.dMin_),
dMax_(pfi.dMax_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::FaceInteraction<CloudType>::postFace
(
const parcelType& p,
bool& keepParticle
)
{
const auto& fzm = this->owner().mesh().faceZones();
forAll(faceZoneIDs_, i)
{
if (!processParticle(p, i))
{
continue;
}
const label zonei = faceZoneIDs_[i];
const label localFacei = fzm[zonei].find(p.face());
if (localFacei != -1)
{
const label facei = fzm[zonei][localFacei];
switch (faceZoneInteraction_[i])
{
case interactionType::ESCAPE:
{
keepParticle = false;
++nEscapeParticles_[i];
break;
}
case interactionType::STICK:
{
auto& pRef = const_cast<parcelType&>(p);
pRef.active(false);
pRef.U() = Zero;
++nStickParticles_[i];
break;
}
case interactionType::REBOUND:
{
const face& f = this->owner().mesh().faces()[facei];
const auto n = f.unitNormal(this->owner().mesh().points());
auto& pRef = const_cast<parcelType&>(p);
pRef.U() -= 2*n*(pRef.U() & n);
++nReboundParticles_[i];
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled enumeration "
<< interactionTypeNames_[faceZoneInteraction_[i]]
<< abort(FatalError);
}
}
}
}
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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::FaceInteraction
Group
grpLagrangianIntermediateFunctionObjects
Description
Face zone-based particle interactions.
\verbatim
faceInteraction1
{
type faceInteraction;
// List of (faceZone interactionType)
faceZones
(
(faceZone1 stick)
(faceZone2 escape)
(faceZone3 rebound)
);
// Optional limiting to diameter range
dMin 0;
dMax 1;
writeToFile yes; // default = yes
}
\endverbatim
File written per faceZone as:
postProcessing/lagrangian/cloudName/modelName/time/modelName_faceZone.dat
SourceFiles
FaceInteraction.C
\*---------------------------------------------------------------------------*/
#ifndef FaceInteraction_H
#define FaceInteraction_H
#include "CloudFunctionObject.H"
#include "Enum.H"
#include "boundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class FaceInteraction Declaration
\*---------------------------------------------------------------------------*/
template<class CloudType>
class FaceInteraction
:
public CloudFunctionObject<CloudType>,
public functionObjects::writeFile
{
public:
// Public Data Types
//- Convenience typedef for parcel type
typedef typename CloudType::parcelType parcelType;
//- Enumeration defining the interaction types
enum class interactionType
{
ESCAPE, //!< particles escape/are removed
STICK, //!< particles stick to the faceZone faces
REBOUND //!< particles rebound from the faceZone faces
};
//- Names for the interaction types
static const Enum<interactionType> interactionTypeNames_;
private:
// Private Data
//- Face zone IDs
labelList faceZoneIDs_;
//- Face zone bounding boxes
List<boundBox> faceZoneBBs_;
//- Face zone particle interaction type
List<interactionType> faceZoneInteraction_;
//- File per zone
PtrList<OFstream> filePtrs_;
//- Number of escape particles per zone
labelList nEscapeParticles_;
//- Number of stick particles per zone
labelList nStickParticles_;
//- Number of rebound particles per zone
labelList nReboundParticles_;
//- Minimum diameter threshold
scalar dMin_;
//- Maximum diameter threshold
scalar dMax_;
protected:
// Protected Member Functions
//- Return true if this particle will be assessed
bool processParticle(const parcelType& p, const label localZonei);
//- Write post-processing info
void write();
public:
//- Runtime type information
TypeName("faceInteraction");
// Constructors
//- Construct from dictionary
FaceInteraction
(
const dictionary& dict,
CloudType& owner,
const word& modelName
);
//- Construct copy
FaceInteraction(const FaceInteraction<CloudType>& ppm);
//- Construct and return a clone
virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
{
return autoPtr<CloudFunctionObject<CloudType>>
(
new FaceInteraction<CloudType>(*this)
);
}
//- Destructor
virtual ~FaceInteraction() = default;
// Member Functions
//- Post-face hook
virtual void postFace(const parcelType& p, bool& keepParticle);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "FaceInteraction.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //