Merge branch 'master' of github.com-OpenFOAM:OpenFOAM/OpenFOAM-dev

This commit is contained in:
Henry Weller
2018-11-12 16:50:15 +00:00
12 changed files with 438 additions and 1106 deletions

View File

@ -1,137 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::SubDimensionedField
Description
SubDimensionedField is a DimensionedField obtained as a section of another
DimensionedField.
Thus it is itself unallocated so that no storage is allocated or
deallocated during its use. To achieve this behaviour,
SubDimensionedField is derived from SubField rather than Field.
SourceFiles
SubDimensionedFieldI.H
\*---------------------------------------------------------------------------*/
#ifndef SubDimensionedField_H
#define SubDimensionedField_H
#include "Field.H"
#include "SubField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class SubDimensionedField Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class GeoMesh>
class SubDimensionedField
:
public regIOobject,
public SubField<Type>
{
public:
// Public typedefs
typedef typename GeoMesh::Mesh Mesh;
typedef typename Field<Type>::cmptType cmptType;
// Constructors
//- Construct from a SubField
inline SubDimensionedField
(
const SubField<Type>& slist
);
//- Construct from a UList and size
inline SubDimensionedField
(
const UList<Type>& list,
const label subSize
);
//- Construct from a UList start and end indices
inline SubDimensionedField
(
const UList<Type>& list,
const label subSize,
const label startIndex
);
//- Construct as copy
inline SubDimensionedField
(
const SubDimensionedField<cmptType, GeoMesh>& sfield
);
// Member functions
//- Return a null SubDimensionedField
static inline const SubDimensionedField<Type, GeoMesh>& null();
//- Return a component field of the field
inline tmp<DimensionedField<cmptType, GeoMesh>> component
(
const direction
) const;
//- Return the field transpose (only defined for second rank tensors)
tmp<DimensionedField<Type, GeoMesh>> T() const;
// Member operators
//- Assignment
inline void operator=(const SubDimensionedField<Type, GeoMesh>&);
//- Allow cast to a const DimensionedField<Type, GeoMesh>&
inline operator const DimensionedField<Type, GeoMesh>&() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "SubDimensionedFieldI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,131 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type, class GeoMesh>
inline Foam::SubDimensionedField<Type, GeoMesh>::SubDimensionedField
(
const SubField<Type>& slist
)
:
SubField<Type>(slist)
{}
template<class Type, class GeoMesh>
inline Foam::SubDimensionedField<Type, GeoMesh>::SubDimensionedField
(
const UList<Type>& list,
const label subSize
)
:
SubField<Type>(list, subSize)
{}
template<class Type, class GeoMesh>
inline Foam::SubDimensionedField<Type, GeoMesh>::SubDimensionedField
(
const UList<Type>& list,
const label subSize,
const label startIndex
)
:
SubField<Type>(list, subSize, startIndex)
{}
template<class Type, class GeoMesh>
inline Foam::SubDimensionedField<Type, GeoMesh>::SubDimensionedField
(
const SubDimensionedField<Type, GeoMesh>& sfield
)
:
tmp<SubDimensionedField<Type, GeoMesh>>::refCount(),
SubField<Type>(sfield)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class GeoMesh>
inline const Foam::SubDimensionedField<Type, GeoMesh>&
Foam::SubDimensionedField<Type, GeoMesh>::null()
{
return NullObjectRef<SubDimensionedField<Type, GeoMesh>>();
}
template<class Type, class GeoMesh>
inline
Foam::tmp
<
Foam::Field<typename Foam::SubDimensionedField<Type, GeoMesh>::cmptType>
>
Foam::SubDimensionedField<Type, GeoMesh>::component
(
const direction d
) const
{
return
(
reinterpret_cast<const DimensionedField<Type, GeoMesh>&>(*this)
).component(d);
}
template<class Type, class GeoMesh>
inline Foam::tmp<Foam::DimensionedField<Type, GeoMesh>>
Foam::SubDimensionedField<Type, GeoMesh>::T() const
{
return
(
reinterpret_cast<const DimensionedField<Type, GeoMesh>&>(*this)
).T();
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class Type, class GeoMesh>
inline void Foam::SubDimensionedField<Type, GeoMesh>::operator=
(
const SubDimensionedField<Type, GeoMesh>& rhs
)
{
dimensions() = rhs.dimensions();
SubField<Type>::operator=(rhs);
}
template<class Type, class GeoMesh>
inline Foam::SubDimensionedField<Type, GeoMesh>::operator
const Foam::DimensionedField<Type, GeoMesh>&() const
{
return *(reinterpret_cast<const DimensionedField<Type, GeoMesh>*>(this));
}
// ************************************************************************* //

View File

@ -30,7 +30,6 @@ License
#include "CellZoneInjection.H"
#include "ConeInjection.H"
#include "ConeNozzleInjection.H"
#include "FieldActivatedInjection.H"
#include "InflationInjection.H"
#include "KinematicLookupTableInjection.H"
@ -47,7 +46,6 @@ License
\
makeInjectionModelType(CellZoneInjection, CloudType); \
makeInjectionModelType(ConeInjection, CloudType); \
makeInjectionModelType(ConeNozzleInjection, CloudType); \
makeInjectionModelType(FieldActivatedInjection, CloudType); \
makeInjectionModelType(InflationInjection, CloudType); \
makeInjectionModelType(KinematicLookupTableInjection, CloudType); \

View File

@ -30,7 +30,6 @@ License
#include "CellZoneInjection.H"
#include "ConeInjection.H"
#include "ConeNozzleInjection.H"
#include "FieldActivatedInjection.H"
#include "ManualInjection.H"
#include "NoInjection.H"
@ -45,7 +44,6 @@ License
makeInjectionModel(CloudType); \
makeInjectionModelType(CellZoneInjection, CloudType); \
makeInjectionModelType(ConeInjection, CloudType); \
makeInjectionModelType(ConeNozzleInjection, CloudType); \
makeInjectionModelType(FieldActivatedInjection, CloudType); \
makeInjectionModelType(ManualInjection, CloudType); \
makeInjectionModelType(NoInjection, CloudType); \

View File

@ -30,7 +30,6 @@ License
#include "CellZoneInjection.H"
#include "ConeInjection.H"
#include "ConeNozzleInjection.H"
#include "FieldActivatedInjection.H"
#include "ManualInjection.H"
#include "NoInjection.H"
@ -45,7 +44,6 @@ License
makeInjectionModel(CloudType); \
makeInjectionModelType(CellZoneInjection, CloudType); \
makeInjectionModelType(ConeInjection, CloudType); \
makeInjectionModelType(ConeNozzleInjection, CloudType); \
makeInjectionModelType(FieldActivatedInjection, CloudType); \
makeInjectionModelType(ManualInjection, CloudType); \
makeInjectionModelType(NoInjection, CloudType); \

View File

@ -30,6 +30,81 @@ License
using namespace Foam::constant::mathematical;
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::ConeInjection<CloudType>::setInjectionMethod()
{
const word injectionMethod =
this->coeffDict().template lookupOrDefault<word>
(
"injectionMethod",
word::null
);
if (injectionMethod == "point" || injectionMethod == word::null)
{
injectionMethod_ = imPoint;
updateMesh();
}
else if (injectionMethod == "disc")
{
injectionMethod_ = imDisc;
this->coeffDict().lookup("dInner") >> dInner_;
this->coeffDict().lookup("dOuter") >> dOuter_;
}
else
{
FatalErrorInFunction
<< "injectionMethod must be either 'point' or 'disc'"
<< exit(FatalError);
}
}
template<class CloudType>
void Foam::ConeInjection<CloudType>::setFlowType()
{
const word flowType =
this->coeffDict().template lookupOrDefault<word>
(
"flowType",
word::null
);
if (flowType == "constantVelocity" || flowType == word::null)
{
flowType_ = ftConstantVelocity;
Umag_.reset(this->coeffDict());
}
else if (flowType == "pressureDrivenVelocity")
{
flowType_ = ftPressureDrivenVelocity;
Pinj_.reset(this->coeffDict());
}
else if (flowType == "flowRateAndDischarge")
{
flowType_ = ftFlowRateAndDischarge;
this->coeffDict().lookup("dInner") >> dInner_;
this->coeffDict().lookup("dOuter") >> dOuter_;
Cd_.reset(this->coeffDict());
}
else
{
FatalErrorInFunction
<< "flowType must be either 'constantVelocity', "
<< "'pressureDrivenVelocity' or 'flowRateAndDischarge'"
<< exit(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
@ -41,14 +116,17 @@ Foam::ConeInjection<CloudType>::ConeInjection
)
:
InjectionModel<CloudType>(dict, owner, modelName, typeName),
positionAxis_(this->coeffDict().lookup("positionAxis")),
injectorCells_(positionAxis_.size()),
injectorTetFaces_(positionAxis_.size()),
injectorTetPts_(positionAxis_.size()),
injectionMethod_(imPoint),
flowType_(ftConstantVelocity),
position_(this->coeffDict().lookup("position")),
direction_(this->coeffDict().lookup("direction")),
injectorCell_(-1),
injectorTetFace_(-1),
injectorTetPt_(-1),
duration_(readScalar(this->coeffDict().lookup("duration"))),
parcelsPerInjector_
parcelsPerSecond_
(
readScalar(this->coeffDict().lookup("parcelsPerInjector"))
readScalar(this->coeffDict().lookup("parcelsPerSecond"))
),
flowRateProfile_
(
@ -59,15 +137,6 @@ Foam::ConeInjection<CloudType>::ConeInjection
this->coeffDict()
)
),
Umag_
(
TimeFunction1<scalar>
(
owner.db().time(),
"Umag",
this->coeffDict()
)
),
thetaInner_
(
TimeFunction1<scalar>
@ -93,26 +162,28 @@ Foam::ConeInjection<CloudType>::ConeInjection
this->coeffDict().subDict("sizeDistribution"), owner.rndGen()
)
),
nInjected_(this->parcelsAddedTotal()),
tanVec1_(positionAxis_.size()),
tanVec2_(positionAxis_.size())
tanVec1_(vector::max),
tanVec2_(vector::max),
dInner_(vGreat),
dOuter_(vGreat),
Umag_(owner.db().time(), "Umag"),
Cd_(owner.db().time(), "Cd"),
Pinj_(owner.db().time(), "Pinj")
{
duration_ = owner.db().time().userTimeToTime(duration_);
setInjectionMethod();
setFlowType();
// Normalise direction vector and determine direction vectors
// tangential to injector axis direction
forAll(positionAxis_, i)
{
vector& axis = positionAxis_[i].second();
axis /= mag(axis);
tanVec1_[i] = normalised(perpendicular(axis));
tanVec2_[i] = normalised(axis^tanVec1_[i]);
}
// tangential to injector direction
direction_ /= mag(direction_);
tanVec1_ = normalised(perpendicular(direction_));
tanVec2_ = normalised(direction_^tanVec1_);
// Set total volume to inject
this->volumeTotal_ = flowRateProfile_.integrate(0.0, duration_);
this->volumeTotal_ = flowRateProfile_.integrate(0, duration_);
updateMesh();
}
@ -125,20 +196,26 @@ Foam::ConeInjection<CloudType>::ConeInjection
)
:
InjectionModel<CloudType>(im),
positionAxis_(im.positionAxis_),
injectorCells_(im.injectorCells_),
injectorTetFaces_(im.injectorTetFaces_),
injectorTetPts_(im.injectorTetPts_),
injectionMethod_(im.injectionMethod_),
flowType_(im.flowType_),
position_(im.position_),
direction_(im.direction_),
injectorCell_(im.injectorCell_),
injectorTetFace_(im.injectorTetFace_),
injectorTetPt_(im.injectorTetPt_),
duration_(im.duration_),
parcelsPerInjector_(im.parcelsPerInjector_),
parcelsPerSecond_(im.parcelsPerSecond_),
flowRateProfile_(im.flowRateProfile_),
Umag_(im.Umag_),
thetaInner_(im.thetaInner_),
thetaOuter_(im.thetaOuter_),
sizeDistribution_(im.sizeDistribution_().clone().ptr()),
nInjected_(im.nInjected_),
tanVec1_(im.tanVec1_),
tanVec2_(im.tanVec2_)
tanVec2_(im.tanVec2_),
dInner_(im.dInner_),
dOuter_(im.dOuter_),
Umag_(im.Umag_),
Cd_(im.Cd_),
Pinj_(im.Pinj_)
{}
@ -155,15 +232,23 @@ template<class CloudType>
void Foam::ConeInjection<CloudType>::updateMesh()
{
// Set/cache the injector cells
forAll(positionAxis_, i)
switch (injectionMethod_)
{
this->findCellAtPosition
(
injectorCells_[i],
injectorTetFaces_[i],
injectorTetPts_[i],
positionAxis_[i].first()
);
case imPoint:
{
this->findCellAtPosition
(
injectorCell_,
injectorTetFace_,
injectorTetPt_,
position_
);
break;
}
default:
{
break;
}
}
}
@ -182,18 +267,13 @@ Foam::label Foam::ConeInjection<CloudType>::parcelsToInject
const scalar time1
)
{
if ((time0 >= 0.0) && (time0 < duration_))
if (time0 >= 0 && time0 < duration_)
{
const scalar targetVolume = flowRateProfile_.integrate(0, time1);
//// Standard calculation
//return floor(parcelsPerSecond_*(time1 - time0));
const label targetParcels =
parcelsPerInjector_*targetVolume/this->volumeTotal_;
const label nToInject = targetParcels - nInjected_;
nInjected_ += nToInject;
return positionAxis_.size()*nToInject;
// Modified calculation to make numbers exact
return floor(parcelsPerSecond_*time1 - this->parcelsAddedTotal());
}
else
{
@ -209,13 +289,13 @@ Foam::scalar Foam::ConeInjection<CloudType>::volumeToInject
const scalar time1
)
{
if ((time0 >= 0.0) && (time0 < duration_))
if (time0 >= 0 && time0 < duration_)
{
return flowRateProfile_.integrate(time0, time1);
}
else
{
return 0.0;
return 0;
}
}
@ -232,12 +312,40 @@ void Foam::ConeInjection<CloudType>::setPositionAndCell
label& tetPti
)
{
const label i = parcelI % positionAxis_.size();
Random& rndGen = this->owner().rndGen();
position = positionAxis_[i].first();
cellOwner = injectorCells_[i];
tetFacei = injectorTetFaces_[i];
tetPti = injectorTetPts_[i];
switch (injectionMethod_)
{
case imPoint:
{
position = position_;
cellOwner = injectorCell_;
tetFacei = injectorTetFace_;
tetPti = injectorTetPt_;
break;
}
case imDisc:
{
const scalar beta = twoPi*rndGen.globalScalar01();
const scalar frac = rndGen.globalScalar01();
const vector tanVec = tanVec1_*cos(beta) + tanVec2_*sin(beta);
const scalar d = sqrt((1 - frac)*sqr(dInner_) + frac*sqr(dOuter_));
position = position_ + d/2*tanVec;
this->findCellAtPosition
(
cellOwner,
tetFacei,
tetPti,
position,
false
);
break;
}
default:
{
break;
}
}
}
@ -250,29 +358,92 @@ void Foam::ConeInjection<CloudType>::setProperties
typename CloudType::parcelType& parcel
)
{
Random& rnd = this->owner().rndGen();
Random& rndGen = this->owner().rndGen();
// set particle velocity
const label i = parcelI % positionAxis_.size();
const scalar t = time - this->SOI_;
scalar t = time - this->SOI_;
scalar ti = thetaInner_.value(t);
scalar to = thetaOuter_.value(t);
scalar coneAngle = degToRad(rnd.scalarAB(ti, to));
// Get the angle from the axis and the vector perpendicular from the axis.
// If injecting at a point, then these are calculated from two new random
// numbers. If a disc, then these calculations have already been done in
// setPositionAndCell, so the angle and vector can be reverse engineered
// from the position.
scalar theta = vGreat;
vector tanVec = vector::max;
switch (injectionMethod_)
{
case imPoint:
{
const scalar beta = twoPi*rndGen.scalar01();
const scalar frac = rndGen.scalar01();
tanVec = tanVec1_*cos(beta) + tanVec2_*sin(beta);
theta =
degToRad
(
sqrt
(
(1 - frac)*sqr(thetaInner_.value(t))
+ frac*sqr(thetaOuter_.value(t))
)
);
break;
}
case imDisc:
{
const scalar r = mag(parcel.position() - position_);
const scalar frac = (2*r - dInner_)/(dOuter_ - dInner_);
tanVec = normalised(parcel.position() - position_);
theta =
degToRad
(
(1 - frac)*thetaInner_.value(t)
+ frac*thetaOuter_.value(t)
);
break;
}
default:
{
break;
}
}
scalar alpha = sin(coneAngle);
scalar dcorr = cos(coneAngle);
scalar beta = twoPi*rnd.sample01<scalar>();
// The direction of injection
const vector dirVec =
normalised(cos(theta)*direction_ + sin(theta)*tanVec);
vector normal = alpha*(tanVec1_[i]*cos(beta) + tanVec2_[i]*sin(beta));
vector dirVec = dcorr*positionAxis_[i].second();
dirVec += normal;
dirVec /= mag(dirVec);
// Set the velocity
switch (flowType_)
{
case ftConstantVelocity:
{
parcel.U() = Umag_.value(t)*dirVec;
break;
}
case ftPressureDrivenVelocity:
{
const scalar pAmbient = this->owner().pAmbient();
const scalar rho = parcel.rho();
const scalar Umag = ::sqrt(2*(Pinj_.value(t) - pAmbient)/rho);
parcel.U() = Umag*dirVec;
break;
}
case ftFlowRateAndDischarge:
{
const scalar A = 0.25*pi*(sqr(dOuter_) - sqr(dInner_));
const scalar massFlowRate =
this->massTotal()*flowRateProfile_.value(t)/this->volumeTotal();
const scalar Umag =
massFlowRate/(parcel.rho()*Cd_.value(t)*A);
parcel.U() = Umag*dirVec;
break;
}
default:
{
break;
}
}
parcel.U() = Umag_.value(t)*dirVec;
// set particle diameter
parcel.d() = sizeDistribution_().sample();
// Set the particle diameter
parcel.d() = sizeDistribution_->sample();
}

