mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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.
This commit is contained in:
committed by
Andrew Heather
parent
f64e2864f7
commit
c4cc33b748
@ -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); \
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -0,0 +1,203 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user