mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: PatchflowRateInjection model - refactored and improved
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -27,6 +27,7 @@ License
|
|||||||
#include "TimeDataEntry.H"
|
#include "TimeDataEntry.H"
|
||||||
#include "distributionModel.H"
|
#include "distributionModel.H"
|
||||||
#include "mathematicalConstants.H"
|
#include "mathematicalConstants.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -39,19 +40,23 @@ Foam::PatchFlowRateInjection<CloudType>::PatchFlowRateInjection
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
InjectionModel<CloudType>(dict, owner, modelName,typeName),
|
InjectionModel<CloudType>(dict, owner, modelName,typeName),
|
||||||
patchName_(this->coeffDict().lookup("patchName")),
|
patchInjectionBase(owner.mesh(), this->coeffDict().lookup("patchName")),
|
||||||
patchId_(owner.mesh().boundaryMesh().findPatchID(patchName_)),
|
|
||||||
patchArea_(0.0),
|
|
||||||
patchNormal_(vector::zero),
|
|
||||||
phiName_(this->coeffDict().template lookupOrDefault<word>("phi", "phi")),
|
phiName_(this->coeffDict().template lookupOrDefault<word>("phi", "phi")),
|
||||||
rhoName_(this->coeffDict().template lookupOrDefault<word>("rho", "rho")),
|
rhoName_(this->coeffDict().template lookupOrDefault<word>("rho", "rho")),
|
||||||
duration_(readScalar(this->coeffDict().lookup("duration"))),
|
duration_(readScalar(this->coeffDict().lookup("duration"))),
|
||||||
concentration_(readScalar(this->coeffDict().lookup("concentration"))),
|
concentration_
|
||||||
parcelsPerSecond_
|
|
||||||
(
|
(
|
||||||
readScalar(this->coeffDict().lookup("parcelsPerSecond"))
|
TimeDataEntry<scalar>
|
||||||
|
(
|
||||||
|
owner.db().time(),
|
||||||
|
"concentration",
|
||||||
|
this->coeffDict()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
parcelConcentration_
|
||||||
|
(
|
||||||
|
readScalar(this->coeffDict().lookup("parcelConcentration"))
|
||||||
),
|
),
|
||||||
U0_(vector::zero),
|
|
||||||
sizeDistribution_
|
sizeDistribution_
|
||||||
(
|
(
|
||||||
distributionModels::distributionModel::New
|
distributionModels::distributionModel::New
|
||||||
@ -59,45 +64,11 @@ Foam::PatchFlowRateInjection<CloudType>::PatchFlowRateInjection
|
|||||||
this->coeffDict().subDict("sizeDistribution"),
|
this->coeffDict().subDict("sizeDistribution"),
|
||||||
owner.rndGen()
|
owner.rndGen()
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
cellOwners_(),
|
|
||||||
fraction_(1.0),
|
|
||||||
pMeanVolume_(0.0)
|
|
||||||
{
|
{
|
||||||
if (patchId_ < 0)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"PatchFlowRateInjection<CloudType>::PatchFlowRateInjection"
|
|
||||||
"("
|
|
||||||
"const dictionary&, "
|
|
||||||
"CloudType&"
|
|
||||||
")"
|
|
||||||
) << "Requested patch " << patchName_ << " not found" << nl
|
|
||||||
<< "Available patches are: " << owner.mesh().boundaryMesh().names()
|
|
||||||
<< nl << exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
const polyPatch& patch = owner.mesh().boundaryMesh()[patchId_];
|
|
||||||
|
|
||||||
duration_ = owner.db().time().userTimeToTime(duration_);
|
duration_ = owner.db().time().userTimeToTime(duration_);
|
||||||
|
|
||||||
updateMesh();
|
patchInjectionBase::updateMesh(owner.mesh());
|
||||||
|
|
||||||
// TODO: retrieve mean diameter from distrution model
|
|
||||||
scalar pMeanDiameter =
|
|
||||||
readScalar(this->coeffDict().lookup("meanParticleDiameter"));
|
|
||||||
pMeanVolume_ = constant::mathematical::pi*pow3(pMeanDiameter)/6.0;
|
|
||||||
|
|
||||||
// patch geometry
|
|
||||||
label patchSize = cellOwners_.size();
|
|
||||||
label totalPatchSize = patchSize;
|
|
||||||
reduce(totalPatchSize, sumOp<label>());
|
|
||||||
fraction_ = scalar(patchSize)/totalPatchSize;
|
|
||||||
|
|
||||||
patchArea_ = gSum(mag(patch.faceAreas()));
|
|
||||||
patchNormal_ = gSum(patch.faceNormals())/totalPatchSize;
|
|
||||||
patchNormal_ /= mag(patchNormal_);
|
|
||||||
|
|
||||||
// Re-initialise total mass/volume to inject to zero
|
// Re-initialise total mass/volume to inject to zero
|
||||||
// - will be reset during each injection
|
// - will be reset during each injection
|
||||||
@ -113,20 +84,13 @@ Foam::PatchFlowRateInjection<CloudType>::PatchFlowRateInjection
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
InjectionModel<CloudType>(im),
|
InjectionModel<CloudType>(im),
|
||||||
patchName_(im.patchName_),
|
patchInjectionBase(im),
|
||||||
patchId_(im.patchId_),
|
|
||||||
patchArea_(im.patchArea_),
|
|
||||||
patchNormal_(im.patchNormal_),
|
|
||||||
phiName_(im.phiName_),
|
phiName_(im.phiName_),
|
||||||
rhoName_(im.rhoName_),
|
rhoName_(im.rhoName_),
|
||||||
duration_(im.duration_),
|
duration_(im.duration_),
|
||||||
concentration_(im.concentration_),
|
concentration_(im.concentration_),
|
||||||
parcelsPerSecond_(im.parcelsPerSecond_),
|
parcelConcentration_(im.parcelConcentration_),
|
||||||
U0_(im.U0_),
|
sizeDistribution_(im.sizeDistribution_().clone().ptr())
|
||||||
sizeDistribution_(im.sizeDistribution_().clone().ptr()),
|
|
||||||
cellOwners_(im.cellOwners_),
|
|
||||||
fraction_(im.fraction_),
|
|
||||||
pMeanVolume_(im.pMeanVolume_)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -142,9 +106,7 @@ Foam::PatchFlowRateInjection<CloudType>::~PatchFlowRateInjection()
|
|||||||
template<class CloudType>
|
template<class CloudType>
|
||||||
void Foam::PatchFlowRateInjection<CloudType>::updateMesh()
|
void Foam::PatchFlowRateInjection<CloudType>::updateMesh()
|
||||||
{
|
{
|
||||||
// Set/cache the injector cells
|
patchInjectionBase::updateMesh(this->owner().mesh());
|
||||||
const polyPatch& patch = this->owner().mesh().boundaryMesh()[patchId_];
|
|
||||||
cellOwners_ = patch.faceCells();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -155,6 +117,36 @@ Foam::scalar Foam::PatchFlowRateInjection<CloudType>::timeEnd() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class CloudType>
|
||||||
|
Foam::scalar Foam::PatchFlowRateInjection<CloudType>::flowRate() const
|
||||||
|
{
|
||||||
|
const polyMesh& mesh = this->owner().mesh();
|
||||||
|
|
||||||
|
const surfaceScalarField& phi =
|
||||||
|
mesh.lookupObject<surfaceScalarField>(phiName_);
|
||||||
|
|
||||||
|
const scalarField& phip = phi.boundaryField()[patchId_];
|
||||||
|
|
||||||
|
scalar flowRateIn = 0.0;
|
||||||
|
if (phi.dimensions() == dimVelocity*dimArea)
|
||||||
|
{
|
||||||
|
flowRateIn = max(0.0, -sum(phip));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const volScalarField& rho =
|
||||||
|
mesh.lookupObject<volScalarField>(rhoName_);
|
||||||
|
const scalarField& rhop = rho.boundaryField()[patchId_];
|
||||||
|
|
||||||
|
flowRateIn = max(0.0, -sum(phip/rhop));
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce(flowRateIn, sumOp<scalar>());
|
||||||
|
|
||||||
|
return flowRateIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class CloudType>
|
template<class CloudType>
|
||||||
Foam::label Foam::PatchFlowRateInjection<CloudType>::parcelsToInject
|
Foam::label Foam::PatchFlowRateInjection<CloudType>::parcelsToInject
|
||||||
(
|
(
|
||||||
@ -164,10 +156,11 @@ Foam::label Foam::PatchFlowRateInjection<CloudType>::parcelsToInject
|
|||||||
{
|
{
|
||||||
if ((time0 >= 0.0) && (time0 < duration_))
|
if ((time0 >= 0.0) && (time0 < duration_))
|
||||||
{
|
{
|
||||||
scalar nParcels = fraction_*(time1 - time0)*parcelsPerSecond_;
|
scalar dt = time1 - time0;
|
||||||
|
|
||||||
cachedRandom& rnd = this->owner().rndGen();
|
scalar c = concentration_.value(0.5*(time0 + time1));
|
||||||
|
|
||||||
|
scalar nParcels = fraction_*parcelConcentration_*c*flowRate()*dt;
|
||||||
label nParcelsToInject = floor(nParcels);
|
label nParcelsToInject = floor(nParcels);
|
||||||
|
|
||||||
// Inject an additional parcel with a probability based on the
|
// Inject an additional parcel with a probability based on the
|
||||||
@ -177,7 +170,7 @@ Foam::label Foam::PatchFlowRateInjection<CloudType>::parcelsToInject
|
|||||||
nParcelsToInject > 0
|
nParcelsToInject > 0
|
||||||
&& (
|
&& (
|
||||||
nParcels - scalar(nParcelsToInject)
|
nParcels - scalar(nParcelsToInject)
|
||||||
> rnd.position(scalar(0), scalar(1))
|
> this->owner().rndGen().position(scalar(0), scalar(1))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -204,38 +197,11 @@ Foam::scalar Foam::PatchFlowRateInjection<CloudType>::volumeToInject
|
|||||||
|
|
||||||
if ((time0 >= 0.0) && (time0 < duration_))
|
if ((time0 >= 0.0) && (time0 < duration_))
|
||||||
{
|
{
|
||||||
const polyMesh& mesh = this->owner().mesh();
|
scalar c = concentration_.value(0.5*(time0 + time1));
|
||||||
|
|
||||||
const surfaceScalarField& phi =
|
volume = c*(time1 - time0)*flowRate();
|
||||||
mesh.lookupObject<surfaceScalarField>(phiName_);
|
|
||||||
|
|
||||||
const scalarField& phip = phi.boundaryField()[patchId_];
|
|
||||||
|
|
||||||
scalar carrierVolume = 0.0;
|
|
||||||
if (phi.dimensions() == dimVelocity*dimArea)
|
|
||||||
{
|
|
||||||
const scalar flowRateIn = max(0.0, -sum(phip));
|
|
||||||
U0_ = -patchNormal_*flowRateIn/patchArea_;
|
|
||||||
carrierVolume = (time1 - time0)*flowRateIn;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const volScalarField& rho =
|
|
||||||
mesh.lookupObject<volScalarField>(rhoName_);
|
|
||||||
const scalarField& rhop = rho.boundaryField()[patchId_];
|
|
||||||
|
|
||||||
const scalar flowRateIn = max(0.0, -sum(phip/rhop));
|
|
||||||
U0_ = -patchNormal_*flowRateIn/patchArea_;
|
|
||||||
carrierVolume = (time1 - time0)*flowRateIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scalar newParticles = concentration_*carrierVolume;
|
|
||||||
|
|
||||||
volume = pMeanVolume_*newParticles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reduce(volume, sumOp<scalar>());
|
|
||||||
|
|
||||||
this->volumeTotal_ = volume;
|
this->volumeTotal_ = volume;
|
||||||
this->massTotal_ = volume*this->owner().constProps().rho0();
|
this->massTotal_ = volume*this->owner().constProps().rho0();
|
||||||
|
|
||||||
@ -255,39 +221,15 @@ void Foam::PatchFlowRateInjection<CloudType>::setPositionAndCell
|
|||||||
label& tetPtI
|
label& tetPtI
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (cellOwners_.size() > 0)
|
patchInjectionBase::setPositionAndCell
|
||||||
{
|
(
|
||||||
cachedRandom& rnd = this->owner().rndGen();
|
this->owner().mesh(),
|
||||||
|
this->owner().rndGen(),
|
||||||
label cellI = rnd.position<label>(0, cellOwners_.size() - 1);
|
position,
|
||||||
|
cellOwner,
|
||||||
cellOwner = cellOwners_[cellI];
|
tetFaceI,
|
||||||
|
tetPtI
|
||||||
// The position is between the face and cell centre, which could be
|
);
|
||||||
// in any tet of the decomposed cell, so arbitrarily choose the first
|
|
||||||
// face of the cell as the tetFace and the first point after the base
|
|
||||||
// point on the face as the tetPt. The tracking will pick the cell
|
|
||||||
// consistent with the motion in the firsttracking step.
|
|
||||||
tetFaceI = this->owner().mesh().cells()[cellOwner][0];
|
|
||||||
tetPtI = 1;
|
|
||||||
|
|
||||||
// position perturbed between cell and patch face centres
|
|
||||||
const vector& pc = this->owner().mesh().C()[cellOwner];
|
|
||||||
const vector& pf =
|
|
||||||
this->owner().mesh().Cf().boundaryField()[patchId_][cellI];
|
|
||||||
|
|
||||||
const scalar a = rnd.sample01<scalar>();
|
|
||||||
const vector d = pf - pc;
|
|
||||||
position = pc + 0.5*a*d;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cellOwner = -1;
|
|
||||||
tetFaceI = -1;
|
|
||||||
tetPtI = -1;
|
|
||||||
// dummy position
|
|
||||||
position = pTraits<vector>::max;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,8 +242,8 @@ void Foam::PatchFlowRateInjection<CloudType>::setProperties
|
|||||||
typename CloudType::parcelType& parcel
|
typename CloudType::parcelType& parcel
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// set particle velocity
|
// set particle velocity to carrier velocity
|
||||||
parcel.U() = U0_;
|
parcel.U() = this->owner().U()[parcel.cell()];
|
||||||
|
|
||||||
// set particle diameter
|
// set particle diameter
|
||||||
parcel.d() = sizeDistribution_->sample();
|
parcel.d() = sizeDistribution_->sample();
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -32,10 +32,10 @@ Description
|
|||||||
- Total mass to inject
|
- Total mass to inject
|
||||||
- Name of patch
|
- Name of patch
|
||||||
- Injection duration
|
- Injection duration
|
||||||
- Initial parcel velocity
|
|
||||||
- Injection target concentration/carrier volume flow rate
|
- Injection target concentration/carrier volume flow rate
|
||||||
|
- Initial parcel velocity given by local flow velocity
|
||||||
- Parcel diameters obtained by distribution model
|
- Parcel diameters obtained by distribution model
|
||||||
- Parcels injected at cell centres adjacent to patch
|
- Parcels injected randomly across the patch
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
PatchFlowRateInjection.C
|
PatchFlowRateInjection.C
|
||||||
@ -46,15 +46,14 @@ SourceFiles
|
|||||||
#define PatchFlowRateInjection_H
|
#define PatchFlowRateInjection_H
|
||||||
|
|
||||||
#include "InjectionModel.H"
|
#include "InjectionModel.H"
|
||||||
|
#include "patchInjectionBase.H"
|
||||||
|
#include "TimeDataEntry.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
class TimeDataEntry;
|
|
||||||
|
|
||||||
class distributionModel;
|
class distributionModel;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -64,22 +63,11 @@ class distributionModel;
|
|||||||
template<class CloudType>
|
template<class CloudType>
|
||||||
class PatchFlowRateInjection
|
class PatchFlowRateInjection
|
||||||
:
|
:
|
||||||
public InjectionModel<CloudType>
|
public InjectionModel<CloudType>,
|
||||||
|
public patchInjectionBase
|
||||||
{
|
{
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
//- Name of patch
|
|
||||||
const word patchName_;
|
|
||||||
|
|
||||||
//- Id of patch
|
|
||||||
const label patchId_;
|
|
||||||
|
|
||||||
//- Patch area
|
|
||||||
scalar patchArea_;
|
|
||||||
|
|
||||||
//- Patch normal direction
|
|
||||||
vector patchNormal_;
|
|
||||||
|
|
||||||
//- Name of carrier (mass or volume) flux field
|
//- Name of carrier (mass or volume) flux field
|
||||||
const word phiName_;
|
const word phiName_;
|
||||||
|
|
||||||
@ -89,27 +77,15 @@ class PatchFlowRateInjection
|
|||||||
//- Injection duration [s]
|
//- Injection duration [s]
|
||||||
scalar duration_;
|
scalar duration_;
|
||||||
|
|
||||||
//- Concentration of particles to carrier [] (particles/m3)
|
//- Concentration profile of particle volume to carrier volume [-]
|
||||||
const scalar concentration_;
|
const TimeDataEntry<scalar> concentration_;
|
||||||
|
|
||||||
//- Number of parcels to introduce per second []
|
//- Parcels to introduce per unit volume flow rate m3 [n/m3]
|
||||||
const label parcelsPerSecond_;
|
const scalar parcelConcentration_;
|
||||||
|
|
||||||
//- Initial parcel velocity [m/s]
|
|
||||||
vector U0_;
|
|
||||||
|
|
||||||
//- Parcel size distribution model
|
//- Parcel size distribution model
|
||||||
const autoPtr<distributionModels::distributionModel> sizeDistribution_;
|
const autoPtr<distributionModels::distributionModel> sizeDistribution_;
|
||||||
|
|
||||||
//- List of cell labels corresponding to injector positions
|
|
||||||
labelList cellOwners_;
|
|
||||||
|
|
||||||
//- Fraction of injection controlled by this processor
|
|
||||||
scalar fraction_;
|
|
||||||
|
|
||||||
//- Mean particle volume TODO: temporary measure - return from PDF
|
|
||||||
scalar pMeanVolume_;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -152,6 +128,9 @@ public:
|
|||||||
//- Return the end-of-injection time
|
//- Return the end-of-injection time
|
||||||
scalar timeEnd() const;
|
scalar timeEnd() const;
|
||||||
|
|
||||||
|
//- Return the total volumetric flow rate across the patch [m3/s]
|
||||||
|
virtual scalar flowRate() const;
|
||||||
|
|
||||||
//- Number of parcels to introduce relative to SOI
|
//- Number of parcels to introduce relative to SOI
|
||||||
virtual label parcelsToInject(const scalar time0, const scalar time1);
|
virtual label parcelsToInject(const scalar time0, const scalar time1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user