33 #include "surfaceInterpolate.H" 44 namespace functionObjects
50 extractEulerianParticles,
72 const label nFaces = fz.
size();
73 const label allFaces =
returnReduce(nFaces, sumOp<label>());
79 <<
": Number of faceZone faces (" << allFaces
80 <<
") is less than the number of requested locations (" 87 <<
" faces : " << allFaces <<
nl 100 if (!nInjectorLocations_)
105 const faceZone& fz = mesh_.faceZones()[zoneID_];
114 const label nFaces = fz.
size();
115 label nLocations = nInjectorLocations_;
120 scalar fraction = scalar(nFaces)/scalar(nGlobalFaces);
121 nLocations = ceil(fraction*nInjectorLocations_);
124 Pout<<
"nFaces:" << nFaces
125 <<
", nGlobalFaces:" << nGlobalFaces
126 <<
", fraction:" << fraction
127 <<
", nLocations:" << nLocations
132 pairPatchAgglomeration ppa
145 label nCoarseFaces = 0;
148 fineToCoarseAddr_ = ppa.restrictTopBottomAddressing();
149 nCoarseFaces =
max(fineToCoarseAddr_) + 1;
152 globalCoarseFaces_ = globalIndex(nCoarseFaces);
155 <<
" coarse faces" <<
endl;
192 patchIDs_.setSize(fz.
size(), -1);
193 patchFaceIDs_.setSize(fz.
size(), -1);
195 label nBlockedFaces = 0;
198 const label facei = fz[localFacei];
200 if (mesh_.isInternalFace(facei))
202 if (alphaf[facei] > alphaThreshold_)
204 blockedFaces[localFacei] =
true;
209 label patchi = mesh_.boundaryMesh().whichPatch(facei);
210 label patchFacei = -1;
212 const polyPatch& pp = mesh_.boundaryMesh()[patchi];
214 const auto* cpp = isA<coupledPolyPatch>(pp);
218 patchFacei = (cpp->owner() ? pp.whichFace(facei) : -1);
220 else if (!isA<emptyPolyPatch>(pp))
222 patchFacei = pp.whichFace(facei);
225 if (patchFacei == -1)
229 else if (alphafp[patchFacei] > alphaThreshold_)
231 blockedFaces[localFacei] =
true;
234 patchIDs_[localFacei] = patchi;
235 patchFaceIDs_[localFacei] = patchFacei;
251 const label particlei = regionToParticleMap_[regioni];
254 if (
p.faceIHit != -1 && nInjectorLocations_)
257 label coarseFacei = fineToCoarseAddr_[
p.faceIHit];
258 p.faceIHit = globalCoarseFaces_.toGlobal(coarseFacei);
261 reduce(
p, sumParticleOp<eulerianParticle>());
265 if ((pDiameter > minDiameter_) && (pDiameter < maxDiameter_))
270 const point position =
p.VC/(
p.V + ROOTVSMALL);
271 const vector U =
p.VU/(
p.V + ROOTVSMALL);
273 if (nInjectorLocations_)
278 injectedParticle* ip =
new injectedParticle
289 cloud_.addParticle(ip);
291 collectedVolume_ +=
p.V;
294 ++nCollectedParticles_;
299 ++nDiscardedParticles_;
300 discardedVolume_ +=
p.V;
307 const label nNewRegions,
316 labelList oldToNewRegion(particles_.size(), -1);
319 forAll(regionFaceIDs, facei)
321 label newRegioni = regionFaceIDs[facei];
322 label oldRegioni = regions0_[facei];
324 if (newRegioni != -1 && oldRegioni != -1)
328 newToNewRegion[newRegioni] =
329 max(newRegioni, oldToNewRegion[oldRegioni]);
330 oldToNewRegion[oldRegioni] = newRegioni;
338 label nParticle = -1;
340 Map<label> newRegionToParticleMap;
341 forAll(newToNewRegion, newRegioni0)
343 label newRegioni = newToNewRegion[newRegioni0];
344 if (newRegions.insert(newRegioni))
350 newRegionToParticleMap.insert(newRegioni0, nParticle);
357 List<eulerianParticle> newParticles(newRegionToParticleMap.size());
358 forAll(oldToNewRegion, oldRegioni)
360 label newRegioni = oldToNewRegion[oldRegioni];
361 if (newRegioni == -1)
365 <<
"Collecting particle from oldRegion:" << oldRegioni
368 collectParticle(time, oldRegioni);
373 label newParticlei = newRegionToParticleMap[newRegioni];
374 label oldParticlei = regionToParticleMap_[oldRegioni];
377 <<
"Combining newRegioni: " << newRegioni
378 <<
"(p:" << newParticlei <<
") and " 379 <<
"oldRegioni: " << oldRegioni
380 <<
"(p:" << oldParticlei <<
")" 383 newParticles[newParticlei] =
384 sumParticleOp<eulerianParticle>()
386 newParticles[newParticlei],
387 particles_[oldParticlei]
393 particles_.transfer(newParticles);
394 regionToParticleMap_ = newRegionToParticleMap;
398 regions0_ = regionFaceIDs;
415 const scalar deltaT = mesh_.time().deltaTValue();
416 const pointField& faceCentres = mesh_.faceCentres();
418 forAll(regionFaceIDs, localFacei)
420 const label newRegioni = regionFaceIDs[localFacei];
421 if (newRegioni != -1)
423 const label particlei = regionToParticleMap_[newRegioni];
424 const label meshFacei = fz[localFacei];
430 p.faceIHit = localFacei;
437 scalar magPhii =
mag(faceValue(
phi, localFacei, meshFacei));
438 vector Ufi = faceValue(
Uf, localFacei, meshFacei);
439 scalar dV = magPhii*deltaT;
441 p.VC += dV*faceCentres[meshFacei];
459 cloud_(mesh_,
"eulerianParticleCloud"),
460 faceZoneName_(
word::null),
465 alphaThreshold_(0.1),
469 nInjectorLocations_(0),
471 globalCoarseFaces_(),
474 regionToParticleMap_(),
475 minDiameter_(ROOTVSMALL),
477 nCollectedParticles_(getProperty<label>(
"nCollectedParticles", 0)),
478 collectedVolume_(getProperty<scalar>(
"collectedVolume", 0)),
479 nDiscardedParticles_(getProperty<label>(
"nDiscardedParticles", 0)),
480 discardedVolume_(getProperty<scalar>(
"discardedVolume", 0))
485 <<
name <<
" function object only applicable to 3-D cases" 504 dict.readEntry(
"faceZone", faceZoneName_);
505 dict.readEntry(
"alpha", alphaName_);
507 dict.readIfPresent(
"alphaThreshold", alphaThreshold_);
508 dict.readIfPresent(
"U", UName_);
509 dict.readIfPresent(
"rho", rhoName_);
510 dict.readIfPresent(
"phi", phiName_);
511 dict.readIfPresent(
"nLocations", nInjectorLocations_);
512 dict.readIfPresent(
"minDiameter", minDiameter_);
513 dict.readIfPresent(
"maxDiameter", maxDiameter_);
517 if (nInjectorLocations_)
540 typeName +
":alphaf",
544 const faceZone& fz = mesh_.faceZones()[zoneID_];
553 setBlockedFaces(alphaf, fz, blockedFaces);
560 const label nRegionsNew = regionFaceIDs.
nRegions();
568 mesh_.time().value(),
574 accumulateParticleInfo(alphaf, tphi(), regionFaceIDs, fz);
576 Log <<
" Collected particles : " << nCollectedParticles_ <<
nl 577 <<
" Collected volume : " << collectedVolume_ <<
nl 578 <<
" Discarded particles : " << nDiscardedParticles_ <<
nl 579 <<
" Discarded volume : " << discardedVolume_ <<
nl 580 <<
" Particles in progress : " << particles_.size() <<
nl 593 setProperty(
"nCollectedParticles", nCollectedParticles_);
594 setProperty(
"collectedVolume", collectedVolume_);
595 setProperty(
"nDiscardedParticles", nDiscardedParticles_);
596 setProperty(
"discardedVolume", discardedVolume_);
void size(const label n)
Older name for setAddressableSize.
virtual void checkFaceZone()
Check that the faceZone is valid.
defineTypeNameAndDebug(ObukhovLength, 0)
virtual void calculateAddressing(const label nRegionsNew, const scalar time, labelList ®ionFaceIDs)
Calculate the addressing between regions between iterations Returns the number of active regions (par...
virtual void collectParticle(const scalar time, const label regioni)
Collect particles that have passed through the faceZone.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Lightweight class to store particle data derived from VOF calculations, with special handling for inp...
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Splits a patch into regions based on a mask field. Result is a globally consistent label list of regi...
labelList regions0_
Region indices in faceZone faces from last iteration.
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
static bool & parRun() noexcept
Test if this a parallel run.
extractEulerianParticles(const word &name, const Time &runTime, const dictionary &dict)
Construct from components.
label zoneID_
Index of the faceZone.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Macros for easy insertion into run-time selection tables.
const word & name() const noexcept
Return the name of this functionObject.
#define forAll(list, i)
Loop across all elements in list.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
word faceZoneName_
Name of faceZone to sample.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
A list of faces which address into the list of points.
void setSize(const label n)
Alias for resize()
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
virtual bool read(const dictionary &)
Read the field min/max data.
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
virtual void initialiseBins()
Initialise the particle collection bins.
A class for handling words, derived from Foam::string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
#define DebugInFunction
Report an information message using Foam::Info.
label size() const noexcept
The number of elements in the list.
dimensionedScalar cbrt(const dimensionedScalar &ds)
virtual const word & type() const =0
Runtime type information.
virtual void accumulateParticleInfo(const surfaceScalarField &alphaf, const surfaceScalarField &phi, const labelList ®ionFaceIDs, const faceZone &fz)
Process latest region information.
constexpr scalar pi(M_PI)
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
autoPtr< surfaceVectorField > Uf
#define DebugInfo
Report an information message using Foam::Info.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
virtual bool execute()
Execute.
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
virtual bool read(const dictionary &dict)
Read.
label nRegions() const noexcept
Return the global number of regions.
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
virtual void setBlockedFaces(const surfaceScalarField &alphaf, const faceZone &fz, boolList &blockedFaces)
Set the blocked faces, i.e. where alpha > alpha threshold value.
label nSolutionD() const
Return the number of valid solved-for dimensions in the mesh.
label nInjectorLocations_
Number of sample locations to generate.
vector point
Point is a vector.
virtual tmp< surfaceScalarField > phiU() const
Return the volumetric flux.
static bool master(const label communicator=worldComm)
Am I the master rank.
const std::string patch
OpenFOAM patch number as a std::string.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
wordList names() const
A list of the zone names.
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool read(const dictionary &dict)
Read optional controls.
A subset of mesh faces organised as a primitive patch.
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
A class for managing temporary objects.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
virtual bool write()
Write.
A List with indirect addressing.
const fvMesh & mesh_
Reference to the fvMesh.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static void listCombineReduce(List< T > &values, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
After completion all processors have the same data.