View File

@ -25,17 +25,112 @@ Class
Foam::ConeInjection
Description
Multi-point cone injection model.
This injector injects particles in a number of cones. The user specifies a
position and a direction to inject at, and two angles to inject between.
Optionally, this injector can introduce particles over a disc, instead of
at a point, in which case inner and outer diameters of the disc are also
specified.
User specifies:
- time of start of injection
- list of injector positions and directions (along injection axes)
- number of parcels to inject per injector
- parcel velocities
- inner and outer half-cone angles
The velocity is specified either as constant, or it is calculated from an
injection pressure, or it is calculated from the injector mass flow rate
and a discharge coefficient; i.e.:
Properties:
- Parcel diameters obtained by distribution model
Constant velocity:
\f[
U = U_{constant}
\f]
Pressure driven velocity:
\f[
U = \sqrt{2(p_{injection} - p)/\rho}
\f]
Flow rate and discharge:
\f[
U = \dot{m}/(\rho A C_{discharge})
\f]
Usage
\table
Property | Description | Required | Default
position | The injection position | yes |
direction | The injection direction | yes |
thetaInner | The inner cone angle | yes |
thetaOuter | The outer cone angle | yes |
injectionMethod | Inject at a point or on a disc | no | point
dInner | The inner disc diameter |\\
if disc or flowRateAndDischarge |
dInner | The outer disc diameter |\\
if disc or flowRateAndDischarge |
flowType | Inject with constantVelocity, pressureDrivenVelocity \\
or flowRateAndDischarge | no | constantVelocity
Umag | The injection velocity | if constantVelocity |
Pinj | The injection pressure |\\
if pressureDrivenVelocity |
Cd | The discharge coefficient | if flowRateAndDischarge |
\endtable
Example specification:
\verbatim
injectionModels
{
model1
{
type coneInjection;
// Times
SOI 0;
duration 1;
// Quantities
massTotal 0; // <-- not used with these settings
parcelBasisType fixed;
parcelsPerSecond 1000000;
flowRateProfile constant 1;
nParticle 1;
// Sizes
sizeDistribution
{
type fixedValue;
fixedValueDistribution
{
value 0.0025;
}
}
// Geometry
position (-0.15 -0.1 0);
direction (1 0 0);
thetaInner 0;
thetaOuter 45;
// - Inject at a point
injectionMethod point;
//// - Or, inject over a disc:
//injectionMethod disc;
//dInner 0;
//dOuter 0.05;
// Velocity
// - Inject with constant velocity
flowType constantVelocity;
Umag 1;
//// - Or, inject with flow rate and discharge coefficient
//// This also requires massTotal, dInner and dOuter
//flowType flowRateAndDischarge;
//Cd 0.9;
//// - Or, inject at a pressure
//flowType pressureDrivenVelocity;
//Pinj 10e5;
}
}
\endverbatim
SourceFiles
ConeInjection.C
@ -47,7 +142,6 @@ SourceFiles
#include "InjectionModel.H"
#include "distributionModel.H"
#include "vectorList.H"
#include "TimeFunction1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -64,32 +158,58 @@ class ConeInjection
:
public InjectionModel<CloudType>
{
public:
//- Injection method enumeration
enum injectionMethod
{
imPoint,
imDisc
};
//- Flow type enumeration
enum flowType
{
ftConstantVelocity,
ftPressureDrivenVelocity,
ftFlowRateAndDischarge
};
private:
// Private data
//- List of position and axis for each injector
List<Tuple2<vector, vector>> positionAxis_;
//- Point/disc injection method
injectionMethod injectionMethod_;
//- List of cell labels corresponding to injector positions
labelList injectorCells_;
//- Flow type
flowType flowType_;
//- List of tetFace labels corresponding to injector positions
labelList injectorTetFaces_;
//- Position of the injector
vector position_;
//- List of tetPt labels corresponding to injector positions
labelList injectorTetPts_;
//- Centreline direction in which to inject
vector direction_;
//- Cell label corresponding to the injector position
label injectorCell_;
//- Tet-face label corresponding to the injector position
label injectorTetFace_;
//- Tet-point label corresponding to the injector position
label injectorTetPt_;
//- Injection duration [s]
scalar duration_;
//- Number of parcels to introduce per injector
const label parcelsPerInjector_;
//- Number of parcels to introduce per second
const label parcelsPerSecond_;
//- Flow rate profile relative to SOI []
const TimeFunction1<scalar> flowRateProfile_;
//- Parcel velocity magnitude relative to SOI [m/s]
const TimeFunction1<scalar> Umag_;
//- Inner half-cone angle relative to SOI [deg]
const TimeFunction1<scalar> thetaInner_;
@ -99,17 +219,44 @@ class ConeInjection
//- Parcel size distribution model
const autoPtr<distributionModel> sizeDistribution_;
//- Number of parcels per injector already injected
mutable label nInjected_;
// Tangential vectors to the direction vector
//- First tangential vector
vectorList tanVec1_;
vector tanVec1_;
//- Second tangential vector
vectorList tanVec2_;
vector tanVec2_;
// Disc geometry
//- The inner disc diameter [m]
scalar dInner_;
//- The outer disc diameter [m]
scalar dOuter_;
// Velocity model coefficients
//- Parcel velocity [m/s]
TimeFunction1<scalar> Umag_;
//- Discharge coefficient []
TimeFunction1<scalar> Cd_;
//- Injection pressure [Pa]
TimeFunction1<scalar> Pinj_;
// Private Member Functions
//- Set the injection type
void setInjectionMethod();
//- Set the injection flow type
void setFlowType();
public:

View File

@ -1,430 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "ConeNozzleInjection.H"
#include "TimeFunction1.H"
#include "mathematicalConstants.H"
#include "distributionModel.H"
using namespace Foam::constant;
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::ConeNozzleInjection<CloudType>::setInjectionMethod()
{
word injectionMethodType = this->coeffDict().lookup("injectionMethod");
if (injectionMethodType == "disc")
{
injectionMethod_ = imDisc;
}
else if (injectionMethodType == "point")
{
injectionMethod_ = imPoint;
// Set/cache the injector cell
this->findCellAtPosition
(
injectorCell_,
tetFacei_,
tetPti_,
position_,
false
);
}
else
{
FatalErrorInFunction
<< "injectionMethod must be either 'point' or 'disc'"
<< exit(FatalError);
}
}
template<class CloudType>
void Foam::ConeNozzleInjection<CloudType>::setFlowType()
{
word flowType = this->coeffDict().lookup("flowType");
if (flowType == "constantVelocity")
{
this->coeffDict().lookup("UMag") >> UMag_;
flowType_ = ftConstantVelocity;
}
else if (flowType == "pressureDrivenVelocity")
{
Pinj_.reset(this->coeffDict());
flowType_ = ftPressureDrivenVelocity;
}
else if (flowType == "flowRateAndDischarge")
{
Cd_.reset(this->coeffDict());
flowType_ = ftFlowRateAndDischarge;
}
else
{
FatalErrorInFunction
<< "flowType must be either 'constantVelocity', "
<<"'pressureDrivenVelocity' or 'flowRateAndDischarge'"
<< exit(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::ConeNozzleInjection<CloudType>::ConeNozzleInjection
(
const dictionary& dict,
CloudType& owner,
const word& modelName
)
:
InjectionModel<CloudType>(dict, owner, modelName, typeName),
injectionMethod_(imPoint),
flowType_(ftConstantVelocity),
outerDiameter_(readScalar(this->coeffDict().lookup("outerDiameter"))),
innerDiameter_(readScalar(this->coeffDict().lookup("innerDiameter"))),
duration_(readScalar(this->coeffDict().lookup("duration"))),
position_(this->coeffDict().lookup("position")),
injectorCell_(-1),
tetFacei_(-1),
tetPti_(-1),
direction_(this->coeffDict().lookup("direction")),
parcelsPerSecond_
(
readScalar(this->coeffDict().lookup("parcelsPerSecond"))
),
flowRateProfile_
(
TimeFunction1<scalar>
(
owner.db().time(),
"flowRateProfile",
this->coeffDict()
)
),
thetaInner_
(
TimeFunction1<scalar>
(
owner.db().time(),
"thetaInner",
this->coeffDict()
)
),
thetaOuter_
(
TimeFunction1<scalar>
(
owner.db().time(),
"thetaOuter",
this->coeffDict()
)
),
sizeDistribution_
(
distributionModel::New
(
this->coeffDict().subDict("sizeDistribution"),
owner.rndGen()
)
),
tanVec1_(Zero),
tanVec2_(Zero),
normal_(Zero),
UMag_(0.0),
Cd_(owner.db().time(), "Cd"),
Pinj_(owner.db().time(), "Pinj")
{
if (innerDiameter_ >= outerDiameter_)
{
FatalErrorInFunction
<< "innerNozzleDiameter >= outerNozzleDiameter" << nl
<< exit(FatalError);
}
duration_ = owner.db().time().userTimeToTime(duration_);
setInjectionMethod();
setFlowType();
// Normalise direction vector
direction_ /= mag(direction_);
// Determine direction vectors tangential to direction
tanVec1_ = normalised(perpendicular(direction_));
tanVec2_ = normalised(direction_ ^ tanVec1_);
// Set total volume to inject
this->volumeTotal_ = flowRateProfile_.integrate(0.0, duration_);
updateMesh();
}
template<class CloudType>
Foam::ConeNozzleInjection<CloudType>::ConeNozzleInjection
(
const ConeNozzleInjection<CloudType>& im
)
:
InjectionModel<CloudType>(im),
injectionMethod_(im.injectionMethod_),
flowType_(im.flowType_),
outerDiameter_(im.outerDiameter_),
innerDiameter_(im.innerDiameter_),
duration_(im.duration_),
position_(im.position_),
injectorCell_(im.injectorCell_),
tetFacei_(im.tetFacei_),
tetPti_(im.tetPti_),
direction_(im.direction_),
parcelsPerSecond_(im.parcelsPerSecond_),
flowRateProfile_(im.flowRateProfile_),
thetaInner_(im.thetaInner_),
thetaOuter_(im.thetaOuter_),
sizeDistribution_(im.sizeDistribution_().clone().ptr()),
tanVec1_(im.tanVec1_),
tanVec2_(im.tanVec2_),
normal_(im.normal_),
UMag_(im.UMag_),
Cd_(im.Cd_),
Pinj_(im.Pinj_)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class CloudType>
Foam::ConeNozzleInjection<CloudType>::~ConeNozzleInjection()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
void Foam::ConeNozzleInjection<CloudType>::updateMesh()
{
// Set/cache the injector cells
switch (injectionMethod_)
{
case imPoint:
{
this->findCellAtPosition
(
injectorCell_,
tetFacei_,
tetPti_,
position_
);
}
default:
{}
}
}
template<class CloudType>
Foam::scalar Foam::ConeNozzleInjection<CloudType>::timeEnd() const
{
return this->SOI_ + duration_;
}
template<class CloudType>
Foam::label Foam::ConeNozzleInjection<CloudType>::parcelsToInject
(
const scalar time0,
const scalar time1
)
{
if ((time0 >= 0.0) && (time0 < duration_))
{
return floor((time1 - time0)*parcelsPerSecond_);
}
else
{
return 0;
}
}
template<class CloudType>
Foam::scalar Foam::ConeNozzleInjection<CloudType>::volumeToInject
(
const scalar time0,
const scalar time1
)
{
if ((time0 >= 0.0) && (time0 < duration_))
{
return flowRateProfile_.integrate(time0, time1);
}
else
{
return 0.0;
}
}
template<class CloudType>
void Foam::ConeNozzleInjection<CloudType>::setPositionAndCell
(
const label,
const label,
const scalar,
vector& position,
label& cellOwner,
label& tetFacei,
label& tetPti
)
{
Random& rndGen = this->owner().rndGen();
scalar beta = mathematical::twoPi*rndGen.globalScalar01();
normal_ = tanVec1_*cos(beta) + tanVec2_*sin(beta);
switch (injectionMethod_)
{
case imPoint:
{
position = position_;
cellOwner = injectorCell_;
tetFacei = tetFacei_;
tetPti = tetPti_;
break;
}
case imDisc:
{
scalar frac = rndGen.globalScalar01();
scalar dr = outerDiameter_ - innerDiameter_;
scalar r = 0.5*(innerDiameter_ + frac*dr);
position = position_ + r*normal_;
this->findCellAtPosition
(
cellOwner,
tetFacei,
tetPti,
position,
false
);
break;
}
default:
{
FatalErrorInFunction
<< "Unknown injectionMethod type" << nl
<< exit(FatalError);
}
}
}
template<class CloudType>
void Foam::ConeNozzleInjection<CloudType>::setProperties
(
const label parcelI,
const label,
const scalar time,
typename CloudType::parcelType& parcel
)
{
Random& rndGen = this->owner().rndGen();
// set particle velocity
const scalar deg2Rad = mathematical::pi/180.0;
scalar t = time - this->SOI_;
scalar ti = thetaInner_.value(t);
scalar to = thetaOuter_.value(t);
scalar coneAngle = rndGen.sample01<scalar>()*(to - ti) + ti;
coneAngle *= deg2Rad;
scalar alpha = sin(coneAngle);
scalar dcorr = cos(coneAngle);
vector normal = alpha*normal_;
vector dirVec = dcorr*direction_;
dirVec += normal;
dirVec /= mag(dirVec);
switch (flowType_)
{
case ftConstantVelocity:
{
parcel.U() = UMag_*dirVec;
break;
}
case ftPressureDrivenVelocity:
{
scalar pAmbient = this->owner().pAmbient();
scalar rho = parcel.rho();
scalar UMag = ::sqrt(2.0*(Pinj_.value(t) - pAmbient)/rho);
parcel.U() = UMag*dirVec;
break;
}
case ftFlowRateAndDischarge:
{
scalar Ao = 0.25*mathematical::pi*outerDiameter_*outerDiameter_;
scalar Ai = 0.25*mathematical::pi*innerDiameter_*innerDiameter_;
scalar massFlowRate =
this->massTotal()
*flowRateProfile_.value(t)
/this->volumeTotal();
scalar Umag = massFlowRate/(parcel.rho()*Cd_.value(t)*(Ao - Ai));
parcel.U() = Umag*dirVec;
break;
}
default:
{
}
}
// set particle diameter
parcel.d() = sizeDistribution_->sample();
}
template<class CloudType>
bool Foam::ConeNozzleInjection<CloudType>::fullyDescribed() const
{
return false;
}
template<class CloudType>
bool Foam::ConeNozzleInjection<CloudType>::validInjection(const label)
{
return true;
}
// ************************************************************************* //

View File

@ -1,282 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::ConeNozzleInjection
Description
Cone injection.
User specifies:
- time of start of injection
- injector position
- direction (along injection axis)
- parcel flow rate
- inner and outer half-cone angles
Properties:
- Parcel diameters obtained by size distribution model.
- Parcel velocity is calculated as:
- Constant velocity:
\verbatim
U = \<specified by user\>
\endverbatim
- Pressure driven velocity:
\verbatim
U = sqrt(2*(Pinj - Pamb)/rho)
\endverbatim
- Flow rate and discharge:
\verbatim
U = V_dot/(A*Cd)
\endverbatim
SourceFiles
ConeNozzleInjection.C
\*---------------------------------------------------------------------------*/
#ifndef ConeNozzleInjection_H
#define ConeNozzleInjection_H
#include "InjectionModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
template<class Type>
class TimeFunction1;
class distributionModel;
/*---------------------------------------------------------------------------*\
Class ConeNozzleInjection Declaration
\*---------------------------------------------------------------------------*/
template<class CloudType>
class ConeNozzleInjection
:
public InjectionModel<CloudType>
{
public:
//- Injection method enumeration
enum injectionMethod
{
imPoint,
imDisc
};
//- Flow type enumeration
enum flowType
{
ftConstantVelocity,
ftPressureDrivenVelocity,
ftFlowRateAndDischarge
};
private:
// Private data
//- Point/disc injection method
injectionMethod injectionMethod_;
//- Flow type
flowType flowType_;
//- Outer nozzle diameter [m]
const scalar outerDiameter_;
//- Inner nozzle diameter [m]
const scalar innerDiameter_;
//- Injection duration [s]
scalar duration_;
//- Injector position [m]
vector position_;
//- Cell containing injector position []
label injectorCell_;
//- Index of tet face for injector cell
label tetFacei_;
//- Index of tet point for injector cell
label tetPti_;
//- Injector direction []
vector direction_;
//- Number of parcels to introduce per second []
const label parcelsPerSecond_;
//- Flow rate profile relative to SOI []
const TimeFunction1<scalar> flowRateProfile_;
//- Inner half-cone angle relative to SOI [deg]
const TimeFunction1<scalar> thetaInner_;
//- Outer half-cone angle relative to SOI [deg]
const TimeFunction1<scalar> thetaOuter_;
//- Parcel size PDF model
const autoPtr<distributionModel> sizeDistribution_;
// Tangential vectors to the direction vector
//- First tangential vector
vector tanVec1_;
//- Second tangential vector
vector tanVec2_;
//- Injection vector orthogonal to direction
vector normal_;
// Velocity model coefficients
//- Constant velocity [m/s]
scalar UMag_;
//- Discharge coefficient, relative to SOI [m/s]
TimeFunction1<scalar> Cd_;
//- Injection pressure [Pa]
TimeFunction1<scalar> Pinj_;
// Private Member Functions
//- Set the injection type
void setInjectionMethod();
//- Set the injection flow type
void setFlowType();
public:
//- Runtime type information
TypeName("coneNozzleInjection");
// Constructors
//- Construct from dictionary
ConeNozzleInjection
(
const dictionary& dict,
CloudType& owner,
const word& modelName
);
//- Construct copy
ConeNozzleInjection(const ConeNozzleInjection<CloudType>& im);
//- Construct and return a clone
virtual autoPtr<InjectionModel<CloudType>> clone() const
{
return autoPtr<InjectionModel<CloudType>>
(
new ConeNozzleInjection<CloudType>(*this)
);
}
//- Destructor
virtual ~ConeNozzleInjection();
// Member Functions
//- Set injector locations when mesh is updated
virtual void updateMesh();
//- Return the end-of-injection time
scalar timeEnd() const;
//- Number of parcels to introduce relative to SOI
virtual label parcelsToInject(const scalar time0, const scalar time1);
//- Volume of parcels to introduce relative to SOI
virtual scalar volumeToInject(const scalar time0, const scalar time1);
// Injection geometry
//- Set the injection position and owner cell
virtual void setPositionAndCell
(
const label parcelI,
const label nParcels,
const scalar time,
vector& position,
label& cellOwner,
label& tetFacei,
label& tetPti
);
//- Set the parcel properties
virtual void setProperties
(
const label parcelI,
const label nParcels,
const scalar time,
typename CloudType::parcelType& parcel
);
//- Flag to identify whether model fully describes the parcel
virtual bool fullyDescribed() const;
//- Return flag to identify whether or not injection of parcelI is
// permitted
virtual bool validInjection(const label parcelI);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "ConeNozzleInjection.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -30,7 +30,6 @@ License
#include "CellZoneInjection.H"
#include "ConeInjection.H"
#include "ConeNozzleInjection.H"
#include "FieldActivatedInjection.H"
#include "InflationInjection.H"
#include "ManualInjection.H"
@ -46,7 +45,6 @@ License
\
makeInjectionModelType(CellZoneInjection, CloudType); \
makeInjectionModelType(ConeInjection, CloudType); \
makeInjectionModelType(ConeNozzleInjection, CloudType); \
makeInjectionModelType(FieldActivatedInjection, CloudType); \
makeInjectionModelType(InflationInjection, CloudType); \
makeInjectionModelType(ManualInjection, CloudType); \

View File

@ -77,15 +77,11 @@ subModels
type coneInjection;
SOI 0.000;
duration 20.000;
positionAxis
(
((0.3 0.35 1.45) (0 0 -1))
((0.6 0.35 1.45) (0 0 -1))
);
position (0.3 0.35 1.45);
direction (0 0 -1);
massTotal 10;
parcelsPerInjector 20000;
parcelsPerSecond 500;
parcelsPerSecond 1000;
parcelBasisType mass;
flowRateProfile constant 0.1;
Umag constant 3.0;
@ -104,6 +100,12 @@ subModels
}
}
}
model2
{
$model1;
position (0.6 0.35 1.45);
}
}
dispersionModel none;

View File

@ -78,14 +78,14 @@ subModels
{
model1
{
type coneNozzleInjection;
type coneInjection;
SOI 0;
massTotal 6.0e-6;
parcelBasisType mass;
injectionMethod disc;
flowType flowRateAndDischarge;
outerDiameter 1.9e-4;
innerDiameter 0;
dInner 0;
dOuter 1.9e-4;
duration 1.25e-3;
position (0 0.0995 0);
direction (0 -1 0);