37 template<
class CloudType>
42 scalar& newVolumeFraction
47 newVolumeFraction = 0.0;
48 bool validInjection =
false;
54 return validInjection;
58 scalar t0 = timeStep0_ - SOI_;
59 scalar t1 = time - SOI_;
62 newParcels = this->parcelsToInject(t0, t1);
66 this->volumeToInject(t0, t1)
67 /(volumeTotal_ + ROOTVSMALL);
69 if (newVolumeFraction > 0)
74 validInjection =
true;
80 validInjection =
false;
86 validInjection =
false;
89 return validInjection;
93 template<
class CloudType>
107 this->owner().mesh().findCellFacePt
122 reduce(proci, maxOp<label>());
137 celli = this->owner().mesh().findNearestCell(position);
141 position += SMALL*(cellCentres[celli] - position);
143 this->owner().mesh().findCellFacePt
157 reduce(proci, maxOp<label>());
172 <<
"Cannot find parcel injection cell. " 173 <<
"Parcel position = " <<
p0 <<
nl 186 template<
class CloudType>
190 const scalar volumeFraction,
191 const scalar diameter,
196 switch (parcelBasis_)
200 scalar volumep =
pi/6.0*
pow3(diameter);
201 scalar volumeTot = massTotal_/
rho;
203 nP = (volumeFraction*volumeTot + delayedVolume_)/(parcels*volumep);
208 nP = massTotal_/(
rho*volumeTotal_);
213 nP = nParticleFixed_;
220 <<
"Unknown parcelBasis type" <<
nl 229 template<
class CloudType>
232 const label parcelsAdded,
233 const scalar massAdded
238 if (allParcelsAdded > 0)
241 <<
"Cloud: " << this->owner().name()
242 <<
" injector: " << this->modelName() <<
nl 243 <<
" Added " << allParcelsAdded <<
" new parcels" <<
nl <<
endl;
247 parcelsAddedTotal_ += allParcelsAdded;
250 massInjected_ +=
returnReduce(massAdded, sumOp<scalar>());
253 time0_ = this->owner().db().time().value();
262 template<
class CloudType>
267 volumeTotal_(this->template getModelProperty<scalar>(
"volumeTotal")),
269 massFlowRate_(nullptr),
270 massInjected_(this->template getModelProperty<scalar>(
"massInjected")),
271 nInjections_(this->template getModelProperty<label>(
"nInjections")),
274 this->template getModelProperty<scalar>(
"parcelsAddedTotal")
276 parcelBasis_(pbNumber),
277 nParticleFixed_(0.0),
279 timeStep0_(this->template getModelProperty<scalar>(
"timeStep0")),
280 minParticlesPerParcel_(1),
283 ignoreOutOfBounds_(false)
287 template<
class CloudType>
292 const word& modelName,
293 const word& modelType
298 volumeTotal_(this->template getModelProperty<scalar>(
"volumeTotal")),
300 massFlowRate_(nullptr),
301 massInjected_(this->template getModelProperty<scalar>(
"massInjected")),
302 nInjections_(this->template getModelProperty<scalar>(
"nInjections")),
305 this->template getModelProperty<scalar>(
"parcelsAddedTotal")
307 parcelBasis_(pbNumber),
308 nParticleFixed_(0.0),
309 time0_(owner.db().time().value()),
310 timeStep0_(this->template getModelProperty<scalar>(
"timeStep0")),
311 minParticlesPerParcel_
313 this->coeffDict().getOrDefault(
"minParticlesPerParcel", scalar(1))
316 injectorID_(this->coeffDict().getOrDefault(
"injectorID", -1)),
319 this->coeffDict().getOrDefault(
"ignoreOutOfBounds", false)
333 if (
owner.solution().active())
335 if (
owner.solution().transient())
344 Function1<scalar>::New
359 const word parcelBasisType(this->
coeffDict().getWord(
"parcelBasisType"));
361 if (parcelBasisType ==
"mass")
365 else if (parcelBasisType ==
"number")
369 else if (parcelBasisType ==
"fixed")
374 Info<<
" Choosing nParticle to be a fixed value, massTotal " 375 <<
"variable now does not determine anything." 381 <<
"parcelBasisType must be either 'number', 'mass' or 'fixed'" 387 template<
class CloudType>
390 const InjectionModel<CloudType>& im
395 volumeTotal_(im.volumeTotal_),
396 massTotal_(im.massTotal_),
397 massFlowRate_(im.massFlowRate_.clone()),
398 massInjected_(im.massInjected_),
399 nInjections_(im.nInjections_),
400 parcelsAddedTotal_(im.parcelsAddedTotal_),
401 parcelBasis_(im.parcelBasis_),
402 nParticleFixed_(im.nParticleFixed_),
404 timeStep0_(im.timeStep0_),
405 minParticlesPerParcel_(im.minParticlesPerParcel_),
406 delayedVolume_(im.delayedVolume_),
407 injectorID_(im.injectorID_),
408 ignoreOutOfBounds_(im.ignoreOutOfBounds_)
414 template<
class CloudType>
419 template<
class CloudType>
423 if (this->owner().
solution().
transient())
425 nTotal = parcelsToInject(0.0, timeEnd() - timeStart());
429 nTotal = parcelsToInject(0.0, 1.0);
432 return massTotal_/nTotal;
436 template<
class CloudType>
437 template<
class TrackCloudType>
440 TrackCloudType&
cloud,
441 typename CloudType::parcelType::trackingData& td
449 const scalar time = this->owner().
db().
time().
value();
452 label parcelsAdded = 0;
453 scalar massAdded = 0.0;
454 label newParcels = 0;
455 scalar newVolumeFraction = 0.0;
456 scalar delayedVolume = 0;
458 if (prepareForNextTimeStep(time, newParcels, newVolumeFraction))
460 const scalar trackTime = this->owner().solution().trackTime();
461 const polyMesh&
mesh = this->owner().
mesh();
464 const scalar deltaT =
465 max(0.0,
min(trackTime,
min(time - SOI_, timeEnd() - time0_)));
468 const scalar padTime =
max(0.0, SOI_ - time0_);
471 for (label parcelI = 0; parcelI < newParcels; parcelI++)
473 if (validInjection(parcelI))
476 scalar timeInj = time0_ + padTime + deltaT*parcelI/newParcels;
500 const scalar dt = time - timeInj;
506 parcelType* pPtr =
new parcelType(
mesh,
pos, celli);
509 cloud.setParcelThermoProperties(*pPtr, dt);
512 setProperties(parcelI, newParcels, timeInj, *pPtr);
515 cloud.checkParcelProperties(*pPtr, dt, fullyDescribed());
535 if (pPtr->nParticle() >= minParticlesPerParcel_)
538 massAdded += pPtr->nParticle()*pPtr->mass();
540 if (pPtr->move(cloud, td, dt))
542 pPtr->typeId() = injectorID_;
543 cloud.addParticle(pPtr);
552 delayedVolume += pPtr->nParticle()*pPtr->volume();
560 delayedVolume_ =
returnReduce(delayedVolume, sumOp<scalar>());
562 postInjectCheck(parcelsAdded, massAdded);
566 template<
class CloudType>
567 template<
class TrackCloudType>
570 TrackCloudType&
cloud,
571 typename CloudType::parcelType::trackingData& td,
572 const scalar trackTime
580 const scalar time = this->owner().
db().
time().
value();
587 const polyMesh&
mesh = this->owner().
mesh();
593 label parcelsAdded = 0;
594 scalar massAdded = 0.0;
597 label newParcels = parcelsToInject(0.0, 1.0);
600 for (label parcelI = 0; parcelI < newParcels; parcelI++)
603 scalar newVolumeFraction = 1.0/scalar(newParcels);
630 parcelType* pPtr =
new parcelType(
mesh,
pos, celli);
633 cloud.setParcelThermoProperties(*pPtr, 0.0);
636 setProperties(parcelI, newParcels, 0.0, *pPtr);
639 cloud.checkParcelProperties(*pPtr, 0.0, fullyDescribed());
654 pPtr->typeId() = injectorID_;
657 cloud.addParticle(pPtr);
659 massAdded += pPtr->nParticle()*pPtr->mass();
664 postInjectCheck(parcelsAdded, massAdded);
668 template<
class CloudType>
673 Log_<<
" Injector " << this->modelName() <<
":" <<
nl 674 <<
" - parcels added = " << parcelsAddedTotal_ <<
nl 675 <<
" - mass introduced = " << massInjected_ <<
nl;
677 if (this->writeTime())
679 this->setModelProperty(
"volumeTotal", volumeTotal_);
680 this->setModelProperty(
"massInjected", massInjected_);
681 this->setModelProperty(
"nInjections", nInjections_);
682 this->setModelProperty(
"parcelsAddedTotal", parcelsAddedTotal_);
683 this->setModelProperty(
"timeStep0", timeStep0_);
virtual void info()
Write to info.
const Type & value() const noexcept
Return const reference to value.
scalar massTotal_
Total mass to inject [kg].
void injectSteadyState(TrackCloudType &cloud, typename CloudType::parcelType::trackingData &td, const scalar trackTime)
Main injection loop - steady-state.
DSMCCloud< dsmcParcel > CloudType
errorManipArg< error, int > exit(error &err, const int errNo=1)
virtual void postInjectCheck(const label parcelsAdded, const scalar massAdded)
Post injection checks.
virtual scalar averageParcelMass()
Return the average parcel mass over the injection period.
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.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
scalar SOI_
Start of injection [s].
Base class for cloud sub-models.
void inject(TrackCloudType &cloud, typename CloudType::parcelType::trackingData &td)
Main injection loop.
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
const Time & time() const
Return the top-level database.
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.
label nGeometricD() const
Return the number of valid geometric dimensions in the mesh.
parcelBasis parcelBasis_
Parcel basis enumeration.
const CloudType & owner() const
Return const access to the owner cloud.
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
dimensionedScalar pos(const dimensionedScalar &ds)
scalar nParticleFixed_
nParticle to assign to parcels when the 'fixed' basis is selected
#define Log_
Report write to Foam::Info if the class log switch is true.
virtual scalar userTimeToTime(const scalar theta) const
Convert the user-time (e.g. CA deg) to real-time (s).
A class for handling words, derived from Foam::string.
const Time & time() const noexcept
Return time registry.
A cloud is a registry collection of lagrangian particles.
const objectRegistry & db() const noexcept
Return the local objectRegistry.
constexpr scalar pi(M_PI)
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
virtual bool findCellAtPosition(label &celli, label &tetFacei, label &tetPti, vector &position, bool errorOnNotFound=true)
Find the cell that contains the supplied position.
virtual void info()
Write injection info.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
InjectionModel(CloudType &owner)
Construct null from owner.
virtual void updateMesh()
Update mesh.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
virtual bool prepareForNextTimeStep(const scalar time, label &newParcels, scalar &newVolumeFraction)
Determine properties for next time step/injection interval.
const fvMesh & mesh() const
Return reference to the mesh.
dimensionedScalar pow3(const dimensionedScalar &ds)
virtual scalar setNumberOfParticles(const label parcels, const scalar volumeFraction, const scalar diameter, const scalar rho)
Set number of particles to inject given parcel properties.
autoPtr< Function1< scalar > > massFlowRate_
Mass flow rate profile for steady calculations.
label injectorID_
Optional injector ID.
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.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Selector class for relaxation factors, solver type and solution.
Templated base class for dsmc cloud.
const volScalarField & p0
static constexpr const zero Zero
Global zero (0)