diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.C index 527b32851d06b6512ec071131b4c9f28fa495641..20eb4cbf2c737507b1299b91d06ddc14f04d94ff 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.C @@ -30,6 +30,7 @@ License #include "Function1.H" #include "unitConversion.H" #include "distributionModel.H" +#include "axisAngleRotation.H" using namespace Foam::constant; @@ -43,8 +44,10 @@ Foam::ConeNozzleInjection<CloudType>::injectionMethodNames ({ { injectionMethod::imPoint, "point" }, { injectionMethod::imDisc, "disc" }, + { injectionMethod::imDiscSegments, "discSegments" }, }); + template<class CloudType> const Foam::Enum < @@ -231,6 +234,20 @@ Foam::ConeNozzleInjection<CloudType>::ConeNozzleInjection owner.rndGen() ) ), + t0_(this->template getModelProperty<scalar>("t0")), + nInjectors_ + ( + this->coeffDict().template getOrDefault<scalar>("nInjectors", 1) + ), + Uinjector_(Zero), + initialInjectorDir_ + ( + this->coeffDict().template getOrDefault<vector> + ( + "initialInjectorDir", + Zero + ) + ), tanVec1_(Zero), tanVec2_(Zero), normal_(Zero), @@ -248,6 +265,15 @@ Foam::ConeNozzleInjection<CloudType>::ConeNozzleInjection << exit(FatalError); } + if (nInjectors_ < SMALL) + { + FatalIOErrorInFunction(this->coeffDict()) + << "Number of injectors in angular-segmented disc " + << "must be positive" << nl + << " nInjectors: " << nInjectors_ << nl + << exit(FatalIOError); + } + // Convert from user time to reduce the number of time conversion calls const Time& time = owner.db().time(); duration_ = time.userTimeToTime(duration_); @@ -297,6 +323,10 @@ Foam::ConeNozzleInjection<CloudType>::ConeNozzleInjection thetaInner_(im.thetaInner_.clone()), thetaOuter_(im.thetaOuter_.clone()), sizeDistribution_(im.sizeDistribution_.clone()), + t0_(im.t0_), + nInjectors_(im.nInjectors_), + Uinjector_(im.Uinjector_), + initialInjectorDir_(im.initialInjectorDir_), tanVec1_(im.tanVec1_), tanVec2_(im.tanVec2_), normal_(im.normal_), @@ -420,6 +450,14 @@ void Foam::ConeNozzleInjection<CloudType>::setPositionAndCell { position = positionVsTime_->value(t); + // Estimate the moving injector velocity + const vector position0(positionVsTime_->value(t0_)); + const scalar dt = t - t0_; + if (dt > 0) + { + Uinjector_ = (position - position0)/dt; + } + this->findCellAtPosition ( cellOwner, @@ -438,6 +476,70 @@ void Foam::ConeNozzleInjection<CloudType>::setPositionAndCell position = positionVsTime_->value(t) + r*normal_; + // Estimate the moving injector velocity + const vector position0(positionVsTime_->value(t0_) + r*normal_); + const scalar dt = t - t0_; + if (dt > 0) + { + Uinjector_ = (position - position0)/dt; + } + + this->findCellAtPosition + ( + cellOwner, + tetFacei, + tetPti, + position + ); + break; + } + case injectionMethod::imDiscSegments: + { + // Calculate the uniform angular increment in radians + const scalar angleIncrement = mathematical::twoPi/nInjectors_; + + // Randomly set the index of injector angles + const label injectorIndex = + rndGen.globalPosition<label>(0, nInjectors_ - 1); + + // Calculate the angle for the current injection + const scalar angle = injectorIndex*angleIncrement; + + // Calculate the rotation tensor around an axis by an angle + const tensor R + ( + coordinateRotations::axisAngle::rotation + ( + direction_, + angle, + false // radians + ) + ); + + // Compute a random radius between innerDiameter_ and outerDiameter_ + const scalar fraction = rndGen.globalSample01<scalar>(); + const scalar dr = outerDiameter_ - innerDiameter_; + const scalar radius = 0.5*(innerDiameter_ + fraction*dr); + + // Rotate the initial direction to get the normal direction + // for this injector + normal_ = R & initialInjectorDir_; + + // Compute the particle's injection position + const vector radialOffset(radius*normal_); + position = positionVsTime_->value(t) + radialOffset; + + // Estimate the injector velocity if time has advanced + const scalar dt = t - t0_; + if (dt > 0) + { + const vector position0 + ( + positionVsTime_->value(t0_) + radialOffset + ); + Uinjector_ = (position - position0)/dt; + } + this->findCellAtPosition ( cellOwner, @@ -455,6 +557,9 @@ void Foam::ConeNozzleInjection<CloudType>::setPositionAndCell << exit(FatalError); } } + + // Update the previous time step + t0_ = t; } @@ -487,7 +592,7 @@ void Foam::ConeNozzleInjection<CloudType>::setProperties { case flowType::ftConstantVelocity: { - parcel.U() = UMag_*dirVec; + parcel.U() = UMag_*dirVec + Uinjector_; break; } case flowType::ftPressureDrivenVelocity: @@ -495,7 +600,7 @@ void Foam::ConeNozzleInjection<CloudType>::setProperties scalar pAmbient = this->owner().pAmbient(); scalar rho = parcel.rho(); scalar UMag = ::sqrt(2.0*(Pinj_->value(t) - pAmbient)/rho); - parcel.U() = UMag*dirVec; + parcel.U() = UMag*dirVec + Uinjector_; break; } case flowType::ftFlowRateAndDischarge: @@ -508,7 +613,7 @@ void Foam::ConeNozzleInjection<CloudType>::setProperties /this->volumeTotal(); scalar Umag = massFlowRate/(parcel.rho()*Cd_->value(t)*(Ao - Ai)); - parcel.U() = Umag*dirVec; + parcel.U() = Umag*dirVec + Uinjector_; break; } default: @@ -520,6 +625,7 @@ void Foam::ConeNozzleInjection<CloudType>::setProperties } } + if (omegaPtr_) { const scalar omega = omegaPtr_->value(t); @@ -552,4 +658,16 @@ bool Foam::ConeNozzleInjection<CloudType>::validInjection(const label) } +template<class CloudType> +void Foam::ConeNozzleInjection<CloudType>::info() +{ + InjectionModel<CloudType>::info(); + + if (this->writeTime()) + { + this->setModelProperty("t0", t0_); + } +} + + // ************************************************************************* // diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.H b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.H index bd03d0771e0122df25233ca8e843d04731e878eb..5110bce14fae0a8615a84c24647c2326ec004d2c 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.H +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/ConeNozzleInjection/ConeNozzleInjection.H @@ -97,7 +97,8 @@ public: enum class injectionMethod { imPoint, - imDisc + imDisc, + imDiscSegments //<! Disc with angular segments }; static const Enum<injectionMethod> injectionMethodNames; @@ -171,6 +172,18 @@ private: //- Parcel size PDF model autoPtr<distributionModel> sizeDistribution_; + //- Previous-time value + scalar t0_; + + //- Number of injectors in angular-segmented disc + label nInjectors_; + + //- Estimated speed of the moving injector + vector Uinjector_; + + //- Initial injector direction + vector initialInjectorDir_; + // Tangential vectors to the direction vector @@ -282,6 +295,12 @@ public: //- Return flag to identify whether or not injection of parcelI is // permitted virtual bool validInjection(const label parcelI); + + + // I-O + + //- Write injection info + virtual void info(); };