ENH: consistent specification of fan conditions (fixes #2279)

This commit is contained in:
Mark Olesen
2021-11-30 09:52:14 +01:00
parent 31a7c2a9cd
commit 49e26dd7d2
7 changed files with 201 additions and 138 deletions

View File

@ -54,8 +54,8 @@ Foam::fanFvPatchField<Type>::fanFvPatchField
rhoName_("rho"),
uniformJump_(false),
nonDimensional_(false),
rpm_(0),
dm_(0)
rpm_(nullptr),
dm_(nullptr)
{}
@ -72,14 +72,14 @@ Foam::fanFvPatchField<Type>::fanFvPatchField
rhoName_(dict.getOrDefault<word>("rho", "rho")),
uniformJump_(dict.getOrDefault("uniformJump", false)),
nonDimensional_(dict.getOrDefault("nonDimensional", false)),
rpm_(0),
dm_(0)
rpm_(nullptr),
dm_(nullptr)
{
// Note that we've not read jumpTable_ etc
if (nonDimensional_)
{
dict.readEntry("rpm", rpm_);
dict.readEntry("dm", dm_);
rpm_.reset(Function1<scalar>::New("rpm", dict, &this->db()));
dm_.reset(Function1<scalar>::New("dm", dict, &this->db()));
}
if (this->cyclicPatch().owner())
@ -104,52 +104,52 @@ Foam::fanFvPatchField<Type>::fanFvPatchField
template<class Type>
Foam::fanFvPatchField<Type>::fanFvPatchField
(
const fanFvPatchField<Type>& ptf,
const fanFvPatchField<Type>& rhs,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
uniformJumpFvPatchField<Type>(ptf, p, iF, mapper),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
uniformJump_(ptf.uniformJump_),
nonDimensional_(ptf.nonDimensional_),
rpm_(ptf.rpm_),
dm_(ptf.dm_)
uniformJumpFvPatchField<Type>(rhs, p, iF, mapper),
phiName_(rhs.phiName_),
rhoName_(rhs.rhoName_),
uniformJump_(rhs.uniformJump_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
template<class Type>
Foam::fanFvPatchField<Type>::fanFvPatchField
(
const fanFvPatchField<Type>& ptf
const fanFvPatchField<Type>& rhs
)
:
uniformJumpFvPatchField<Type>(ptf),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
uniformJump_(ptf.uniformJump_),
nonDimensional_(ptf.nonDimensional_),
rpm_(ptf.rpm_),
dm_(ptf.dm_)
uniformJumpFvPatchField<Type>(rhs),
phiName_(rhs.phiName_),
rhoName_(rhs.rhoName_),
uniformJump_(rhs.uniformJump_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
template<class Type>
Foam::fanFvPatchField<Type>::fanFvPatchField
(
const fanFvPatchField<Type>& ptf,
const fanFvPatchField<Type>& rhs,
const DimensionedField<Type, volMesh>& iF
)
:
uniformJumpFvPatchField<Type>(ptf, iF),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
uniformJump_(ptf.uniformJump_),
nonDimensional_(ptf.nonDimensional_),
rpm_(ptf.rpm_),
dm_(ptf.dm_)
uniformJumpFvPatchField<Type>(rhs, iF),
phiName_(rhs.phiName_),
rhoName_(rhs.rhoName_),
uniformJump_(rhs.uniformJump_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
@ -176,13 +176,17 @@ void Foam::fanFvPatchField<Type>::write(Ostream& os) const
uniformJumpFvPatchField<Type>::write(os);
os.writeEntryIfDifferent<word>("phi", "phi", phiName_);
os.writeEntryIfDifferent<word>("rho", "rho", rhoName_);
os.writeEntryIfDifferent<bool>("uniformJump", false, uniformJump_);
if (uniformJump_)
{
os.writeEntry("uniformJump", "true");
}
if (nonDimensional_)
{
os.writeEntry("nonDimensional", nonDimensional_);
os.writeEntry("rpm", rpm_);
os.writeEntry("dm", dm_);
os.writeEntry("nonDimensional", "true");
rpm_->writeData(os);
dm_->writeData(os);
}
}

View File

@ -69,8 +69,8 @@ Usage
rho | density field name | no | rho
uniformJump | apply uniform pressure based on avg velocity | no | false
nonDimensional | use non-dimensional table | no | false
rpm | fan rpm (non-dimensional table) | no | 0
dm | mean diameter (non-dimensional table) | no | 0
rpm | fan rpm (non-dimensional table) | no |
dm | mean diameter (non-dimensional table) | no |
\endtable
Example of the boundary condition specification:
@ -115,6 +115,7 @@ SourceFiles
#define fanFvPatchField_H
#include "uniformJumpFvPatchField.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -130,7 +131,7 @@ class fanFvPatchField
:
public uniformJumpFvPatchField<Type>
{
// Private data
// Private Data
//- Name of the flux transporting the field
word phiName_;
@ -144,13 +145,11 @@ class fanFvPatchField
//- Use non-dimensional curve
bool nonDimensional_;
// Parameters for non-dimensional table
//- Fan rpm (for non-dimensional curve)
autoPtr<Function1<scalar>> rpm_;
//- Fan rpm
scalar rpm_;
//- Fan mean diameter
scalar dm_;
//- Fan mean diameter (for non-dimensional curve)
autoPtr<Function1<scalar>> dm_;
// Private Member Functions

View File

@ -45,17 +45,35 @@ void Foam::fanFvPatchField<Foam::scalar>::calcFanJump()
patch().patchField<surfaceScalarField, scalar>(phi);
scalarField Un(max(phip/patch().magSf(), scalar(0)));
// The non-dimensional parameters
scalar rpm(0);
scalar meanDiam(0);
if (nonDimensional_)
{
rpm = rpm_->value(this->db().time().timeOutputValue());
meanDiam = dm_->value(this->db().time().timeOutputValue());
}
if (uniformJump_)
{
scalar area = gSum(patch().magSf());
const scalar area = gSum(patch().magSf());
Un = gSum(Un*patch().magSf())/area;
if (nonDimensional_)
{
// Create an non-dimensional velocity
Un =
120.0*Un/pow3(constant::mathematical::pi)
/ dm_/rpm_;
(
120.0*Un
/ stabilise
(
pow3(constant::mathematical::pi) * meanDiam * rpm,
VSMALL
)
);
}
}
@ -71,7 +89,8 @@ void Foam::fanFvPatchField<Foam::scalar>::calcFanJump()
// Convert non-dimensional deltap from curve into deltaP
scalarField pdFan
(
deltap*pow4(constant::mathematical::pi)*sqr(dm_*rpm_)/1800.0
deltap*pow4(constant::mathematical::pi)
* sqr(meanDiam*rpm)/1800.0
);
this->setJump(pdFan);

View File

@ -57,25 +57,25 @@ Foam::fanPressureFvPatchScalarField::fanPressureFvPatchScalarField
fanCurve_(nullptr),
direction_(ffdOut),
nonDimensional_(false),
rpm_(0),
dm_(0)
rpm_(nullptr),
dm_(nullptr)
{}
Foam::fanPressureFvPatchScalarField::fanPressureFvPatchScalarField
(
const fanPressureFvPatchScalarField& ptf,
const fanPressureFvPatchScalarField& rhs,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
totalPressureFvPatchScalarField(ptf, p, iF, mapper),
fanCurve_(ptf.fanCurve_.clone()),
direction_(ptf.direction_),
nonDimensional_(ptf.nonDimensional_),
rpm_(ptf.rpm_),
dm_(ptf.dm_)
totalPressureFvPatchScalarField(rhs, p, iF, mapper),
fanCurve_(rhs.fanCurve_.clone()),
direction_(rhs.direction_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
@ -90,56 +90,56 @@ Foam::fanPressureFvPatchScalarField::fanPressureFvPatchScalarField
fanCurve_(nullptr),
direction_(fanFlowDirectionNames_.get("direction", dict)),
nonDimensional_(dict.getOrDefault("nonDimensional", false)),
rpm_(0),
dm_(0)
rpm_(nullptr),
dm_(nullptr)
{
// Backwards compatibility
if (dict.found("file"))
{
fanCurve_.reset
(
new Function1Types::TableFile<scalar>("fanCurve", dict)
new Function1Types::TableFile<scalar>("fanCurve", dict, &this->db())
);
}
else
{
fanCurve_.reset(Function1<scalar>::New("fanCurve", dict, &db()));
fanCurve_.reset(Function1<scalar>::New("fanCurve", dict, &this->db()));
}
if (nonDimensional_)
{
dict.readEntry("rpm", rpm_);
dict.readEntry("dm", dm_);
rpm_.reset(Function1<scalar>::New("rpm", dict, &this->db()));
dm_.reset(Function1<scalar>::New("dm", dict, &this->db()));
}
}
Foam::fanPressureFvPatchScalarField::fanPressureFvPatchScalarField
(
const fanPressureFvPatchScalarField& fppsf
const fanPressureFvPatchScalarField& rhs
)
:
totalPressureFvPatchScalarField(fppsf),
fanCurve_(fppsf.fanCurve_.clone()),
direction_(fppsf.direction_),
nonDimensional_(fppsf.nonDimensional_),
rpm_(fppsf.rpm_),
dm_(fppsf.dm_)
totalPressureFvPatchScalarField(rhs),
fanCurve_(rhs.fanCurve_.clone()),
direction_(rhs.direction_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
Foam::fanPressureFvPatchScalarField::fanPressureFvPatchScalarField
(
const fanPressureFvPatchScalarField& fppsf,
const fanPressureFvPatchScalarField& rhs,
const DimensionedField<scalar, volMesh>& iF
)
:
totalPressureFvPatchScalarField(fppsf, iF),
fanCurve_(fppsf.fanCurve_.clone()),
direction_(fppsf.direction_),
nonDimensional_(fppsf.nonDimensional_),
rpm_(fppsf.rpm_),
dm_(fppsf.dm_)
totalPressureFvPatchScalarField(rhs, iF),
fanCurve_(rhs.fanCurve_.clone()),
direction_(rhs.direction_),
nonDimensional_(rhs.nonDimensional_),
rpm_(rhs.rpm_.clone()),
dm_(rhs.dm_.clone())
{}
@ -182,11 +182,24 @@ void Foam::fanPressureFvPatchScalarField::updateCoeffs()
<< exit(FatalError);
}
// The non-dimensional parameters
scalar rpm(0);
scalar meanDiam(0);
if (nonDimensional_)
{
rpm = rpm_->value(this->db().time().timeOutputValue());
meanDiam = dm_->value(this->db().time().timeOutputValue());
// Create an non-dimensional flow rate
volFlowRate =
120.0*volFlowRate/pow3(constant::mathematical::pi)/pow3(dm_)/rpm_;
120.0*volFlowRate
/ stabilise
(
pow3(constant::mathematical::pi * meanDiam) * rpm,
VSMALL
);
}
// Pressure drop for this flow rate
@ -195,7 +208,11 @@ void Foam::fanPressureFvPatchScalarField::updateCoeffs()
if (nonDimensional_)
{
// Convert the non-dimensional deltap from curve into deltaP
pdFan = pdFan*pow4(constant::mathematical::pi)*sqr(dm_*rpm_)/1800;
pdFan =
(
pdFan*pow4(constant::mathematical::pi)
* sqr(rpm * meanDiam) / 1800.0
);
}
totalPressureFvPatchScalarField::updateCoeffs
@ -215,8 +232,8 @@ void Foam::fanPressureFvPatchScalarField::write(Ostream& os) const
if (nonDimensional_)
{
os.writeEntry("nonDimensional", "true");
os.writeEntry("rpm", rpm_);
os.writeEntry("dm", dm_);
rpm_->writeData(os);
dm_->writeData(os);
}
}

View File

@ -59,8 +59,8 @@ Usage
direction | direction of flow through fan [in/out] | yes |
p0 | environmental total pressure | yes |
nonDimensional | uses non-dimensional table | no | false
rpm | fan rpm for non-dimensional table | no | 0
dm | mean diameter for non-dimensional table | no | 0.0
rpm | fan rpm for non-dimensional table | no |
dm | mean diameter for non-dimensional table | no |
file | fan curve file name | legacy |
outOfBounds | out of bounds handling | legacy |
\endtable
@ -154,10 +154,10 @@ private:
bool nonDimensional_;
//- Fan rpm (for non-dimensional curve)
scalar rpm_;
autoPtr<Function1<scalar>> rpm_;
//- Fan mean diameter (for non-dimensional curve)
scalar dm_;
autoPtr<Function1<scalar>> dm_;
public:

View File

@ -84,7 +84,14 @@ void Foam::swirlFanVelocityFvPatchField::calcFanJump()
if (rMag > rInner_ && rMag < rOuter_)
{
magTangU[i] =
deltaP[i]/rMag/fanEff_/rpmToRads(rpm);
(
deltaP[i]
/ stabilise
(
fanEff_ * rMag * rpmToRads(rpm),
VSMALL
)
);
}
}
}
@ -93,12 +100,19 @@ void Foam::swirlFanVelocityFvPatchField::calcFanJump()
if (rEff_ <= 0)
{
FatalErrorInFunction
<< "Effective radius rEff should be specified in the "<< nl
<< "Effective radius 'rEff' was ill-specified in the "
<< "dictionary." << nl
<< exit(FatalError);
}
magTangU =
deltaP/rEff_/fanEff_/rpmToRads(rpm);
(
deltaP
/ stabilise
(
fanEff_ * rEff_ * rpmToRads(rpm),
VSMALL
)
);
}
// Calculate the tangential velocity
@ -122,11 +136,11 @@ Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
pName_("p"),
rhoName_("rho"),
origin_(),
rpm_(),
rEff_(0.0),
fanEff_(1.0),
rInner_(0.0),
rOuter_(0.0),
rpm_(nullptr),
fanEff_(1),
rEff_(0),
rInner_(0),
rOuter_(0),
useRealRadius_(false)
{}
@ -158,8 +172,8 @@ Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
? Function1<scalar>::New("rpm", dict, &db())
: nullptr
),
rEff_(dict.getOrDefault<scalar>("rEff", 0)),
fanEff_(dict.getOrDefault<scalar>("fanEff", 1)),
rEff_(dict.getOrDefault<scalar>("rEff", 0)),
rInner_(dict.getOrDefault<scalar>("rInner", 0)),
rOuter_(dict.getOrDefault<scalar>("rOuter", 0)),
useRealRadius_(dict.getOrDefault("useRealRadius", false))
@ -168,60 +182,62 @@ Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
(
const swirlFanVelocityFvPatchField& ptf,
const swirlFanVelocityFvPatchField& rhs,
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fixedJumpFvPatchField<vector>(ptf, p, iF, mapper),
phiName_(ptf.phiName_),
pName_(ptf.pName_),
rhoName_(ptf.rhoName_),
origin_(ptf.origin_),
rpm_(ptf.rpm_.clone()),
rEff_(ptf.rEff_),
fanEff_(ptf.fanEff_),
rInner_(ptf.rInner_),
rOuter_(ptf.rOuter_),
useRealRadius_(ptf.useRealRadius_)
fixedJumpFvPatchField<vector>(rhs, p, iF, mapper),
phiName_(rhs.phiName_),
pName_(rhs.pName_),
rhoName_(rhs.rhoName_),
origin_(rhs.origin_),
rpm_(rhs.rpm_.clone()),
fanEff_(rhs.fanEff_),
rEff_(rhs.rEff_),
rInner_(rhs.rInner_),
rOuter_(rhs.rOuter_),
useRealRadius_(rhs.useRealRadius_)
{}
Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
(
const swirlFanVelocityFvPatchField& ptf
const swirlFanVelocityFvPatchField& rhs
)
:
fixedJumpFvPatchField<vector>(ptf),
phiName_(ptf.phiName_),
pName_(ptf.pName_),
rhoName_(ptf.rhoName_),
origin_(ptf.origin_),
rpm_(ptf.rpm_.clone()),
rEff_(ptf.rEff_),
rInner_(ptf.rInner_),
rOuter_(ptf.rOuter_),
useRealRadius_(ptf.useRealRadius_)
fixedJumpFvPatchField<vector>(rhs),
phiName_(rhs.phiName_),
pName_(rhs.pName_),
rhoName_(rhs.rhoName_),
origin_(rhs.origin_),
rpm_(rhs.rpm_.clone()),
fanEff_(rhs.fanEff_),
rEff_(rhs.rEff_),
rInner_(rhs.rInner_),
rOuter_(rhs.rOuter_),
useRealRadius_(rhs.useRealRadius_)
{}
Foam::swirlFanVelocityFvPatchField::swirlFanVelocityFvPatchField
(
const swirlFanVelocityFvPatchField& ptf,
const swirlFanVelocityFvPatchField& rhs,
const DimensionedField<vector, volMesh>& iF
)
:
fixedJumpFvPatchField<vector>(ptf, iF),
phiName_(ptf.phiName_),
pName_(ptf.pName_),
rhoName_(ptf.rhoName_),
origin_(ptf.origin_),
rpm_(ptf.rpm_.clone()),
rEff_(ptf.rEff_),
rInner_(ptf.rInner_),
rOuter_(ptf.rOuter_),
useRealRadius_(ptf.useRealRadius_)
fixedJumpFvPatchField<vector>(rhs, iF),
phiName_(rhs.phiName_),
pName_(rhs.pName_),
rhoName_(rhs.rhoName_),
origin_(rhs.origin_),
rpm_(rhs.rpm_.clone()),
fanEff_(rhs.fanEff_),
rEff_(rhs.rEff_),
rInner_(rhs.rInner_),
rOuter_(rhs.rOuter_),
useRealRadius_(rhs.useRealRadius_)
{}
@ -254,10 +270,18 @@ void Foam::swirlFanVelocityFvPatchField::write(Ostream& os) const
rpm_->writeData(os);
}
os.writeEntryIfDifferent<scalar>("rEff", 0.0, rEff_);
os.writeEntryIfDifferent<bool>("useRealRadius", false, useRealRadius_);
os.writeEntryIfDifferent<scalar>("rInner", 0.0, rInner_);
os.writeEntryIfDifferent<scalar>("rOuter", 0.0, rOuter_);
os.writeEntryIfDifferent<scalar>("fanEff", 1, rEff_);
if (useRealRadius_)
{
os.writeEntry("useRealRadius", "true");
os.writeEntryIfDifferent<scalar>("rInner", 0, rInner_);
os.writeEntryIfDifferent<scalar>("rOuter", 0, rOuter_);
}
else
{
os.writeEntryIfDifferent<scalar>("rEff", 0, rEff_);
}
}
}

View File

@ -73,11 +73,11 @@ Usage
p | pressure field name | no | p
origin | fan centre | no | calculated
rpm | RPM of the fan | yes
rEff | Effective radius | no | 0.0
fanEff | Fan efficiency | no | 1.0
fanEff | Fan efficiency | no | 1
rEff | Effective radius | no | 0
useRealRadius| Use inner/outer radii | no | false
rInner | Inner radius | no | 0.0
rOuter | Outer radius | no | 0.0
rInner | Inner radius | no | 0
rOuter | Outer radius | no | 0
\endtable
Example of the boundary condition specification:
@ -137,12 +137,12 @@ class swirlFanVelocityFvPatchField
//- Fan rpm
autoPtr<Function1<scalar>> rpm_;
//- Effective fan radius
scalar rEff_;
//- Fan efficiency
scalar fanEff_;
//- Effective fan radius
scalar rEff_;
//- Inner radius
scalar rInner_;