lagrangian: InjectionModel: Time-varying parcel flow rate

The parcelsPerSecond control can now be specified as a time-varying
function. This provides additional control over the temporal
distribution of injected parcels, which may be advantageous if, for
example, the mass flow rate varies significantly. It also enables
variable flow rates of particulates in cases which have a fixed number
of particles per parcel.
This commit is contained in:
Will Bainbridge
2023-06-13 15:34:40 +01:00
parent 0fa46ef28a
commit 3eed5c0c99
22 changed files with 91 additions and 65 deletions

View File

@ -144,10 +144,7 @@ Foam::ConeInjection<CloudType>::ConeInjection
injectorTetPt_(-1),
duration_(this->readDuration(dict, owner)),
massFlowRate_(this->readMassFlowRate(dict, owner, duration_)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
thetaInner_
(
TimeFunction1<scalar>
@ -263,10 +260,15 @@ Foam::label Foam::ConeInjection<CloudType>::nParcelsToInject
if (time0 >= 0 && time0 < duration_)
{
//// Standard calculation
//return floor(parcelsPerSecond_*(time1 - time0));
//return floor(parcelsPerSecond_.integral(time0, time1));
// Modified calculation to make numbers exact
return floor(parcelsPerSecond_*time1 - this->parcelsAddedTotal());
return
floor
(
parcelsPerSecond_.integral(0, time1)
- this->parcelsAddedTotal()
);
}
else
{

View File

@ -217,7 +217,7 @@ private:
const TimeFunction1<scalar> massFlowRate_;
//- Number of parcels to introduce per second
const label parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Inner half-cone angle relative to SOI [deg]
const TimeFunction1<scalar> thetaInner_;

View File

@ -99,9 +99,12 @@ Foam::InjectionModel<CloudType>::readMassFlowRate
{
const Time& time = owner.mesh().time();
const bool haveMassFlowRate = dict.found("massFlowRate");
const bool haveMassTotal = dict.found("massTotal");
if (dict.found("nParticle"))
{
if (dict.found("massFlowRate") || dict.found("massTotal"))
if (haveMassFlowRate || haveMassTotal)
{
IOWarningInFunction(dict)
<< "If nParticle is specified then massFlowRate and massTotal "
@ -116,7 +119,21 @@ Foam::InjectionModel<CloudType>::readMassFlowRate
);
}
if (owner.solution().steadyState())
if (owner.solution().steadyState() && haveMassTotal)
{
FatalIOErrorInFunction(dict)
<< "Cannot specify the massTotal of a steady injection. Use "
<< "massFlowRate instead." << exit(FatalIOError);
}
if (haveMassFlowRate && haveMassTotal)
{
FatalIOErrorInFunction(dict)
<< "Cannot specify both massFlowRate and massTotal. Use one or "
<< "the other." << exit(FatalIOError);
}
if (owner.solution().steadyState() || haveMassFlowRate)
{
return TimeFunction1<scalar>(time, "massFlowRate", dict);
}
@ -153,6 +170,20 @@ Foam::InjectionModel<CloudType>::readMassFlowRate
}
template<class CloudType>
Foam::TimeFunction1<Foam::scalar>
Foam::InjectionModel<CloudType>::readParcelsPerSecond
(
const dictionary& dict,
CloudType& owner
)
{
const Time& time = owner.mesh().time();
return TimeFunction1<scalar>(time, "parcelsPerSecond", dict);
}
template<class CloudType>
Foam::label Foam::InjectionModel<CloudType>::index() const
{

View File

@ -137,6 +137,14 @@ protected:
const scalar duration
);
//- Read the number of parcels injected per second for continuous
// injections
TimeFunction1<scalar> readParcelsPerSecond
(
const dictionary& dict,
CloudType& owner
);
//- Get the index of this injector
label index() const;

View File

@ -39,10 +39,7 @@ Foam::MomentumLookupTableInjection<CloudType>::MomentumLookupTableInjection
InjectionModel<CloudType>(dict, owner, modelName, typeName),
inputFileName_(this->coeffDict().lookup("inputFile")),
duration_(this->readDuration(dict, owner)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
randomise_(readBool(this->coeffDict().lookup("randomise"))),
injectors_
(
@ -131,7 +128,12 @@ Foam::label Foam::MomentumLookupTableInjection<CloudType>::nParcelsToInject
{
if (time0 >= 0 && time0 < duration_)
{
return floor(injectorCells_.size()*(time1 - time0)*parcelsPerSecond_);
return
floor
(
injectorCells_.size()
*parcelsPerSecond_.integral(time0, time1)
);
}
else
{

View File

@ -80,7 +80,7 @@ class MomentumLookupTableInjection
const scalar duration_;
//- Number of parcels per injector - common to all injection sources
const scalar parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Flag to indicate to randomise injection positions
bool randomise_;

View File

@ -41,10 +41,7 @@ Foam::PatchInjection<CloudType>::PatchInjection
patchInjectionBase(owner.mesh(), this->coeffDict().lookup("patchName")),
duration_(this->readDuration(dict, owner)),
massFlowRate_(this->readMassFlowRate(dict, owner, duration_)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
U0_(this->coeffDict().lookup("U0")),
sizeDistribution_
(
@ -106,7 +103,7 @@ Foam::label Foam::PatchInjection<CloudType>::nParcelsToInject
{
if (time0 >= 0 && time0 < duration_)
{
scalar nParcels = (time1 - time0)*parcelsPerSecond_;
scalar nParcels = parcelsPerSecond_.integral(time0, time1);
Random& rnd = this->owner().rndGen();

View File

@ -78,7 +78,7 @@ class PatchInjection
const TimeFunction1<scalar> massFlowRate_;
//- Number of parcels to introduce per second []
const label parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Initial parcel velocity [m/s]
const vector U0_;

View File

@ -38,10 +38,7 @@ Foam::ReactingLookupTableInjection<CloudType>::ReactingLookupTableInjection
InjectionModel<CloudType>(dict, owner, modelName, typeName),
inputFileName_(this->coeffDict().lookup("inputFile")),
duration_(this->readDuration(dict, owner)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
randomise_(readBool(this->coeffDict().lookup("randomise"))),
injectors_
(
@ -131,7 +128,12 @@ Foam::label Foam::ReactingLookupTableInjection<CloudType>::nParcelsToInject
{
if (time0 >= 0 && time0 < duration_)
{
return floor(injectorCells_.size()*(time1 - time0)*parcelsPerSecond_);
return
floor
(
injectorCells_.size()
*parcelsPerSecond_.integral(time0, time1)
);
}
else
{

View File

@ -79,7 +79,7 @@ class ReactingLookupTableInjection
const scalar duration_;
//- Number of parcels per injector - common to all injection sources
const scalar parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Flag to indicate to randomise injection positions
bool randomise_;

View File

@ -39,10 +39,7 @@ ReactingMultiphaseLookupTableInjection
InjectionModel<CloudType>(dict, owner, modelName, typeName),
inputFileName_(this->coeffDict().lookup("inputFile")),
duration_(this->readDuration(dict, owner)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
randomise_(readBool(this->coeffDict().lookup("randomise"))),
injectors_
(
@ -136,7 +133,12 @@ Foam::ReactingMultiphaseLookupTableInjection<CloudType>::nParcelsToInject
{
if (time0 >= 0 && time0 < duration_)
{
return floor(injectorCells_.size()*(time1 - time0)*parcelsPerSecond_);
return
floor
(
injectorCells_.size()
*parcelsPerSecond_.integral(time0, time1)
);
}
else
{

View File

@ -82,7 +82,7 @@ class ReactingMultiphaseLookupTableInjection
const scalar duration_;
//- Number of parcels per injector - common to all injection sources
const scalar parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Flag to indicate to randomise injection positions
bool randomise_;

View File

@ -39,10 +39,7 @@ Foam::ThermoLookupTableInjection<CloudType>::ThermoLookupTableInjection
InjectionModel<CloudType>(dict, owner, modelName, typeName),
inputFileName_(this->coeffDict().lookup("inputFile")),
duration_(this->readDuration(dict, owner)),
parcelsPerSecond_
(
this->coeffDict().template lookup<scalar>("parcelsPerSecond")
),
parcelsPerSecond_(this->readParcelsPerSecond(dict, owner)),
randomise_(readBool(this->coeffDict().lookup("randomise"))),
injectors_
(
@ -132,7 +129,12 @@ Foam::label Foam::ThermoLookupTableInjection<CloudType>::nParcelsToInject
{
if (time0 >= 0 && time0 < duration_)
{
return floor(injectorCells_.size()*(time1 - time0)*parcelsPerSecond_);
return
floor
(
injectorCells_.size()
*parcelsPerSecond_.integral(time0, time1)
);
}
else
{

View File

@ -78,7 +78,7 @@ class ThermoLookupTableInjection
const scalar duration_;
//- Number of parcels per injector - common to all injection sources
const scalar parcelsPerSecond_;
const TimeFunction1<scalar> parcelsPerSecond_;
//- Flag to indicate to randomise injection positions
bool randomise_;

View File

@ -69,7 +69,7 @@ subModels
model1
{
type patchInjection;
massTotal 40;
massFlowRate 10;
SOI 1;
uniformParcelSize volume;
patchName inlet;

View File

@ -79,31 +79,15 @@ subModels
mu 650e-6;
sigma 25e-6;
}
flowRateProfile constant 1;
SOI 0;
duration 60;
}
model2
{
type patchInjection;
$model1;
patchName upperInlet;
U0 (18.7939 -6.8404 0);
nParticle 1;
parcelsPerSecond 1390885;
sizeDistribution
{
type normal;
Q 0;
min 500e-6;
max 800e-6;
mu 650e-6;
sigma 25e-6;
}
flowRateProfile constant 1;
massTotal 0;
SOI 0;
duration 60;
}
}

View File

@ -77,7 +77,6 @@ subModels
model1
{
type reactingLookupTableInjection;
massTotal 0.5;
uniformParcelSize volume;
SOI 0;
inputFile "parcelInjectionProperties";

View File

@ -77,7 +77,6 @@ subModels
model1
{
type thermoLookupTableInjection;
massTotal 100;
uniformParcelSize volume;
SOI 0;
inputFile "parcelInjectionProperties";

View File

@ -77,12 +77,12 @@ subModels
model1
{
type coneInjection;
SOI 0.000;
duration 20.000;
SOI 0;
duration 20;
position (0.3 0.35 1.45);
direction (0 0 -1);
massTotal 10;
massFlowRate 0.5;
parcelsPerSecond 1000;
uniformParcelSize volume;
flowRateProfile constant 0.1;

View File

@ -77,7 +77,6 @@ subModels
model1
{
type reactingLookupTableInjection;
massTotal 0.1;
uniformParcelSize volume;
SOI 0.01;
inputFile "parcelInjectionProperties";

View File

@ -77,7 +77,6 @@ subModels
model1
{
type reactingLookupTableInjection;
massTotal 1e-2;
uniformParcelSize volume;
SOI 0.5;
inputFile "parcelInjectionProperties";

View File

@ -78,7 +78,7 @@ subModels
{
type patchInjection;
SOI 0.01;
massTotal 8;
massFlowRate 16;
uniformParcelSize volume;
patchName inletCentral;
duration 10000;