diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C index cd945d30..47530705 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C @@ -76,14 +76,15 @@ heatTransferGunn::heatTransferGunn partTempField_ ( IOobject ( - "particleTemp", + "partTemp", sm.mesh().time().timeName(), sm.mesh(), IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), 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_ ( IOobject diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C index 6e354810..17be0c17 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C @@ -59,6 +59,7 @@ heatTransferGunnPartField::heatTransferGunnPartField "zeroGradient" ), partRhoField_(sm.mesh().lookupObject("partRho")), + typeCp_(propsDict_.lookupOrDefault("specificHeatCapacities",scalarList(1,-1.0))), partCp_(NULL), thermCondModel_ ( @@ -70,11 +71,16 @@ heatTransferGunnPartField::heatTransferGunnPartField ), fvOptions(fv::options::New(sm.mesh())) { - if(!implicit_) + if (!implicit_) { 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(); } @@ -102,6 +108,19 @@ void heatTransferGunnPartField::calcEnergyContribution() // if heat sources in particles present, pull them here // 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; particleCloud_.averagingM().resetWeightFields(); particleCloud_.averagingM().setScalarAverage @@ -155,19 +174,20 @@ void heatTransferGunnPartField::postFlow() void heatTransferGunnPartField::solve() { 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 partRhoEff = alphaP*partRhoField_; -// volScalarField thCond = thermCondModel_().thermCond(); + volScalarField partCpEff = alphaP*partRhoField_*partCpField_; + volScalarField thCondEff = alphaP*thermCondModel_().thermCond(); +// thCondEff.correctBoundaryConditions(); fvScalarMatrix partTEqn ( Qsource - - fvm::Sp(QPartFluidCoeff_/partCpField_, partTempField_) - // - fvm::laplacian(alphaP*thCond/partCpField_,partTempField_) + - fvm::Sp(QPartFluidCoeff_, partTempField_) + - fvm::laplacian(thCondEff,partTempField_) == - fvOptions(partRhoEff, partTempField_) + fvOptions(partCpEff, partTempField_) ); // if transient add time derivative - need particle density and specific heat fields // if sources activated add sources diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.H b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.H index a52cdec0..a321be7e 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.H @@ -29,6 +29,7 @@ License #include "cfdemCloudEnergy.H" #include "heatTransferGunn.H" #include "fvOptions.H" +#include "scalarList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -48,6 +49,8 @@ private: const volScalarField& partRhoField_; + scalarList typeCp_; + mutable double **partCp_; autoPtr thermCondModel_; diff --git a/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.C b/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.C index 35f816dd..7b8b9a95 100644 --- a/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.C +++ b/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.C @@ -50,9 +50,24 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond : thermCondModel(dict,sm), 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("voidfractionFieldName","voidfraction")), voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), - ks0_(transportProperties_.lookup("ks")), + typeKs_(propsDict_.lookupOrDefault("thermalConductivities",scalarList(1,-1.0))), + partKs_(NULL), wallQFactorName_(propsDict_.lookupOrDefault("wallQFactorName","wallQFactor")), wallQFactor_ ( IOobject @@ -68,6 +83,17 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond ), 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()) { Info << "Found field for scaling wall heat flux.\n" << endl; @@ -79,9 +105,17 @@ ZehnerSchluenderThermCond::ZehnerSchluenderThermCond // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // 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 * * * * * * * * * * * * * // tmp ZehnerSchluenderThermCond::thermCond() const @@ -106,7 +140,8 @@ tmp ZehnerSchluenderThermCond::thermCond() const volScalarField& svf = tvf.ref(); - scalar A = ks0_.value()/kf0_.value(); + calcPartKsField(); + scalar A = 0.0; scalar B = 0.0; scalar C = 0.0; scalar k = 0.0; @@ -116,12 +151,11 @@ tmp ZehnerSchluenderThermCond::thermCond() const forAll(svf, cellI) { - // debugging - Pout << "calculating field in cell " << cellI << endl; 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 { + A = partKsField_[cellI]/kf0_.value(); B = 1.25 * Foam::pow((1 - voidfraction) / voidfraction, 1.11); OnemBoA = 1.0 - B/A; C = (A - 1) / (OnemBoA * OnemBoA) * B/A * log(A/B) - (B - 1)/OnemBoA - 0.5 * (B + 1); @@ -131,8 +165,6 @@ tmp ZehnerSchluenderThermCond::thermCond() const } } - // debugging - Pout << "patch types of svf boundary: " << svf.boundaryField().types() << endl; svf.correctBoundaryConditions(); // if a wallQFactor field is present, use it to scale heat transport through a patch @@ -151,8 +183,35 @@ tmp ZehnerSchluenderThermCond::thermDiff() const 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 diff --git a/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.H b/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.H index 12320d75..b3cafd7c 100644 --- a/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.H +++ b/src/lagrangian/cfdemParticle/subModels/thermCondModel/ZehnerSchluenderThermCond/ZehnerSchluenderThermCond.H @@ -34,6 +34,7 @@ SourceFiles #define ZehnerSchluenderThermCond_H #include "thermCondModel.H" +#include "scalarList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -52,12 +53,16 @@ class ZehnerSchluenderThermCond private: dictionary propsDict_; + + mutable volScalarField partKsField_; word voidfractionFieldName_; const volScalarField& voidfraction_; - dimensionedScalar ks0_; + scalarList typeKs_; + + mutable double **partKs_; word wallQFactorName_; @@ -66,6 +71,10 @@ private: bool hasWallQFactor_; + void allocateMyArrays() const; + + void calcPartKsField() const; + public: //- Runtime type information