mirror of
https://github.com/ParticulateFlow/CFDEMcoupling-PFM.git
synced 2025-12-08 06:37:44 +00:00
Specific heat and thermal conductivities for various species.
This commit is contained in:
@ -76,14 +76,15 @@ heatTransferGunn::heatTransferGunn
|
|||||||
partTempField_
|
partTempField_
|
||||||
( IOobject
|
( IOobject
|
||||||
(
|
(
|
||||||
"particleTemp",
|
"partTemp",
|
||||||
sm.mesh().time().timeName(),
|
sm.mesh().time().timeName(),
|
||||||
sm.mesh(),
|
sm.mesh(),
|
||||||
IOobject::READ_IF_PRESENT,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
sm.mesh(),
|
sm.mesh(),
|
||||||
dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0)
|
dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0),
|
||||||
|
"zeroGradient"
|
||||||
),
|
),
|
||||||
partRelTempField_
|
partRelTempField_
|
||||||
( IOobject
|
( IOobject
|
||||||
|
|||||||
@ -59,6 +59,7 @@ heatTransferGunnPartField::heatTransferGunnPartField
|
|||||||
"zeroGradient"
|
"zeroGradient"
|
||||||
),
|
),
|
||||||
partRhoField_(sm.mesh().lookupObject<volScalarField>("partRho")),
|
partRhoField_(sm.mesh().lookupObject<volScalarField>("partRho")),
|
||||||
|
typeCp_(propsDict_.lookupOrDefault<scalarList>("specificHeatCapacities",scalarList(1,-1.0))),
|
||||||
partCp_(NULL),
|
partCp_(NULL),
|
||||||
thermCondModel_
|
thermCondModel_
|
||||||
(
|
(
|
||||||
@ -70,11 +71,16 @@ heatTransferGunnPartField::heatTransferGunnPartField
|
|||||||
),
|
),
|
||||||
fvOptions(fv::options::New(sm.mesh()))
|
fvOptions(fv::options::New(sm.mesh()))
|
||||||
{
|
{
|
||||||
if(!implicit_)
|
if (!implicit_)
|
||||||
{
|
{
|
||||||
FatalError << "heatTransferGunnPartField requires implicit heat transfer treatment." << abort(FatalError);
|
FatalError << "heatTransferGunnPartField requires implicit heat transfer treatment." << abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeCp_[0] < 0.0)
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferGunnPartField: provide list of specific heat capacities." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
allocateMyArrays();
|
allocateMyArrays();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +108,19 @@ void heatTransferGunnPartField::calcEnergyContribution()
|
|||||||
// if heat sources in particles present, pull them here
|
// if heat sources in particles present, pull them here
|
||||||
|
|
||||||
// loop over all particles to fill partCp_ based on type
|
// loop over all particles to fill partCp_ based on type
|
||||||
|
label cellI=0;
|
||||||
|
label partType = 0;
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if(cellI >= 0)
|
||||||
|
{
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
||||||
|
partCp_[index][0] = typeCp_[partType - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
partCpField_.primitiveFieldRef() = 0.0;
|
partCpField_.primitiveFieldRef() = 0.0;
|
||||||
particleCloud_.averagingM().resetWeightFields();
|
particleCloud_.averagingM().resetWeightFields();
|
||||||
particleCloud_.averagingM().setScalarAverage
|
particleCloud_.averagingM().setScalarAverage
|
||||||
@ -155,19 +174,20 @@ void heatTransferGunnPartField::postFlow()
|
|||||||
void heatTransferGunnPartField::solve()
|
void heatTransferGunnPartField::solve()
|
||||||
{
|
{
|
||||||
Info << "patch types of partTemp boundary: " << partTempField_.boundaryField().types() << endl;
|
Info << "patch types of partTemp boundary: " << partTempField_.boundaryField().types() << endl;
|
||||||
volScalarField Qsource = QPartFluidCoeff_*tempField_/partCpField_;
|
volScalarField Qsource = QPartFluidCoeff_*tempField_;
|
||||||
volScalarField alphaP = 1.0 - voidfraction_;
|
volScalarField alphaP = 1.0 - voidfraction_;
|
||||||
volScalarField partRhoEff = alphaP*partRhoField_;
|
volScalarField partCpEff = alphaP*partRhoField_*partCpField_;
|
||||||
// volScalarField thCond = thermCondModel_().thermCond();
|
volScalarField thCondEff = alphaP*thermCondModel_().thermCond();
|
||||||
|
// thCondEff.correctBoundaryConditions();
|
||||||
|
|
||||||
|
|
||||||
fvScalarMatrix partTEqn
|
fvScalarMatrix partTEqn
|
||||||
(
|
(
|
||||||
Qsource
|
Qsource
|
||||||
- fvm::Sp(QPartFluidCoeff_/partCpField_, partTempField_)
|
- fvm::Sp(QPartFluidCoeff_, partTempField_)
|
||||||
// - fvm::laplacian(alphaP*thCond/partCpField_,partTempField_)
|
- fvm::laplacian(thCondEff,partTempField_)
|
||||||
==
|
==
|
||||||
fvOptions(partRhoEff, partTempField_)
|
fvOptions(partCpEff, partTempField_)
|
||||||
);
|
);
|
||||||
// if transient add time derivative - need particle density and specific heat fields
|
// if transient add time derivative - need particle density and specific heat fields
|
||||||
// if sources activated add sources
|
// if sources activated add sources
|
||||||
|
|||||||
@ -29,6 +29,7 @@ License
|
|||||||
#include "cfdemCloudEnergy.H"
|
#include "cfdemCloudEnergy.H"
|
||||||
#include "heatTransferGunn.H"
|
#include "heatTransferGunn.H"
|
||||||
#include "fvOptions.H"
|
#include "fvOptions.H"
|
||||||
|
#include "scalarList.H"
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
@ -48,6 +49,8 @@ private:
|
|||||||
|
|
||||||
const volScalarField& partRhoField_;
|
const volScalarField& partRhoField_;
|
||||||
|
|
||||||
|
scalarList typeCp_;
|
||||||
|
|
||||||
mutable double **partCp_;
|
mutable double **partCp_;
|
||||||
|
|
||||||
autoPtr<thermCondModel> thermCondModel_;
|
autoPtr<thermCondModel> thermCondModel_;
|
||||||
|
|||||||
@ -50,9 +50,24 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond
|
|||||||
:
|
:
|
||||||
thermCondModel(dict,sm),
|
thermCondModel(dict,sm),
|
||||||
propsDict_(dict.subDict(typeName + "Props")),
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
partKsField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"partKs",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
ks0_(transportProperties_.lookup("ks")),
|
typeKs_(propsDict_.lookupOrDefault<scalarList>("thermalConductivities",scalarList(1,-1.0))),
|
||||||
|
partKs_(NULL),
|
||||||
wallQFactorName_(propsDict_.lookupOrDefault<word>("wallQFactorName","wallQFactor")),
|
wallQFactorName_(propsDict_.lookupOrDefault<word>("wallQFactorName","wallQFactor")),
|
||||||
wallQFactor_
|
wallQFactor_
|
||||||
( IOobject
|
( IOobject
|
||||||
@ -68,6 +83,17 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond
|
|||||||
),
|
),
|
||||||
hasWallQFactor_(false)
|
hasWallQFactor_(false)
|
||||||
{
|
{
|
||||||
|
if (typeKs_[0] < 0.0)
|
||||||
|
{
|
||||||
|
FatalError << "ZehnerSchluenderThermCond: provide list of thermal conductivities." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeKs_.size() > 1) allocateMyArrays();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
partKsField_ *= typeKs_[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (wallQFactor_.headerOk())
|
if (wallQFactor_.headerOk())
|
||||||
{
|
{
|
||||||
Info << "Found field for scaling wall heat flux.\n" << endl;
|
Info << "Found field for scaling wall heat flux.\n" << endl;
|
||||||
@ -79,9 +105,17 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond
|
|||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
ZehnerSchluenderThermCond::~ZehnerSchluenderThermCond()
|
ZehnerSchluenderThermCond::~ZehnerSchluenderThermCond()
|
||||||
{}
|
{
|
||||||
|
if (typeKs_.size() > 1) particleCloud_.dataExchangeM().destroy(partKs_,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ZehnerSchluenderThermCond::allocateMyArrays() const
|
||||||
|
{
|
||||||
|
double initVal=0.0;
|
||||||
|
particleCloud_.dataExchangeM().allocateArray(partKs_,initVal,1);
|
||||||
|
}
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
tmp<volScalarField> ZehnerSchluenderThermCond::thermCond() const
|
tmp<volScalarField> ZehnerSchluenderThermCond::thermCond() const
|
||||||
@ -106,7 +140,8 @@ tmp<volScalarField> ZehnerSchluenderThermCond::thermCond() const
|
|||||||
|
|
||||||
volScalarField& svf = tvf.ref();
|
volScalarField& svf = tvf.ref();
|
||||||
|
|
||||||
scalar A = ks0_.value()/kf0_.value();
|
calcPartKsField();
|
||||||
|
scalar A = 0.0;
|
||||||
scalar B = 0.0;
|
scalar B = 0.0;
|
||||||
scalar C = 0.0;
|
scalar C = 0.0;
|
||||||
scalar k = 0.0;
|
scalar k = 0.0;
|
||||||
@ -116,12 +151,11 @@ tmp<volScalarField> ZehnerSchluenderThermCond::thermCond() const
|
|||||||
|
|
||||||
forAll(svf, cellI)
|
forAll(svf, cellI)
|
||||||
{
|
{
|
||||||
// debugging
|
|
||||||
Pout << "calculating field in cell " << cellI << endl;
|
|
||||||
voidfraction = voidfraction_[cellI];
|
voidfraction = voidfraction_[cellI];
|
||||||
if(voidfraction > 1.0 - SMALL) svf[cellI] = 0.0;
|
if(voidfraction > 1.0 - SMALL || partKsField_[cellI] < SMALL) svf[cellI] = 0.0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
A = partKsField_[cellI]/kf0_.value();
|
||||||
B = 1.25 * Foam::pow((1 - voidfraction) / voidfraction, 1.11);
|
B = 1.25 * Foam::pow((1 - voidfraction) / voidfraction, 1.11);
|
||||||
OnemBoA = 1.0 - B/A;
|
OnemBoA = 1.0 - B/A;
|
||||||
C = (A - 1) / (OnemBoA * OnemBoA) * B/A * log(A/B) - (B - 1)/OnemBoA - 0.5 * (B + 1);
|
C = (A - 1) / (OnemBoA * OnemBoA) * B/A * log(A/B) - (B - 1)/OnemBoA - 0.5 * (B + 1);
|
||||||
@ -131,8 +165,6 @@ tmp<volScalarField> ZehnerSchluenderThermCond::thermCond() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// debugging
|
|
||||||
Pout << "patch types of svf boundary: " << svf.boundaryField().types() << endl;
|
|
||||||
svf.correctBoundaryConditions();
|
svf.correctBoundaryConditions();
|
||||||
|
|
||||||
// if a wallQFactor field is present, use it to scale heat transport through a patch
|
// if a wallQFactor field is present, use it to scale heat transport through a patch
|
||||||
@ -151,8 +183,35 @@ tmp<volScalarField> ZehnerSchluenderThermCond::thermDiff() const
|
|||||||
FatalError << "ZehnerSchluenderThermCond does not provide thermal diffusivity." << abort(FatalError);
|
FatalError << "ZehnerSchluenderThermCond does not provide thermal diffusivity." << abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZehnerSchluenderThermCond::calcPartKsField() const
|
||||||
|
{
|
||||||
|
if (typeKs_.size() <= 1) return;
|
||||||
|
|
||||||
|
allocateMyArrays();
|
||||||
|
label cellI=0;
|
||||||
|
label partType = 0;
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if(cellI >= 0)
|
||||||
|
{
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
||||||
|
partKs_[index][0] = typeKs_[partType - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partKsField_.primitiveFieldRef() = 0.0;
|
||||||
|
particleCloud_.averagingM().resetWeightFields();
|
||||||
|
particleCloud_.averagingM().setScalarAverage
|
||||||
|
(
|
||||||
|
partKsField_,
|
||||||
|
partKs_,
|
||||||
|
particleCloud_.particleWeights(),
|
||||||
|
particleCloud_.averagingM().UsWeightField(),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|||||||
@ -34,6 +34,7 @@ SourceFiles
|
|||||||
#define ZehnerSchluenderThermCond_H
|
#define ZehnerSchluenderThermCond_H
|
||||||
|
|
||||||
#include "thermCondModel.H"
|
#include "thermCondModel.H"
|
||||||
|
#include "scalarList.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -53,11 +54,15 @@ private:
|
|||||||
|
|
||||||
dictionary propsDict_;
|
dictionary propsDict_;
|
||||||
|
|
||||||
|
mutable volScalarField partKsField_;
|
||||||
|
|
||||||
word voidfractionFieldName_;
|
word voidfractionFieldName_;
|
||||||
|
|
||||||
const volScalarField& voidfraction_;
|
const volScalarField& voidfraction_;
|
||||||
|
|
||||||
dimensionedScalar ks0_;
|
scalarList typeKs_;
|
||||||
|
|
||||||
|
mutable double **partKs_;
|
||||||
|
|
||||||
word wallQFactorName_;
|
word wallQFactorName_;
|
||||||
|
|
||||||
@ -66,6 +71,10 @@ private:
|
|||||||
|
|
||||||
bool hasWallQFactor_;
|
bool hasWallQFactor_;
|
||||||
|
|
||||||
|
void allocateMyArrays() const;
|
||||||
|
|
||||||
|
void calcPartKsField() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
|
|||||||
Reference in New Issue
Block a user