From 0e17be2620585cf30fe7481ce8494326cda1037e Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 14 May 2018 13:17:00 +0200 Subject: [PATCH 01/47] Added extended virtualMassForce model --- .../cfdemParticle/cfdemCloud/cfdemCloud.C | 4 + .../cfdemParticle/cfdemCloud/cfdemCloud.H | 8 + .../cfdemParticle/cfdemCloud/cfdemCloudI.H | 16 ++ .../virtualMassForce/virtualMassForce.C | 147 +++++++++++++----- .../virtualMassForce/virtualMassForce.H | 17 +- 5 files changed, 153 insertions(+), 39 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index 89e2cead..a94d7851 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -93,6 +93,7 @@ cfdemCloud::cfdemCloud DEMForces_(NULL), Cds_(NULL), radii_(NULL), + densities_(NULL), voidfractions_(NULL), cellIDs_(NULL), particleWeights_(NULL), @@ -353,6 +354,7 @@ cfdemCloud::~cfdemCloud() dataExchangeM().destroy(DEMForces_,3); dataExchangeM().destroy(Cds_,1); dataExchangeM().destroy(radii_,1); + dataExchangeM().destroy(densities_,1); dataExchangeM().destroy(voidfractions_,1); dataExchangeM().destroy(cellIDs_,1); dataExchangeM().destroy(particleWeights_,1); @@ -364,6 +366,7 @@ cfdemCloud::~cfdemCloud() void cfdemCloud::getDEMdata() { dataExchangeM().getData("radius","scalar-atom",radii_); + dataExchangeM().getData("density","scalar-atom",densities_); dataExchangeM().getData("x","vector-atom",positions_); dataExchangeM().getData("v","vector-atom",velocities_); @@ -698,6 +701,7 @@ bool cfdemCloud::reAllocArrays() dataExchangeM().allocateArray(DEMForces_,0.,3); dataExchangeM().allocateArray(Cds_,0.,1); dataExchangeM().allocateArray(radii_,0.,1); + dataExchangeM().allocateArray(densities_,0.,1); dataExchangeM().allocateArray(voidfractions_,1.,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(cellIDs_,-1,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(particleWeights_,0.,voidFractionM().maxCellsPerParticle()); diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H index b17b6381..bc8d011d 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H @@ -118,6 +118,8 @@ protected: mutable double **radii_; + mutable double **densities_; + mutable double **voidfractions_; mutable int **cellIDs_; @@ -298,10 +300,14 @@ public: inline double ** radii() const; + inline double ** densities() const; + inline double ** voidfractions() const; inline void get_radii(double**&) const; + inline void get_densities(double**&) const; + inline int ** cellIDs() const; inline void get_cellIDs(int**&) const; @@ -314,6 +320,8 @@ public: inline scalar radius(int) const; + inline scalar density(int) const; + virtual inline double d(int) const; inline scalar d32(bool recalc=true); diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H index 2fbe1744..c8e1297d 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H @@ -145,6 +145,12 @@ inline double ** cfdemCloud::radii() const return radii_; } +inline double ** cfdemCloud::densities() const +{ + return densities_; +} + + inline double ** cfdemCloud::voidfractions() const { return voidfractions_; @@ -159,6 +165,11 @@ inline void cfdemCloud::get_radii(double **& values) const values=radii_; } +inline void cfdemCloud::get_densities(double **& values) const +{ + values=densities_; +} + inline int ** cfdemCloud::cellIDs() const { return cellIDs_; @@ -192,6 +203,11 @@ inline scalar cfdemCloud::radius(int index) const return radii_[index][0]; } +inline scalar cfdemCloud::density(int index) const +{ + return densities_[index][0]; +} + inline double cfdemCloud::d(int index) const { return 2.*radii_[index][0]; diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 2d33a4fb..8915d1c4 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -67,10 +67,16 @@ virtualMassForce::virtualMassForce propsDict_(dict.subDict(typeName + "Props")), velFieldName_(propsDict_.lookup("velFieldName")), U_(sm.mesh().lookupObject (velFieldName_)), + voidfractionFieldName_(propsDict_.lookup("voidfractionFieldName")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + UsFieldName_(propsDict_.lookup("UsFieldName")), + Us_(sm.mesh().lookupObject (UsFieldName_)), phiFieldName_(propsDict_.lookup("phiFieldName")), phi_(sm.mesh().lookupObject (phiFieldName_)), UrelOld_(NULL), splitUrelCalculation_(false), + useUs_(false), + useFelderhof_(false), Cadd_(0.5) { @@ -102,15 +108,32 @@ virtualMassForce::virtualMassForce Cadd_ = readScalar(propsDict_.lookup("Cadd")); Info << "Virtual mass model: using non-standard Cadd = " << Cadd_ << endl; } + if(propsDict_.found("useUs")) + { + useUs_ = readBool(propsDict_.lookup("useUs")); + if(useUs_) + { + Info << "Virtual mass model: using averaged Us"; + Info << "WARNING: ignoring virtual mass of relative particle motion/collisions \n"; + } + } + if(propsDict_.found("useFelderhof")) + { + useFelderhof_ = readBool(propsDict_.lookup("useFelderhof")); + if(useFelderhof_) + { + Info << "Virtual mass model: using Cadd correlation by Felderhof"; + Info << "WARNING: ignoring user-set Cadd \n"; + } + } particleCloud_.checkCG(true); //Append the field names to be probed particleCloud_.probeM().initialize(typeName, typeName+".logDat"); particleCloud_.probeM().vectorFields_.append("virtualMassForce"); //first entry must the be the force - particleCloud_.probeM().vectorFields_.append("Urel"); - particleCloud_.probeM().vectorFields_.append("UrelOld"); - particleCloud_.probeM().vectorFields_.append("ddtUrel"); + particleCloud_.probeM().vectorFields_.append("acceleration"); + particleCloud_.probeM().scalarFields_.append("Cadd"); particleCloud_.probeM().scalarFields_.append("Vs"); particleCloud_.probeM().scalarFields_.append("rho"); particleCloud_.probeM().writeHeader(); @@ -135,16 +158,33 @@ void virtualMassForce::setForce() const vector position(0,0,0); vector Ufluid(0,0,0); - vector Ur(0,0,0); + vector Urel(0,0,0); vector DDtU(0,0,0); + vector ddtUs(0,0,0); + vector Us(0,0,0); + vector UrelOld(0,0,0); + vector ddtUrel(0,0,0); + vector accel(0,0,0); - //Compute extra vfields in case it is needed + scalar voidfraction(1); + scalar epsilons(0); + scalar sg(1); + scalar logsg(0); + + //DDtU volVectorField DDtU_(0.0*U_/U_.mesh().time().deltaT()); - if(splitUrelCalculation_) + if(splitUrelCalculation_ || useUs_ ) DDtU_ = fvc::ddt(U_) + fvc::div(phi_, U_); //Total Derivative of fluid velocity + //ddtUs + volVectorField ddtUs_(0.0*U_/U_.mesh().time().deltaT()); + if (useUs_) + ddtUs_ = fvc::ddt(Us_); + interpolationCellPoint UInterpolator_( U_); + interpolationCellPoint ddtUsInterpolator_(ddtUs_); interpolationCellPoint DDtUInterpolator_(DDtU_); + interpolationCellPoint voidfractionInterpolator_(voidfraction_); #include "setupProbeModel.H" @@ -157,7 +197,7 @@ void virtualMassForce::setForce() const if (cellI > -1) // particle Found { - + // particle position and fluid velocity if(forceSubM(0).interpolation()) { position = particleCloud_.position(index); @@ -168,47 +208,81 @@ void virtualMassForce::setForce() const Ufluid = U_[cellI]; } - - if(splitUrelCalculation_) //if split, just use total derivative of fluid velocity - if(forceSubM(0).interpolation()) + // DDtU / relative velocity + if(splitUrelCalculation_ || useUs_ ) { - DDtU = DDtUInterpolator_.interpolate(position,cellI); + if(forceSubM(0).interpolation()) + DDtU = DDtUInterpolator_.interpolate(position,cellI); + else + DDtU = DDtU_[cellI]; } else { - DDtU = DDtU_[cellI]; + Us = particleCloud_.velocity(index); + Urel = Ufluid - Us; } - else + + // averaged Us + if(useUs_ && !splitUrelCalculation_ ) { - vector Us = particleCloud_.velocity(index); - Ur = Ufluid - Us; + if(forceSubM(0).interpolation()) + ddtUs = ddtUsInterpolator_.interpolate(position,cellI); + else + ddtUs = ddtUs_[cellI]; } - - //Check of particle was on this CPU the last step - if(UrelOld_[index][0]==NOTONCPU) //use 1. element to indicate that particle was on this CPU the last time step - haveUrelOld_ = false; - else - haveUrelOld_ = true; - - vector UrelOld(0.,0.,0.); - vector ddtUrel(0.,0.,0.); - for(int j=0;j<3;j++) + // ddtUrel from UrelOld + if (!useUs_ || !splitUrelCalculation_ ) { - UrelOld[j] = UrelOld_[index][j]; - UrelOld_[index][j] = Ur[j]; + //Check of particle was on this CPU the last step + if(UrelOld_[index][0]==NOTONCPU) //use 1. element to indicate that particle was on this CPU the last time step + haveUrelOld_ = false; + else + haveUrelOld_ = true; + + vector UrelOld(0.,0.,0.); + vector ddtUrel(0.,0.,0.); + for(int j=0;j<3;j++) + { + UrelOld[j] = UrelOld_[index][j]; + UrelOld_[index][j] = Urel[j]; + } + if(haveUrelOld_ ) //only compute force if we have old (relative) velocity + ddtUrel = (Urel-UrelOld)/dt; } - if(haveUrelOld_ ) //only compute force if we have old (relative) velocity - ddtUrel = (Ur-UrelOld)/dt; - if(splitUrelCalculation_) //we can always compute the total derivative in case we split - ddtUrel = DDtU; + // take right expression for the acceleration term + if(splitUrelCalculation_) + accel = DDtU; + else if (useUs_) + accel = DDtU - ddtUs; + else + accel = ddtUrel; + // take right expression for Cadd + scalar rho = forceSubM(0).rhoField()[cellI]; scalar ds = 2*particleCloud_.radius(index); scalar Vs = ds*ds*ds*M_PI/6; - scalar rho = forceSubM(0).rhoField()[cellI]; - virtualMassForce = Cadd_ * rho * Vs * ddtUrel; + if (useFelderhof_) + { + if(forceSubM(0).interpolation()) + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + else + voidfraction = voidfraction_[cellI]; + + sg = particleCloud_.density(index) / rho; + logsg = log(sg); + epsilons = 1-voidfraction; + + Cadd_ = 0.5 + + ( 0.047*logsg + 0.13)*epsilons + + (-0.066*logsg - 0.58)*epsilons*epsilons + + ( 1.42)*epsilons*epsilons*epsilons; + } + + // calculate force + virtualMassForce = Cadd_ * rho * Vs * accel; if( forceSubM(0).verbose() ) //&& index>100 && index < 105) { @@ -216,14 +290,13 @@ void virtualMassForce::setForce() const Pout << "position = " << particleCloud_.position(index) << endl; } - //Set value fields and write the probe + // Set value fields and write the probe if(probeIt_) { #include "setupProbeModelfields.H" vValues.append(virtualMassForce); //first entry must the be the force - vValues.append(Ur); - vValues.append(UrelOld); - vValues.append(ddtUrel); + vValues.append(accel); + sValues.append(Cadd_); sValues.append(Vs); sValues.append(rho); particleCloud_.probeM().writeProbe(index, sValues, vValues); diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H index ff2ee4df..1be1a60b 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H @@ -63,6 +63,14 @@ private: const volVectorField& U_; + word voidfractionFieldName_; + + const volScalarField& voidfraction_; + + word UsFieldName_; + + const volVectorField& Us_; + word phiFieldName_; const surfaceScalarField& phi_; @@ -72,8 +80,13 @@ private: mutable bool splitUrelCalculation_; //indicator to split calculation of Urel between CFDEM and LIGGGHTS //requires the integration fix to take dv/dt into account! - mutable double Cadd_; //indicator to split calculation of Urel between CFDEM and LIGGGHTS - //requires the integration fix to take dv/dt into account! + mutable double Cadd_; //custom Cadd value + + mutable bool useUs_; //indicator to use averaged Us instead of v_p + + mutable bool useFelderhof_; //indicator to use Cadd values from Felderhof + + public: From dd611fc7a06226899c9c48d8a808d8d274e243fd Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 16 May 2018 13:58:38 +0200 Subject: [PATCH 02/47] Major correction to the Mei lift force model --- .../cfdemParticle/cfdemCloud/cfdemCloud.C | 9 + .../cfdemParticle/cfdemCloud/cfdemCloud.H | 10 +- .../cfdemParticle/cfdemCloud/cfdemCloudI.H | 5 + .../subModels/forceModel/MeiLift/MeiLift.C | 228 +++++++++++++----- .../subModels/forceModel/MeiLift/MeiLift.H | 6 +- .../virtualMassForce/virtualMassForce.C | 4 +- .../virtualMassForce/virtualMassForce.H | 4 +- 7 files changed, 202 insertions(+), 64 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index a94d7851..f5920889 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -86,6 +86,7 @@ cfdemCloud::cfdemCloud modelType_(couplingProperties_.lookup("modelType")), positions_(NULL), velocities_(NULL), + omegas_(NULL), fluidVel_(NULL), fAcc_(NULL), impForces_(NULL), @@ -347,6 +348,7 @@ cfdemCloud::~cfdemCloud() clockM().normHist(); dataExchangeM().destroy(positions_,3); dataExchangeM().destroy(velocities_,3); + dataExchangeM().destroy(omegas_,3); dataExchangeM().destroy(fluidVel_,3); dataExchangeM().destroy(fAcc_,3); dataExchangeM().destroy(impForces_,3); @@ -369,6 +371,7 @@ void cfdemCloud::getDEMdata() dataExchangeM().getData("density","scalar-atom",densities_); dataExchangeM().getData("x","vector-atom",positions_); dataExchangeM().getData("v","vector-atom",velocities_); + dataExchangeM().getData("omega","vector-atom",omegas_); if(impDEMdragAcc_) dataExchangeM().getData("dragAcc","vector-atom",fAcc_); // array is used twice - might be necessary to clean it first @@ -498,6 +501,11 @@ vector cfdemCloud::velocity(int index) const return vector(velocities()[index][0],velocities()[index][1],velocities()[index][2]); } +vector cfdemCloud::omega(int index) const +{ + return vector(omegas()[index][0],omegas()[index][1],omegas()[index][2]); +} + vector cfdemCloud::expForce(int index) const { return vector(DEMForces()[index][0],DEMForces()[index][1],DEMForces()[index][2]); @@ -694,6 +702,7 @@ bool cfdemCloud::reAllocArrays() // get arrays of new length dataExchangeM().allocateArray(positions_,0.,3); dataExchangeM().allocateArray(velocities_,0.,3); + dataExchangeM().allocateArray(omegas_,0.,3); dataExchangeM().allocateArray(fluidVel_,0.,3); dataExchangeM().allocateArray(fAcc_,0.,3); dataExchangeM().allocateArray(impForces_,0.,3); diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H index bc8d011d..2abc4784 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H @@ -104,6 +104,8 @@ protected: mutable double **velocities_; + mutable double **omegas_; + mutable double **fluidVel_; mutable double **fAcc_; @@ -246,6 +248,8 @@ public: vector velocity(int) const; + vector omega(int) const; + vector expForce(int) const; vector fluidVel(int) const; @@ -286,6 +290,8 @@ public: inline double ** velocities() const; + inline double ** omegas() const; + inline double ** fluidVels() const; inline double ** fAccs() const; @@ -335,10 +341,8 @@ public: virtual inline int ** particleTypes() const {return NULL;} virtual label particleType(label index) const {return -1;} - //access to the particle's rotation and torque data + //access to the particle's torque data virtual inline double ** DEMTorques() const {return NULL;} - virtual inline double ** omegaArray() const {return NULL;} - virtual vector omega(int) const {return vector(0,0,0);} //access to the particles' orientation information virtual inline double ** exArray() const {return NULL;} diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H index c8e1297d..6f8bceba 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H @@ -110,6 +110,11 @@ inline double ** cfdemCloud::velocities() const return velocities_; } +inline double ** cfdemCloud::omegas() const +{ + return omegas_; +} + inline double ** cfdemCloud::fluidVels() const { return fluidVel_; diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C index c753e8c1..97cf6509 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C @@ -81,9 +81,36 @@ MeiLift::MeiLift propsDict_(dict.subDict(typeName + "Props")), velFieldName_(propsDict_.lookup("velFieldName")), U_(sm.mesh().lookupObject (velFieldName_)), - useSecondOrderTerms_(false) + useShearInduced_(true), + useSpinInduced_(false), + combineShearSpin_(false) { - if (propsDict_.found("useSecondOrderTerms")) useSecondOrderTerms_=true; + // read switches + if(propsDict_.found("useShearInduced")) + { + useShearInduced_ = readBool(propsDict_.lookup("useShearInduced")); + if(useShearInduced_) + Info << "Lift model: including shear-induced term.\n"; + } + if(propsDict_.found("useSpinInduced")) + { + useSpinInduced_ = readBool(propsDict_.lookup("useSpinInduced")); + if(useSpinInduced_) + { + Info << "Lift model: including spin-induced term.\n"; + Info << "Make sure to use a rolling friction model in LIGGGHTS!\n"; + } + } + if(propsDict_.found("combineShearSpin")) + { + combineShearSpin_ = readBool(propsDict_.lookup("combineShearSpin")); + if(combineShearSpin_) + { + Info << "Lift model: combining shear- and spin-terms by assuming equilibrium spin-rate.\n"; + if(!useShearInduced_ || !useSpinInduced_) + FatalError << "Shear- and spin-induced lift must be activated in order to combine.\n"; + } + } // init force sub model setForceSubModels(propsDict_); @@ -100,10 +127,15 @@ MeiLift::MeiLift particleCloud_.probeM().initialize(typeName, typeName+".logDat"); particleCloud_.probeM().vectorFields_.append("liftForce"); //first entry must the be the force particleCloud_.probeM().vectorFields_.append("Urel"); //other are debug - particleCloud_.probeM().vectorFields_.append("vorticity"); //other are debug - particleCloud_.probeM().scalarFields_.append("Rep"); //other are debug - particleCloud_.probeM().scalarFields_.append("Rew"); //other are debug - particleCloud_.probeM().scalarFields_.append("J_star"); //other are debug + particleCloud_.probeM().vectorFields_.append("vorticity"); + particleCloud_.probeM().vectorFields_.append("Ang velocity"); + particleCloud_.probeM().scalarFields_.append("Rep"); + particleCloud_.probeM().scalarFields_.append("Rew"); + particleCloud_.probeM().scalarFields_.append("J*"); + particleCloud_.probeM().scalarFields_.append("Cl(shear)"); + particleCloud_.probeM().scalarFields_.append("Cl*(spin)"); + particleCloud_.probeM().scalarFields_.append("Omega eq"); + particleCloud_.probeM().scalarFields_.append("Cl(combined)"); particleCloud_.probeM().writeHeader(); } @@ -122,27 +154,44 @@ void MeiLift::setForce() const const volScalarField& nufField = forceSubM(0).nuField(); const volScalarField& rhoField = forceSubM(0).rhoField(); + // vectors vector position(0,0,0); vector lift(0,0,0); vector Us(0,0,0); vector Ur(0,0,0); + vector Omega(0,0,0); + vector vorticity(0,0,0); + + // properties scalar magUr(0); scalar magVorticity(0); + scalar magOmega(0); scalar ds(0); scalar nuf(0); scalar rho(0); scalar voidfraction(1); + + // dimensionless groups scalar Rep(0); scalar Rew(0); - scalar Cl(0); - scalar Cl_star(0); - scalar J_star(0); - scalar Omega_eq(0); - scalar alphaStar(0); - scalar epsilonSqr(0.0); - scalar epsilon(0); + + // shear induced scalar omega_star(0); - vector vorticity(0,0,0); + scalar Clshear(0); + scalar J_star(0); + scalar alphaStar(0); + scalar epsilonSqr(0); + scalar epsilon(0); + + // spin induced + scalar Omega_star(0); + scalar Clspin_star(0); + + // shear-spin combination + scalar Omega_eq(0); + scalar Clcombined(0); + + volVectorField vorticityField = fvc::curl(U_); interpolationCellPoint UInterpolator_(U_); @@ -152,14 +201,14 @@ void MeiLift::setForce() const for (int index = 0; index < particleCloud_.numberOfParticles(); ++index) { - //if(mask[index][0]) - //{ lift = vector::zero; label cellI = particleCloud_.cellIDs()[index][0]; if (cellI > -1) // particle Found { - Us = particleCloud_.velocity(index); + // properties + Us = particleCloud_.velocity(index); + Omega = particleCloud_.omega(index); if (forceSubM(0).interpolation()) { @@ -173,23 +222,42 @@ void MeiLift::setForce() const vorticity = vorticityField[cellI]; } - magUr = mag(Ur); - magVorticity = mag(vorticity); + ds = 2. * particleCloud_.radius(index); + nuf = nufField[cellI]; + rho = rhoField[cellI]; - if (magUr > 0 && magVorticity > 0) + magUr = mag(Ur); + Rep = ds*magUr/nuf; + + // shear-induced lift + if (useShearInduced_) { - ds = 2. * particleCloud_.radius(index); - nuf = nufField[cellI]; - rho = rhoField[cellI]; + magVorticity = mag(vorticity); + Rew = magVorticity*ds*ds/nuf; + omega_star = magVorticity * ds / magUr; + alphaStar = 0.5 * omega_star; + /* + //Second order terms given by Loth and Dorgan (2009) + if (useSecondOrderTerms_) + { + scalar sqrtRep = sqrt(Rep); + //Loth and Dorgan (2009), Eq (34) + Cl_star = 1.0 - (0.675 + 0.15 * (1.0 + tanh(0.28 * (alphaStar - 2.0)))) * tanh(0.18 * sqrtRep); + //Loth and Dorgan (2009), Eq (38) + Omega_eq = alphaStar * (1.0 - 0.0075 * Rew) * (1.0 - 0.062 * sqrtRep - 0.001 * Rep); + //Loth and Dorgan (2009), Eq (39) + Cl += Omega_eq * Cl_star; + } - // calc dimensionless properties - Rep = ds*magUr/nuf; - Rew = magVorticity*ds*ds/nuf; + //Loth and Dorgan (2009), Eq (27) + lift = 0.125 * constant::mathematical::pi + * rho + * Cl + * magUr * Ur ^ vorticity / magVorticity + * ds * ds; + */ epsilonSqr = omega_star / Rep; + epsilon = sqrt(epsilonSqr); - omega_star = magVorticity * ds / magUr; - alphaStar = 0.5 * omega_star; - epsilonSqr = omega_star / Rep; - epsilon = sqrt(epsilonSqr); //Basic model for the correction to the Saffman lift //McLaughlin (1991), Mei (1992), Loth and Dorgan (2009) @@ -212,35 +280,74 @@ void MeiLift::setForce() const * (1.0 + tanh(2.5 * (log10(epsilon) + 0.191))) * (0.667 + tanh(6.0 * ( epsilon - 0.32 ))); } - //Loth and Dorgan (2009), Eq (31): Saffman lift-coefficient: ClSaff = 12.92 / pi * epsilon ~ 4.11 * epsilon - //Loth and Dorgan (2009), Eq (32) - Cl = J_star * 4.11 * epsilon; //multiply correction to the basic Saffman model - //Second order terms given by Loth and Dorgan (2009) - if (useSecondOrderTerms_) + //Loth and Dorgan (2009), Eq (31), Eq (32) + Clshear = J_star * 4.11 * epsilon; //multiply correction to the basic Saffman model + } + + if (useSpinInduced_) + { + magOmega = mag(Omega); + Omega_star = magOmega * ds / magUr; + + //Loth and Dorgan (2009), Eq (34) + Clspin_star = 1.0 - (0.675 + 0.15 * (1.0 + tanh(0.28 * (Omega_star - 2.0)))) * tanh(0.18 * sqrt(Rep)); + } + + if (combineShearSpin_) + { + //Loth and Dorgan (2009), Eq (38) + Omega_eq = alphaStar * (1.0 - 0.0075 * Rew) * (1.0 - 0.062 * sqrt(Rep) - 0.001 * Rep); + //Loth and Dorgan (2009), Eq (39) + Clcombined = Clshear + Clspin_star * Omega_eq; + + if (magUr>0.0 && magVorticity>0.0) { - scalar sqrtRep = sqrt(Rep); - //Loth and Dorgan (2009), Eq (34) - Cl_star = 1.0 - (0.675 + 0.15 * (1.0 + tanh(0.28 * (alphaStar - 2.0)))) * tanh(0.18 * sqrtRep); - //Loth and Dorgan (2009), Eq (38) - Omega_eq = alphaStar * (1.0 - 0.0075 * Rew) * (1.0 - 0.062 * sqrtRep - 0.001 * Rep); - //Loth and Dorgan (2009), Eq (39) - Cl += Omega_eq * Cl_star; - } - - //Loth and Dorgan (2009), Eq (27) - lift = 0.125 * constant::mathematical::pi - * rho - * Cl - * magUr * Ur ^ vorticity / magVorticity - * ds * ds; - - if (modelType_ == "B") - { - voidfraction = particleCloud_.voidfraction(index); - lift /= voidfraction; + //Loth and Dorgan (2009), Eq (27) + lift = 0.125 * constant::mathematical::pi + * rho + * Clcombined + * magUr * magUr + * (vorticity ^ Ur) / mag(vorticity ^ Ur) // force direction + * ds * ds; } } + else + { + //Loth and Dorgan (2009), Eq (36) + if (useShearInduced_) + { + if (magUr>0.0 && magVorticity>0.0) + { + //Loth and Dorgan (2009), Eq (27) + lift += 0.125 * constant::mathematical::pi + * rho + * Clshear + * magUr * magUr + * (vorticity ^ Ur) / mag(vorticity ^ Ur) // force direction + * ds * ds; + } + } + if (useSpinInduced_) + { + if (magUr>0.0 && magOmega>0.0) + { + //Loth and Dorgan (2009), Eq (33) + lift += 0.125 * constant::mathematical::pi + * rho + * Clspin_star + * (Omega ^ Ur) + * ds * ds * ds; + } + } + } + + if (modelType_ == "B") + { + voidfraction = particleCloud_.voidfraction(index); + lift /= voidfraction; + } + //********************************** //SAMPLING AND VERBOSE OUTOUT @@ -250,6 +357,7 @@ void MeiLift::setForce() const Pout << "Us = " << Us << endl; Pout << "Ur = " << Ur << endl; Pout << "vorticity = " << vorticity << endl; + Pout << "Omega = " << Omega << endl; Pout << "ds = " << ds << endl; Pout << "rho = " << rho << endl; Pout << "nuf = " << nuf << endl; @@ -258,6 +366,10 @@ void MeiLift::setForce() const Pout << "alphaStar = " << alphaStar << endl; Pout << "epsilon = " << epsilon << endl; Pout << "J_star = " << J_star << endl; + Pout << "Omega_eq = " << Omega_eq << endl; + Pout << "Clshear = " << Clshear<< endl; + Pout << "Clspin_star = " << Clspin_star << endl; + Pout << "Clcombined = " << Clcombined << endl; Pout << "lift = " << lift << endl; } @@ -268,9 +380,14 @@ void MeiLift::setForce() const vValues.append(lift); //first entry must the be the force vValues.append(Ur); vValues.append(vorticity); + vValues.append(Omega); sValues.append(Rep); sValues.append(Rew); sValues.append(J_star); + sValues.append(Clshear); + sValues.append(Clspin_star); + sValues.append(Omega_eq); + sValues.append(Clcombined); particleCloud_.probeM().writeProbe(index, sValues, vValues); } // END OF SAMPLING AND VERBOSE OUTOUT @@ -279,7 +396,6 @@ void MeiLift::setForce() const } // write particle based data to global array forceSubM(0).partToArray(index,lift,vector::zero); - //} } } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.H b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.H index 81ecfaee..4b43a0d0 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.H @@ -83,7 +83,11 @@ private: const volVectorField& U_; - bool useSecondOrderTerms_; + bool useShearInduced_; + + bool useSpinInduced_; + + bool combineShearSpin_; public: diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 8915d1c4..f9614bb2 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -113,7 +113,7 @@ virtualMassForce::virtualMassForce useUs_ = readBool(propsDict_.lookup("useUs")); if(useUs_) { - Info << "Virtual mass model: using averaged Us"; + Info << "Virtual mass model: using averaged Us \n"; Info << "WARNING: ignoring virtual mass of relative particle motion/collisions \n"; } } @@ -122,7 +122,7 @@ virtualMassForce::virtualMassForce useFelderhof_ = readBool(propsDict_.lookup("useFelderhof")); if(useFelderhof_) { - Info << "Virtual mass model: using Cadd correlation by Felderhof"; + Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; Info << "WARNING: ignoring user-set Cadd \n"; } } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H index 1be1a60b..6c302458 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H @@ -80,12 +80,12 @@ private: mutable bool splitUrelCalculation_; //indicator to split calculation of Urel between CFDEM and LIGGGHTS //requires the integration fix to take dv/dt into account! - mutable double Cadd_; //custom Cadd value - mutable bool useUs_; //indicator to use averaged Us instead of v_p mutable bool useFelderhof_; //indicator to use Cadd values from Felderhof + mutable double Cadd_; //custom Cadd value + public: From 9051bb7a709b3b8f44aaecf2a953fc431d82d548 Mon Sep 17 00:00:00 2001 From: s126103 Date: Thu, 17 May 2018 10:40:31 +0200 Subject: [PATCH 03/47] Extended Beestra drag model to polydisperse particles, correction in the superficial velocity (voidfraction*Uf-Us instead uf voidfraction(Uf-Us)) --- .../forceModel/BeetstraDrag/BeetstraDrag.C | 97 +++++++++++++------ .../forceModel/BeetstraDrag/BeetstraDrag.H | 6 ++ .../virtualMassForce/virtualMassForce.C | 2 +- 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C index 58677ad3..e109976b 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C @@ -56,12 +56,24 @@ BeetstraDrag::BeetstraDrag UsFieldName_(propsDict_.lookup("granVelFieldName")), UsField_(sm.mesh().lookupObject (UsFieldName_)), scaleDia_(1.), - scaleDrag_(1.) + scaleDrag_(1.), + polydisperse_(false), + dSauterFieldName_(propsDict_.lookup("dSauterFieldName")), + dSauterField_(sm.mesh().lookupObject (dSauterFieldName_)) { + + if(propsDict_.found("polydisperse")) + { + polydisperse_ = readBool(propsDict_.lookup("polydisperse")); + if(polydisperse_) + { + Info << "Drag model: using polydisperse correction factor \n"; + } + } //Append the field names to be probed particleCloud_.probeM().initialize(typeName, typeName+".logDat"); particleCloud_.probeM().vectorFields_.append("dragForce"); //first entry must be the force - particleCloud_.probeM().vectorFields_.append("Urel"); + particleCloud_.probeM().vectorFields_.append("Urelsup"); particleCloud_.probeM().scalarFields_.append("Rep"); particleCloud_.probeM().scalarFields_.append("betaP"); particleCloud_.probeM().scalarFields_.append("voidfraction"); @@ -112,35 +124,41 @@ void BeetstraDrag::setForce() const vector position(0,0,0); scalar voidfraction(1); vector Ufluid(0,0,0); + vector Ufluidsup(0,0,0); vector drag(0,0,0); - label cellI=0; + label cellI = 0; vector Us(0,0,0); - vector Ur(0,0,0); + vector Ursup(0,0,0); scalar ds(0); scalar ds_scaled(0); scalar scaleDia3 = scaleDia_*scaleDia_*scaleDia_; scalar nuf(0); scalar rho(0); - scalar magUr(0); + scalar magUrsup(0); scalar Rep(0); scalar localPhiP(0); + scalar Fdrag(0); + scalar yi(0); + scalar dSauter(0); vector dragExplicit(0,0,0); scalar dragCoefficient(0); interpolationCellPoint voidfractionInterpolator_(voidfraction_); + interpolationCellPoint dSauterInterpolator_(dSauterField_); interpolationCellPoint UInterpolator_(U_); #include "setupProbeModel.H" for(int index = 0; index < particleCloud_.numberOfParticles(); ++index) { - cellI = particleCloud_.cellIDs()[index][0]; - drag = vector(0,0,0); - dragExplicit = vector(0,0,0); - Ufluid =vector(0,0,0); - voidfraction=0; + cellI = particleCloud_.cellIDs()[index][0]; + drag = vector(0,0,0); + dragExplicit = vector(0,0,0); + Ufluid = vector(0,0,0); + Ufluidsup = vector(0,0,0); + voidfraction = 0; dragCoefficient = 0; if (cellI > -1) // particle found @@ -154,7 +172,7 @@ void BeetstraDrag::setForce() const //Ensure interpolated void fraction to be meaningful // Info << " --> voidfraction: " << voidfraction << endl; if(voidfraction>1.00) voidfraction = 1.0; - if(voidfraction<0.10) voidfraction = 0.10; + if(voidfraction<0.30) voidfraction = 0.30; } else { @@ -162,41 +180,56 @@ void BeetstraDrag::setForce() const Ufluid = U_[cellI]; } - Us = particleCloud_.velocity(index); - Ur = Ufluid-Us; - magUr = mag(Ur); - ds = 2*particleCloud_.radius(index); - ds_scaled = ds/scaleDia_; - rho = rhoField[cellI]; - nuf = nufField[cellI]; + Ufluidsup = Ufluid*voidfraction; + Us = particleCloud_.velocity(index); + Ursup = Ufluidsup-Us; + magUrsup = mag(Ursup); + ds = 2*particleCloud_.radius(index); + ds_scaled = ds/scaleDia_; + rho = rhoField[cellI]; + nuf = nufField[cellI]; + localPhiP = 1.0f-voidfraction+SMALL; - Rep=0.0; - localPhiP = 1.0f-voidfraction+SMALL; + // Ur is interstitial velocity, Beetstra uses superficial! + Rep = ds_scaled*magUrsup/nuf+SMALL; - // calc particle's drag coefficient (i.e., Force per unit slip velocity and Stokes drag) + // Beetstra et. al (2007), Eq. (21) + Fdrag = 10.0*localPhiP/(voidfraction*voidfraction) + + voidfraction*voidfraction*(1.0+1.5*sqrt(localPhiP)) + + 0.413*Rep/(24*voidfraction*voidfraction) + * (1.0/voidfraction + 3*voidfraction*localPhiP + 8.4*pow(Rep,-0.343)) + / (1+pow(10,3*localPhiP)*pow(Rep,-0.5*(1+4*localPhiP))); - Rep=ds_scaled*voidfraction*magUr/nuf+SMALL; - dragCoefficient = 10.0*localPhiP/(voidfraction*voidfraction) + - voidfraction*voidfraction*(1.0+1.5*Foam::sqrt(localPhiP)) + - 0.413*Rep/(24*voidfraction*voidfraction)*(1.0/voidfraction+3*voidfraction*localPhiP+8.4*Foam::pow(Rep,-0.343))/ - (1+Foam::pow(10,3*localPhiP)*Foam::pow(Rep,-0.5*(1+4*localPhiP))); + if (polydisperse_) + { + if( forceSubM(0).interpolation() ) + dSauter = dSauterInterpolator_.interpolate(position,cellI); + else + dSauter = dSauterField_[cellI]; + + // Beetstra et. al (2007), Eq. (21) + yi = ds_scaled/dSauter; + Fdrag *= (voidfraction*yi + localPhiP*yi*yi + 0.064*voidfraction*yi*yi*yi); + } // calc particle's drag - dragCoefficient *= 3*M_PI*ds_scaled*nuf*rho*voidfraction*scaleDia3*scaleDrag_; + dragCoefficient = Fdrag*3.0*M_PI*ds_scaled*nuf*rho*scaleDrag_*scaleDia3; + if (modelType_=="B") dragCoefficient /= voidfraction; - drag = dragCoefficient * Ur; + drag = dragCoefficient * Ursup; // explicitCorr - forceSubM(0).explicitCorr(drag,dragExplicit,dragCoefficient,Ufluid,U_[cellI],Us,UsField_[cellI],forceSubM(0).verbose()); + forceSubM(0).explicitCorr(drag,dragExplicit,dragCoefficient,Ufluidsup,U_[cellI]*voidfraction_[cellI],Us,UsField_[cellI],forceSubM(0).verbose()); if(forceSubM(0).verbose() && index >=0 && index <2) { Pout << "cellI = " << cellI << endl; Pout << "index = " << index << endl; + Pout << "Ufluidsup = " << Ufluidsup << endl; Pout << "Us = " << Us << endl; - Pout << "Ur = " << Ur << endl; + Pout << "Ursup = " << Ursup << endl; Pout << "ds = " << ds << endl; Pout << "ds/scale = " << ds/scaleDia_ << endl; Pout << "rho = " << rho << endl; @@ -211,7 +244,7 @@ void BeetstraDrag::setForce() const { #include "setupProbeModelfields.H" vValues.append(drag); //first entry must the be the force - vValues.append(Ur); + vValues.append(Ursup); sValues.append(Rep); sValues.append(voidfraction); particleCloud_.probeM().writeProbe(index, sValues, vValues); @@ -219,7 +252,7 @@ void BeetstraDrag::setForce() const } // write particle based data to global array - forceSubM(0).partToArray(index,drag,dragExplicit,Ufluid,dragCoefficient); + forceSubM(0).partToArray(index,drag,dragExplicit,Ufluidsup,dragCoefficient); } } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H index f6e079ab..adcb7ecf 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H @@ -59,6 +59,12 @@ private: mutable scalar scaleDrag_; + mutable bool polydisperse_; + + word dSauterFieldName_; + + const volScalarField& dSauterField_; + public: //- Runtime type information diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index f9614bb2..3660fc9d 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -69,7 +69,7 @@ virtualMassForce::virtualMassForce U_(sm.mesh().lookupObject (velFieldName_)), voidfractionFieldName_(propsDict_.lookup("voidfractionFieldName")), voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), - UsFieldName_(propsDict_.lookup("UsFieldName")), + UsFieldName_(propsDict_.lookup("granVelFieldName")), Us_(sm.mesh().lookupObject (UsFieldName_)), phiFieldName_(propsDict_.lookup("phiFieldName")), phi_(sm.mesh().lookupObject (phiFieldName_)), From 8b62c223120bb307db0835ea3fa06eb239ee2d05 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 18 May 2018 09:30:03 +0200 Subject: [PATCH 04/47] fixes based on comments --- .../forceModel/BeetstraDrag/BeetstraDrag.C | 54 +++++++++---------- .../subModels/forceModel/MeiLift/MeiLift.C | 41 ++++++-------- .../virtualMassForce/virtualMassForce.C | 36 +++++-------- 3 files changed, 55 insertions(+), 76 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C index e109976b..c24a85d0 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C @@ -57,26 +57,27 @@ BeetstraDrag::BeetstraDrag UsField_(sm.mesh().lookupObject (UsFieldName_)), scaleDia_(1.), scaleDrag_(1.), - polydisperse_(false), - dSauterFieldName_(propsDict_.lookup("dSauterFieldName")), - dSauterField_(sm.mesh().lookupObject (dSauterFieldName_)) + polydisperse_(propsDict_.lookupOrDefault("polydisperse",false)), + dSauterFieldName_(propsDict_.lookupOrDefault("dSauterFieldName",voidfractionFieldName_)), // use voidfractionField as a dummy to prevent lookup failure + dSauterField_(sm.mesh().lookupObject (dSauterFieldName_)) { - if(propsDict_.found("polydisperse")) + if(polydisperse_) { - polydisperse_ = readBool(propsDict_.lookup("polydisperse")); - if(polydisperse_) - { - Info << "Drag model: using polydisperse correction factor \n"; - } + Info << "Drag model: using polydisperse correction factor \n"; + if(!propsDict_.found("dSauterFieldName")) + FatalError << "dSauterFieldName must be specified when polydisperse = true"; } + + //Append the field names to be probed particleCloud_.probeM().initialize(typeName, typeName+".logDat"); particleCloud_.probeM().vectorFields_.append("dragForce"); //first entry must be the force - particleCloud_.probeM().vectorFields_.append("Urelsup"); + particleCloud_.probeM().vectorFields_.append("Urel"); particleCloud_.probeM().scalarFields_.append("Rep"); - particleCloud_.probeM().scalarFields_.append("betaP"); particleCloud_.probeM().scalarFields_.append("voidfraction"); + particleCloud_.probeM().scalarFields_.append("Fdrag"); + particleCloud_.probeM().scalarFields_.append("y_polydisperse"); particleCloud_.probeM().writeHeader(); // init force sub model @@ -124,18 +125,17 @@ void BeetstraDrag::setForce() const vector position(0,0,0); scalar voidfraction(1); vector Ufluid(0,0,0); - vector Ufluidsup(0,0,0); vector drag(0,0,0); label cellI = 0; vector Us(0,0,0); - vector Ursup(0,0,0); + vector Ur(0,0,0); scalar ds(0); scalar ds_scaled(0); scalar scaleDia3 = scaleDia_*scaleDia_*scaleDia_; scalar nuf(0); scalar rho(0); - scalar magUrsup(0); + scalar magUr(0); scalar Rep(0); scalar localPhiP(0); scalar Fdrag(0); @@ -146,8 +146,8 @@ void BeetstraDrag::setForce() const scalar dragCoefficient(0); interpolationCellPoint voidfractionInterpolator_(voidfraction_); - interpolationCellPoint dSauterInterpolator_(dSauterField_); interpolationCellPoint UInterpolator_(U_); + interpolationCellPoint dSauterInterpolator_(dSauterField_); #include "setupProbeModel.H" @@ -157,7 +157,6 @@ void BeetstraDrag::setForce() const drag = vector(0,0,0); dragExplicit = vector(0,0,0); Ufluid = vector(0,0,0); - Ufluidsup = vector(0,0,0); voidfraction = 0; dragCoefficient = 0; @@ -180,10 +179,9 @@ void BeetstraDrag::setForce() const Ufluid = U_[cellI]; } - Ufluidsup = Ufluid*voidfraction; Us = particleCloud_.velocity(index); - Ursup = Ufluidsup-Us; - magUrsup = mag(Ursup); + Ur = Ufluid-Us; + magUr = mag(Ur); ds = 2*particleCloud_.radius(index); ds_scaled = ds/scaleDia_; rho = rhoField[cellI]; @@ -191,7 +189,7 @@ void BeetstraDrag::setForce() const localPhiP = 1.0f-voidfraction+SMALL; // Ur is interstitial velocity, Beetstra uses superficial! - Rep = ds_scaled*magUrsup/nuf+SMALL; + Rep = ds_scaled*voidfraction*magUr/nuf+SMALL; // Beetstra et. al (2007), Eq. (21) Fdrag = 10.0*localPhiP/(voidfraction*voidfraction) @@ -213,23 +211,23 @@ void BeetstraDrag::setForce() const } // calc particle's drag - dragCoefficient = Fdrag*3.0*M_PI*ds_scaled*nuf*rho*scaleDrag_*scaleDia3; + dragCoefficient = Fdrag*3.0*M_PI*ds_scaled*nuf*rho*voidfraction*scaleDia3*scaleDrag_; if (modelType_=="B") dragCoefficient /= voidfraction; - drag = dragCoefficient * Ursup; + drag = dragCoefficient * Ur; // explicitCorr - forceSubM(0).explicitCorr(drag,dragExplicit,dragCoefficient,Ufluidsup,U_[cellI]*voidfraction_[cellI],Us,UsField_[cellI],forceSubM(0).verbose()); + forceSubM(0).explicitCorr(drag,dragExplicit,dragCoefficient,Ufluid,U_[cellI],Us,UsField_[cellI],forceSubM(0).verbose()); if(forceSubM(0).verbose() && index >=0 && index <2) { Pout << "cellI = " << cellI << endl; Pout << "index = " << index << endl; - Pout << "Ufluidsup = " << Ufluidsup << endl; + Pout << "Ufluid = " << Ufluid << endl; Pout << "Us = " << Us << endl; - Pout << "Ursup = " << Ursup << endl; + Pout << "Ur = " << Ur << endl; Pout << "ds = " << ds << endl; Pout << "ds/scale = " << ds/scaleDia_ << endl; Pout << "rho = " << rho << endl; @@ -244,15 +242,17 @@ void BeetstraDrag::setForce() const { #include "setupProbeModelfields.H" vValues.append(drag); //first entry must the be the force - vValues.append(Ursup); + vValues.append(Ur); sValues.append(Rep); sValues.append(voidfraction); + sValues.append(Fdrag); + sValues.append(yi); particleCloud_.probeM().writeProbe(index, sValues, vValues); } } // write particle based data to global array - forceSubM(0).partToArray(index,drag,dragExplicit,Ufluidsup,dragCoefficient); + forceSubM(0).partToArray(index,drag,dragExplicit,Ufluid,dragCoefficient); } } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C index 97cf6509..7472f791 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C @@ -81,35 +81,26 @@ MeiLift::MeiLift propsDict_(dict.subDict(typeName + "Props")), velFieldName_(propsDict_.lookup("velFieldName")), U_(sm.mesh().lookupObject (velFieldName_)), - useShearInduced_(true), - useSpinInduced_(false), - combineShearSpin_(false) + useShearInduced_(propsDict_.lookupOrDefault("useShearInduced",true)), + useSpinInduced_(propsDict_.lookupOrDefault("useSpinInduced",false)), + combineShearSpin_(propsDict_.lookupOrDefault("combineShearSpin",false)) { // read switches - if(propsDict_.found("useShearInduced")) - { - useShearInduced_ = readBool(propsDict_.lookup("useShearInduced")); - if(useShearInduced_) - Info << "Lift model: including shear-induced term.\n"; + + if(useShearInduced_) + Info << "Lift model: including shear-induced term.\n"; + + if(useSpinInduced_) + { + Info << "Lift model: including spin-induced term.\n"; + Info << "Make sure to use a rolling friction model in LIGGGHTS!\n"; } - if(propsDict_.found("useSpinInduced")) + + if(combineShearSpin_) { - useSpinInduced_ = readBool(propsDict_.lookup("useSpinInduced")); - if(useSpinInduced_) - { - Info << "Lift model: including spin-induced term.\n"; - Info << "Make sure to use a rolling friction model in LIGGGHTS!\n"; - } - } - if(propsDict_.found("combineShearSpin")) - { - combineShearSpin_ = readBool(propsDict_.lookup("combineShearSpin")); - if(combineShearSpin_) - { - Info << "Lift model: combining shear- and spin-terms by assuming equilibrium spin-rate.\n"; - if(!useShearInduced_ || !useSpinInduced_) - FatalError << "Shear- and spin-induced lift must be activated in order to combine.\n"; - } + Info << "Lift model: combining shear- and spin-terms by assuming equilibrium spin-rate.\n"; + if(!useShearInduced_ || !useSpinInduced_) + FatalError << "Shear- and spin-induced lift must be activated in order to combine.\n"; } // init force sub model diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 3660fc9d..37badab6 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -74,9 +74,9 @@ virtualMassForce::virtualMassForce phiFieldName_(propsDict_.lookup("phiFieldName")), phi_(sm.mesh().lookupObject (phiFieldName_)), UrelOld_(NULL), - splitUrelCalculation_(false), - useUs_(false), - useFelderhof_(false), + splitUrelCalculation_(propsDict_.lookupOrDefault("splitUrelCalculation",false)), + useUs_(propsDict_.lookupOrDefault("useUs",false)), + useFelderhof_(propsDict_.lookupOrDefault("useFelderhof",false)), Cadd_(0.5) { @@ -94,37 +94,25 @@ virtualMassForce::virtualMassForce forceSubM(0).readSwitches(); //Extra switches/settings - if(propsDict_.found("splitUrelCalculation")) + if(splitUrelCalculation_) { - splitUrelCalculation_ = readBool(propsDict_.lookup("splitUrelCalculation")); - if(splitUrelCalculation_) - { - Info << "Virtual mass model: will split the Urel calculation\n"; - Info << "WARNING: be sure that LIGGGHTS integration takes ddtv_p implicitly into account! \n"; - } + Info << "Virtual mass model: will split the Urel calculation\n"; + Info << "WARNING: be sure that LIGGGHTS integration takes ddtv_p implicitly into account! \n"; } if(propsDict_.found("Cadd")) { Cadd_ = readScalar(propsDict_.lookup("Cadd")); Info << "Virtual mass model: using non-standard Cadd = " << Cadd_ << endl; } - if(propsDict_.found("useUs")) + if(useUs_) { - useUs_ = readBool(propsDict_.lookup("useUs")); - if(useUs_) - { - Info << "Virtual mass model: using averaged Us \n"; - Info << "WARNING: ignoring virtual mass of relative particle motion/collisions \n"; - } + Info << "Virtual mass model: using averaged Us \n"; + Info << "WARNING: ignoring virtual mass of relative particle motion/collisions \n"; } - if(propsDict_.found("useFelderhof")) + if(useFelderhof_) { - useFelderhof_ = readBool(propsDict_.lookup("useFelderhof")); - if(useFelderhof_) - { - Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; - Info << "WARNING: ignoring user-set Cadd \n"; - } + Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; + Info << "WARNING: ignoring user-set Cadd \n"; } particleCloud_.checkCG(true); From 41faf88df7b012732b6b495956f36a8920a57e35 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 18 May 2018 10:03:41 +0200 Subject: [PATCH 05/47] Mergning cfdemCloud from feature/cfdemSolverRhoSimple --- .../cfdemParticle/cfdemCloud/cfdemCloud.C | 59 ++++++++++++++----- .../cfdemParticle/cfdemCloud/cfdemCloud.H | 39 ++++++------ .../cfdemParticle/cfdemCloud/cfdemCloudI.H | 57 +++++++++++------- 3 files changed, 100 insertions(+), 55 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index f5920889..5d132ddd 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -83,10 +83,11 @@ cfdemCloud::cfdemCloud ignore_(false), allowCFDsubTimestep_(true), limitDEMForces_(false), + getParticleDensities_(couplingProperties_.lookupOrDefault("getParticleDensities",false)), + getParticleTypes_(couplingProperties_.lookupOrDefault("getParticleTypes",false)), modelType_(couplingProperties_.lookup("modelType")), positions_(NULL), velocities_(NULL), - omegas_(NULL), fluidVel_(NULL), fAcc_(NULL), impForces_(NULL), @@ -94,7 +95,6 @@ cfdemCloud::cfdemCloud DEMForces_(NULL), Cds_(NULL), radii_(NULL), - densities_(NULL), voidfractions_(NULL), cellIDs_(NULL), particleWeights_(NULL), @@ -129,6 +129,19 @@ cfdemCloud::cfdemCloud mesh, dimensionedScalar("zero", dimensionSet(0,0,-1,0,0), 0) // 1/s ), + particleDensityField_ + ( + IOobject + ( + "partRho", + mesh.time().timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-3,0,0,0), 0.0) + ), checkPeriodicCells_(false), turbulence_ ( @@ -348,7 +361,6 @@ cfdemCloud::~cfdemCloud() clockM().normHist(); dataExchangeM().destroy(positions_,3); dataExchangeM().destroy(velocities_,3); - dataExchangeM().destroy(omegas_,3); dataExchangeM().destroy(fluidVel_,3); dataExchangeM().destroy(fAcc_,3); dataExchangeM().destroy(impForces_,3); @@ -356,25 +368,27 @@ cfdemCloud::~cfdemCloud() dataExchangeM().destroy(DEMForces_,3); dataExchangeM().destroy(Cds_,1); dataExchangeM().destroy(radii_,1); - dataExchangeM().destroy(densities_,1); dataExchangeM().destroy(voidfractions_,1); dataExchangeM().destroy(cellIDs_,1); dataExchangeM().destroy(particleWeights_,1); dataExchangeM().destroy(particleVolumes_,1); dataExchangeM().destroy(particleV_,1); + if(getParticleDensities_) dataExchangeM().destroy(particleDensities_,1); + if(getParticleTypes_) dataExchangeM().destroy(particleTypes_,1); } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // void cfdemCloud::getDEMdata() { dataExchangeM().getData("radius","scalar-atom",radii_); - dataExchangeM().getData("density","scalar-atom",densities_); dataExchangeM().getData("x","vector-atom",positions_); dataExchangeM().getData("v","vector-atom",velocities_); - dataExchangeM().getData("omega","vector-atom",omegas_); if(impDEMdragAcc_) dataExchangeM().getData("dragAcc","vector-atom",fAcc_); // array is used twice - might be necessary to clean it first + + if(getParticleDensities_) dataExchangeM().getData("density","scalar-atom",particleDensities_); + if(getParticleTypes_) dataExchangeM().getData("type","scalar-atom",particleTypes_); } void cfdemCloud::giveDEMdata() @@ -452,6 +466,25 @@ void cfdemCloud::setParticleForceField() ); } +void cfdemCloud::setScalarAverages() +{ + if(!getParticleDensities_) return; + if(verbose_) Info << "- setScalarAverage" << endl; + + particleDensityField_.primitiveFieldRef() = 0.0; + averagingM().resetWeightFields(); + averagingM().setScalarAverage + ( + particleDensityField_, + particleDensities_, + particleWeights_, + averagingM().UsWeightField(), + NULL + ); + + if(verbose_) Info << "setScalarAverage done." << endl; +} + void cfdemCloud::setVectorAverages() { if(verbose_) Info << "- setVectorAverage(Us,velocities_,weights_)" << endl; @@ -501,11 +534,6 @@ vector cfdemCloud::velocity(int index) const return vector(velocities()[index][0],velocities()[index][1],velocities()[index][2]); } -vector cfdemCloud::omega(int index) const -{ - return vector(omegas()[index][0],omegas()[index][1],omegas()[index][2]); -} - vector cfdemCloud::expForce(int index) const { return vector(DEMForces()[index][0],DEMForces()[index][1],DEMForces()[index][2]); @@ -609,7 +637,8 @@ bool cfdemCloud::evolve clockM().stop("setvoidFraction"); // set average particles velocity field - clockM().start(20,"setVectorAverage"); + clockM().start(20,"setAverages"); + setScalarAverages(); setVectorAverages(); @@ -623,7 +652,7 @@ bool cfdemCloud::evolve if(!treatVoidCellsAsExplicitForce()) smoothingM().smoothenReferenceField(averagingM().UsNext()); - clockM().stop("setVectorAverage"); + clockM().stop("setAverages"); } //============================================ @@ -702,7 +731,6 @@ bool cfdemCloud::reAllocArrays() // get arrays of new length dataExchangeM().allocateArray(positions_,0.,3); dataExchangeM().allocateArray(velocities_,0.,3); - dataExchangeM().allocateArray(omegas_,0.,3); dataExchangeM().allocateArray(fluidVel_,0.,3); dataExchangeM().allocateArray(fAcc_,0.,3); dataExchangeM().allocateArray(impForces_,0.,3); @@ -710,12 +738,13 @@ bool cfdemCloud::reAllocArrays() dataExchangeM().allocateArray(DEMForces_,0.,3); dataExchangeM().allocateArray(Cds_,0.,1); dataExchangeM().allocateArray(radii_,0.,1); - dataExchangeM().allocateArray(densities_,0.,1); dataExchangeM().allocateArray(voidfractions_,1.,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(cellIDs_,-1,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(particleWeights_,0.,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(particleVolumes_,0.,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(particleV_,0.,1); + if(getParticleDensities_) dataExchangeM().allocateArray(particleDensities_,0.,1); + if(getParticleTypes_) dataExchangeM().allocateArray(particleTypes_,0.,1); arraysReallocated_ = true; return true; } diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H index 2abc4784..1b3f78cf 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H @@ -96,6 +96,10 @@ protected: bool limitDEMForces_; + bool getParticleDensities_; + + bool getParticleTypes_; + scalar maxDEMForce_; const word modelType_; @@ -104,8 +108,6 @@ protected: mutable double **velocities_; - mutable double **omegas_; - mutable double **fluidVel_; mutable double **fAcc_; @@ -120,12 +122,14 @@ protected: mutable double **radii_; - mutable double **densities_; - mutable double **voidfractions_; mutable int **cellIDs_; + mutable double **particleDensities_; + + mutable int **particleTypes_; + mutable double **particleWeights_; mutable double **particleVolumes_; @@ -166,6 +170,8 @@ protected: mutable volScalarField ddtVoidfraction_; + mutable volScalarField particleDensityField_; + mutable Switch checkPeriodicCells_; const turbulenceModel& turbulence_; @@ -209,6 +215,8 @@ protected: virtual void setParticleForceField(); + virtual void setScalarAverages(); + virtual void setVectorAverages(); public: @@ -248,8 +256,6 @@ public: vector velocity(int) const; - vector omega(int) const; - vector expForce(int) const; vector fluidVel(int) const; @@ -290,8 +296,6 @@ public: inline double ** velocities() const; - inline double ** omegas() const; - inline double ** fluidVels() const; inline double ** fAccs() const; @@ -306,14 +310,10 @@ public: inline double ** radii() const; - inline double ** densities() const; - inline double ** voidfractions() const; inline void get_radii(double**&) const; - inline void get_densities(double**&) const; - inline int ** cellIDs() const; inline void get_cellIDs(int**&) const; @@ -326,8 +326,6 @@ public: inline scalar radius(int) const; - inline scalar density(int) const; - virtual inline double d(int) const; inline scalar d32(bool recalc=true); @@ -337,16 +335,19 @@ public: virtual inline int maxType() {return -1;} virtual inline bool multipleTypesDMax() {return false;} virtual inline bool multipleTypesDMin() {return false;} - virtual inline double ** particleDensity() const {return NULL;} - virtual inline int ** particleTypes() const {return NULL;} - virtual label particleType(label index) const {return -1;} + virtual inline double ** particleDensity() const; + virtual inline double particleDensity(label index) const; + virtual inline int ** particleTypes() const; + virtual inline label particleType(label index) const; - //access to the particle's torque data + //access to the particle's rotation and torque data virtual inline double ** DEMTorques() const {return NULL;} + virtual inline double ** omegaArray() const {return NULL;} + virtual vector omega(int) const {return vector::zero;} //access to the particles' orientation information virtual inline double ** exArray() const {return NULL;} - virtual vector ex(int) const {return vector(0,0,0);} + virtual vector ex(int) const {return vector::zero;} //Detector if SRF module is enable or not virtual inline bool SRFOn(){return false;} diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H index 6f8bceba..56ddfa48 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H @@ -110,11 +110,6 @@ inline double ** cfdemCloud::velocities() const return velocities_; } -inline double ** cfdemCloud::omegas() const -{ - return omegas_; -} - inline double ** cfdemCloud::fluidVels() const { return fluidVel_; @@ -150,12 +145,6 @@ inline double ** cfdemCloud::radii() const return radii_; } -inline double ** cfdemCloud::densities() const -{ - return densities_; -} - - inline double ** cfdemCloud::voidfractions() const { return voidfractions_; @@ -170,11 +159,6 @@ inline void cfdemCloud::get_radii(double **& values) const values=radii_; } -inline void cfdemCloud::get_densities(double **& values) const -{ - values=densities_; -} - inline int ** cfdemCloud::cellIDs() const { return cellIDs_; @@ -208,11 +192,6 @@ inline scalar cfdemCloud::radius(int index) const return radii_[index][0]; } -inline scalar cfdemCloud::density(int index) const -{ - return densities_[index][0]; -} - inline double cfdemCloud::d(int index) const { return 2.*radii_[index][0]; @@ -237,6 +216,42 @@ inline double cfdemCloud::d32(bool recalc) return d32_; } +inline double ** cfdemCloud::particleDensity() const +{ + if(!getParticleDensities_) return NULL; + else + { + return particleDensities_; + } +} + +inline double cfdemCloud::particleDensity(label index) const +{ + if(!getParticleDensities_) return -1.0; + else + { + return particleDensities_[index][0]; + } +} + +inline int ** cfdemCloud::particleTypes() const +{ + if(!getParticleTypes_) return NULL; + else + { + return particleTypes_; + } +} + +inline label cfdemCloud::particleType(label index) const +{ + if(!getParticleDensities_) return -1; + else + { + return particleTypes_[index][0]; + } +} + inline int cfdemCloud::numberOfParticles() const { return numberOfParticles_; From 324094bb0ba46da820a2b53e5ca2a1371faa3b0b Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 18 May 2018 11:40:43 +0200 Subject: [PATCH 06/47] conditionally communicate particle density and angular velocity --- .../cfdemParticle/cfdemCloud/cfdemCloud.C | 47 ++++--------------- .../cfdemParticle/cfdemCloud/cfdemCloud.H | 20 ++++---- .../cfdemParticle/cfdemCloud/cfdemCloudI.H | 16 ++++--- .../subModels/forceModel/MeiLift/MeiLift.C | 27 ++--------- .../virtualMassForce/virtualMassForce.C | 6 ++- 5 files changed, 35 insertions(+), 81 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index 5d132ddd..98869b87 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -84,7 +84,7 @@ cfdemCloud::cfdemCloud allowCFDsubTimestep_(true), limitDEMForces_(false), getParticleDensities_(couplingProperties_.lookupOrDefault("getParticleDensities",false)), - getParticleTypes_(couplingProperties_.lookupOrDefault("getParticleTypes",false)), + getParticleAngVels_(couplingProperties_.lookupOrDefault("getParticleAngVels",false)), modelType_(couplingProperties_.lookup("modelType")), positions_(NULL), velocities_(NULL), @@ -97,6 +97,8 @@ cfdemCloud::cfdemCloud radii_(NULL), voidfractions_(NULL), cellIDs_(NULL), + particleDensities_(NULL), + particleAngVels_(NULL), particleWeights_(NULL), particleVolumes_(NULL), particleV_(NULL), @@ -129,19 +131,6 @@ cfdemCloud::cfdemCloud mesh, dimensionedScalar("zero", dimensionSet(0,0,-1,0,0), 0) // 1/s ), - particleDensityField_ - ( - IOobject - ( - "partRho", - mesh.time().timeName(), - mesh, - IOobject::READ_IF_PRESENT, - IOobject::NO_WRITE - ), - mesh, - dimensionedScalar("zero", dimensionSet(1,-3,0,0,0), 0.0) - ), checkPeriodicCells_(false), turbulence_ ( @@ -374,7 +363,7 @@ cfdemCloud::~cfdemCloud() dataExchangeM().destroy(particleVolumes_,1); dataExchangeM().destroy(particleV_,1); if(getParticleDensities_) dataExchangeM().destroy(particleDensities_,1); - if(getParticleTypes_) dataExchangeM().destroy(particleTypes_,1); + if(getParticleAngVels_) dataExchangeM().destroy(particleAngVels_,1); } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // @@ -388,7 +377,7 @@ void cfdemCloud::getDEMdata() dataExchangeM().getData("dragAcc","vector-atom",fAcc_); // array is used twice - might be necessary to clean it first if(getParticleDensities_) dataExchangeM().getData("density","scalar-atom",particleDensities_); - if(getParticleTypes_) dataExchangeM().getData("type","scalar-atom",particleTypes_); + if(getParticleAngVels_) dataExchangeM().getData("omega","vector-atom",particleAngVels_); } void cfdemCloud::giveDEMdata() @@ -466,25 +455,6 @@ void cfdemCloud::setParticleForceField() ); } -void cfdemCloud::setScalarAverages() -{ - if(!getParticleDensities_) return; - if(verbose_) Info << "- setScalarAverage" << endl; - - particleDensityField_.primitiveFieldRef() = 0.0; - averagingM().resetWeightFields(); - averagingM().setScalarAverage - ( - particleDensityField_, - particleDensities_, - particleWeights_, - averagingM().UsWeightField(), - NULL - ); - - if(verbose_) Info << "setScalarAverage done." << endl; -} - void cfdemCloud::setVectorAverages() { if(verbose_) Info << "- setVectorAverage(Us,velocities_,weights_)" << endl; @@ -637,8 +607,7 @@ bool cfdemCloud::evolve clockM().stop("setvoidFraction"); // set average particles velocity field - clockM().start(20,"setAverages"); - setScalarAverages(); + clockM().start(20,"setVectorAverage"); setVectorAverages(); @@ -652,7 +621,7 @@ bool cfdemCloud::evolve if(!treatVoidCellsAsExplicitForce()) smoothingM().smoothenReferenceField(averagingM().UsNext()); - clockM().stop("setAverages"); + clockM().stop("setVectorAverage"); } //============================================ @@ -744,7 +713,7 @@ bool cfdemCloud::reAllocArrays() dataExchangeM().allocateArray(particleVolumes_,0.,voidFractionM().maxCellsPerParticle()); dataExchangeM().allocateArray(particleV_,0.,1); if(getParticleDensities_) dataExchangeM().allocateArray(particleDensities_,0.,1); - if(getParticleTypes_) dataExchangeM().allocateArray(particleTypes_,0.,1); + if(getParticleAngVels_) dataExchangeM().allocateArray(particleAngVels_,0.,3); arraysReallocated_ = true; return true; } diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H index 1b3f78cf..ce0dd254 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H @@ -98,7 +98,7 @@ protected: bool getParticleDensities_; - bool getParticleTypes_; + bool getParticleAngVels_; scalar maxDEMForce_; @@ -128,7 +128,7 @@ protected: mutable double **particleDensities_; - mutable int **particleTypes_; + mutable double **particleAngVels_; mutable double **particleWeights_; @@ -170,8 +170,6 @@ protected: mutable volScalarField ddtVoidfraction_; - mutable volScalarField particleDensityField_; - mutable Switch checkPeriodicCells_; const turbulenceModel& turbulence_; @@ -215,8 +213,6 @@ protected: virtual void setParticleForceField(); - virtual void setScalarAverages(); - virtual void setVectorAverages(); public: @@ -335,15 +331,15 @@ public: virtual inline int maxType() {return -1;} virtual inline bool multipleTypesDMax() {return false;} virtual inline bool multipleTypesDMin() {return false;} - virtual inline double ** particleDensity() const; + virtual inline double ** particleDensities() const; virtual inline double particleDensity(label index) const; - virtual inline int ** particleTypes() const; - virtual inline label particleType(label index) const; + virtual inline double ** particleAngVels() const; + virtual vector particleAngVel(label index) const; + virtual inline int ** particleTypes() const {return NULL;} + virtual label particleType(label index) const {return -1;} - //access to the particle's rotation and torque data + //access to the particle's and torque data virtual inline double ** DEMTorques() const {return NULL;} - virtual inline double ** omegaArray() const {return NULL;} - virtual vector omega(int) const {return vector::zero;} //access to the particles' orientation information virtual inline double ** exArray() const {return NULL;} diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H index 56ddfa48..e4dfb590 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H @@ -216,7 +216,7 @@ inline double cfdemCloud::d32(bool recalc) return d32_; } -inline double ** cfdemCloud::particleDensity() const +inline double ** cfdemCloud::particleDensities() const { if(!getParticleDensities_) return NULL; else @@ -234,21 +234,23 @@ inline double cfdemCloud::particleDensity(label index) const } } -inline int ** cfdemCloud::particleTypes() const +inline double ** cfdemCloud::particleAngVels() const { - if(!getParticleTypes_) return NULL; + if(!getParticleAngVels_) return NULL; else { - return particleTypes_; + return particleAngVels_; } } -inline label cfdemCloud::particleType(label index) const +inline vector cfdemCloud::particleAngVel(label index) const { - if(!getParticleDensities_) return -1; + if(!getParticleAngVels_) return vector::zero; else { - return particleTypes_[index][0]; + vector angVel; + for(int i=0;i<3;i++) angVel[i] = particleAngVels_[index][i]; + return angVel; } } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C index 7472f791..31c59592 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C @@ -94,13 +94,15 @@ MeiLift::MeiLift { Info << "Lift model: including spin-induced term.\n"; Info << "Make sure to use a rolling friction model in LIGGGHTS!\n"; + if(!dict.lookupOrDefault("getParticleAngVels",false)) + FatalError << "Lift model: useSpinInduced=true requires getParticleAngVels=true in couplingProperties" << abort(FatalError); } if(combineShearSpin_) { Info << "Lift model: combining shear- and spin-terms by assuming equilibrium spin-rate.\n"; if(!useShearInduced_ || !useSpinInduced_) - FatalError << "Shear- and spin-induced lift must be activated in order to combine.\n"; + FatalError << "Shear- and spin-induced lift must be activated in order to combine." << abort(FatalError); } // init force sub model @@ -199,7 +201,7 @@ void MeiLift::setForce() const { // properties Us = particleCloud_.velocity(index); - Omega = particleCloud_.omega(index); + Omega = particleCloud_.particleAngVel(index); if (forceSubM(0).interpolation()) { @@ -227,26 +229,7 @@ void MeiLift::setForce() const Rew = magVorticity*ds*ds/nuf; omega_star = magVorticity * ds / magUr; alphaStar = 0.5 * omega_star; - /* - //Second order terms given by Loth and Dorgan (2009) - if (useSecondOrderTerms_) - { - scalar sqrtRep = sqrt(Rep); - //Loth and Dorgan (2009), Eq (34) - Cl_star = 1.0 - (0.675 + 0.15 * (1.0 + tanh(0.28 * (alphaStar - 2.0)))) * tanh(0.18 * sqrtRep); - //Loth and Dorgan (2009), Eq (38) - Omega_eq = alphaStar * (1.0 - 0.0075 * Rew) * (1.0 - 0.062 * sqrtRep - 0.001 * Rep); - //Loth and Dorgan (2009), Eq (39) - Cl += Omega_eq * Cl_star; - } - - //Loth and Dorgan (2009), Eq (27) - lift = 0.125 * constant::mathematical::pi - * rho - * Cl - * magUr * Ur ^ vorticity / magVorticity - * ds * ds; - */ epsilonSqr = omega_star / Rep; + epsilonSqr = omega_star / Rep; epsilon = sqrt(epsilonSqr); diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 37badab6..35d2b498 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -113,6 +113,10 @@ virtualMassForce::virtualMassForce { Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; Info << "WARNING: ignoring user-set Cadd \n"; + + bool getParticleDensities_ = dict.lookupOrDefault("getParticleDensities",false); + if(!dict.lookupOrDefault("getParticleDensities",false)) + FatalError << "Virtual mass model: useFelderhof=true requires getParticleDensities=true in couplingProperties" << abort(FatalError); } particleCloud_.checkCG(true); @@ -259,7 +263,7 @@ void virtualMassForce::setForce() const else voidfraction = voidfraction_[cellI]; - sg = particleCloud_.density(index) / rho; + sg = particleCloud_.particleDensity(index) / rho; logsg = log(sg); epsilons = 1-voidfraction; From f79a21bb884c1275a81c52769ac6be9ff2082859 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 18 May 2018 14:33:20 +0200 Subject: [PATCH 07/47] Correction based on Beetra's erratum --- .../subModels/forceModel/BeetstraDrag/BeetstraDrag.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C index c24a85d0..eb7a8f89 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C @@ -207,7 +207,7 @@ void BeetstraDrag::setForce() const // Beetstra et. al (2007), Eq. (21) yi = ds_scaled/dSauter; - Fdrag *= (voidfraction*yi + localPhiP*yi*yi + 0.064*voidfraction*yi*yi*yi); + Fdrag *= (voidfraction*yi + 0.064*voidfraction*yi*yi*yi); } // calc particle's drag From 54b88ed8732fa9cb2309f0193d5b142121eb25e2 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 25 Jun 2018 10:04:07 +0200 Subject: [PATCH 08/47] Loosened timeStepFraction constraint, preventing unnecessary crashes --- src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index 98869b87..7158bcfc 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -629,7 +629,7 @@ bool cfdemCloud::evolve // IMPLICIT FORCE CONTRIBUTION AND SOLVER USE EXACTLY THE SAME AVERAGED // QUANTITIES AT THE GRID! Info << "\n timeStepFraction() = " << dataExchangeM().timeStepFraction() << endl; - if(dataExchangeM().timeStepFraction() > 1.0000001) + if(dataExchangeM().timeStepFraction() > 1.001) { FatalError << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); } From 693e9fd40463fbf305794490290fce4ea8b7da56 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 25 Jun 2018 10:10:45 +0200 Subject: [PATCH 09/47] Extension of cfdemSolverMultiphase with scalar transport --- .../cfdemSolverMultiphaseScalar/Allwclean | 8 + .../cfdemSolverMultiphaseScalar/Allwmake | 12 + .../cfdemSolverMultiphaseScalar/Make/files | 3 + .../cfdemSolverMultiphaseScalar/Make/options | 30 + .../cfdemSolverMultiphaseScalar/TEqn.H | 15 + .../cfdemSolverMultiphaseScalar/UEqn.H | 61 ++ .../additionalChecks.H | 17 + .../alphaCourantNo.H | 21 + .../cfdemSolverMultiphaseScalar.C | 149 ++++ .../cfdemSolverMultiphaseScalar/correctPhi.H | 11 + .../createFields.H | 203 +++++ .../multiphaseMixture/Make/files | 5 + .../multiphaseMixture/Make/options | 13 + .../alphaContactAngleFvPatchScalarField.C | 146 ++++ .../alphaContactAngleFvPatchScalarField.H | 215 +++++ .../alphaContactAngleFvPatchScalarField.C | 1 + .../alphaContactAngleFvPatchScalarField.H | 1 + .../lnInclude/multiphaseMixture.C | 1 + .../lnInclude/multiphaseMixture.H | 1 + .../multiphaseMixture/lnInclude/phase.C | 1 + .../multiphaseMixture/lnInclude/phase.H | 1 + .../multiphaseMixture/multiphaseMixture.C | 807 ++++++++++++++++++ .../multiphaseMixture/multiphaseMixture.H | 290 +++++++ .../multiphaseMixture/phase/phase.C | 101 +++ .../multiphaseMixture/phase/phase.H | 169 ++++ .../cfdemSolverMultiphaseScalar/pEqn.H | 73 ++ 26 files changed, 2355 insertions(+) create mode 100755 applications/solvers/cfdemSolverMultiphaseScalar/Allwclean create mode 100755 applications/solvers/cfdemSolverMultiphaseScalar/Allwmake create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/Make/files create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/Make/options create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/UEqn.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/additionalChecks.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/alphaCourantNo.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/correctPhi.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/createFields.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/options create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.C create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.H create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.C create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.H create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.C create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.H create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.C create mode 120000 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/pEqn.H diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/Allwclean b/applications/solvers/cfdemSolverMultiphaseScalar/Allwclean new file mode 100755 index 00000000..1c8a5a68 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/Allwclean @@ -0,0 +1,8 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +set -x + +wclean libso multiphaseMixture +wclean + +#------------------------------------------------------------------------------ diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/Allwmake b/applications/solvers/cfdemSolverMultiphaseScalar/Allwmake new file mode 100755 index 00000000..fbe71a59 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/Allwmake @@ -0,0 +1,12 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Parse arguments for library compilation +targetType=libso +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments +set -x + +wmake $targetType multiphaseMixture +wmake + +#------------------------------------------------------------------------------ diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/Make/files b/applications/solvers/cfdemSolverMultiphaseScalar/Make/files new file mode 100644 index 00000000..b4567eab --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/Make/files @@ -0,0 +1,3 @@ +cfdemSolverMultiphaseScalar.C + +EXE = $(CFDEM_APP_DIR)/cfdemSolverMultiphaseScalar diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/Make/options b/applications/solvers/cfdemSolverMultiphaseScalar/Make/options new file mode 100644 index 00000000..78dc7582 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/Make/options @@ -0,0 +1,30 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -ImultiphaseMixture/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels/interfaceProperties/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/sampling/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lcfdemMultiphaseInterFoam \ + -linterfaceProperties \ + -lincompressibleTransportModels \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lfiniteVolume \ + -lfvOptions \ + -lmeshTools \ + -lsampling \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ + $(CFDEM_ADD_LIBS) diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H new file mode 100644 index 00000000..6513b654 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H @@ -0,0 +1,15 @@ + // get scalar source from DEM + particleCloud.forceM(1).manipulateScalarField(Tsource); + Tsource.correctBoundaryConditions(); + + // solve scalar transport equation + fvScalarMatrix TEqn + ( + fvm::ddt(voidfraction,T) - fvm::Sp(fvc::ddt(voidfraction),T) + + fvm::div(phi, T) - fvm::Sp(fvc::div(phi),T) + - fvm::laplacian(DT*voidfraction, T) + == + Tsource + ); + TEqn.relax(); + TEqn.solve(); \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/UEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/UEqn.H new file mode 100644 index 00000000..86d12e50 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/UEqn.H @@ -0,0 +1,61 @@ +const surfaceScalarField& rhoPhi(mixture.rhoPhi()); + +volScalarField muEff = rho*(turbulence->nu() + turbulence->nut()); + +if (modelType == "A") + muEff *= voidfraction; + +fvVectorMatrix UEqn +( + fvm::ddt(rhoEps, U) - fvm::Sp(fvc::ddt(rhoEps),U) + + fvm::div(rhoPhi, U) - fvm::Sp(fvc::div(rhoPhi),U) + //+ particleCloud.divVoidfractionTau(U, voidfraction) + - fvm::laplacian(muEff, U) - fvc::div(muEff*dev2(fvc::grad(U)().T())) + == + fvOptions(rho, U) + - fvm::Sp(Ksl,U) +); + +UEqn.relax(); + +fvOptions.constrain(UEqn); + +if (pimple.momentumPredictor() && (modelType=="B" || modelType=="Bfull")) +{ + solve + ( + UEqn + == + fvc::reconstruct + ( + (- ghf*fvc::snGrad(rho) - fvc::snGrad(p_rgh)) * mesh.magSf() + ) + + + fvc::reconstruct + ( + mixture.surfaceTensionForce() * mesh.magSf() + ) * voidfraction + + Ksl*Us + ); + + fvOptions.correct(U); +} +else if (pimple.momentumPredictor()) +{ + solve + ( + UEqn + == + fvc::reconstruct + ( + ( + mixture.surfaceTensionForce() + - ghf*fvc::snGrad(rho) + - fvc::snGrad(p_rgh) + ) * mesh.magSf() + ) * voidfraction + + Ksl*Us + ); + + fvOptions.correct(U); +} diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/additionalChecks.H b/applications/solvers/cfdemSolverMultiphaseScalar/additionalChecks.H new file mode 100644 index 00000000..6f485462 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/additionalChecks.H @@ -0,0 +1,17 @@ +// Additional solver-specific checks + +// Useful if one wants to e.g. initialize floating particles using the Archimedes model +if (particleCloud.couplingProperties().found("unrestrictedForceModelSelection")) +{ + Warning << "Using unrestrictedForceModelSelection, results may be incorrect!" << endl; +} else +{ + #include "checkModelType.H" +} + +word modelType = particleCloud.modelType(); + +if(!particleCloud.couplingProperties().found("useDDTvoidfraction")) +{ + Warning << "Suppressing ddt(voidfraction) is not recommended with this solver as it may generate incorrect results!" << endl; +} diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/alphaCourantNo.H b/applications/solvers/cfdemSolverMultiphaseScalar/alphaCourantNo.H new file mode 100644 index 00000000..61dafb14 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/alphaCourantNo.H @@ -0,0 +1,21 @@ +scalar alphaCoNum = 0.0; +scalar meanAlphaCoNum = 0.0; + +if (mesh.nInternalFaces()) +{ + scalarField sumPhi + ( + mixture.nearInterface()().primitiveField() + *fvc::surfaceSum(mag(phi))().primitiveField() + ); + + alphaCoNum = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue(); + + meanAlphaCoNum = + 0.5*(gSum(sumPhi)/gSum(mesh.V().field()))*runTime.deltaTValue(); +} + +Info<< "Interface Courant Number mean: " << meanAlphaCoNum + << " max: " << alphaCoNum << endl; + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C new file mode 100644 index 00000000..6bcb8e36 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria + +Application + cfdemSolverMultiphase + +Description + CFD-DEM solver for n incompressible fluids which captures the interfaces and + includes surface-tension and contact-angle effects for each phase. It is based + on the OpenFOAM(R)-4.x solver multiphaseInterFoam but extended to incorporate + DEM functionalities from the open-source DEM code LIGGGHTS. + + Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected. + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "multiphaseMixture.H" +#include "turbulentTransportModel.H" +#include "pimpleControl.H" +#include "fvOptions.H" +#include "CorrectPhi.H" + +#include "cfdemCloud.H" +#include "implicitCouple.H" +#include "clockModel.H" +#include "smoothingModel.H" +#include "forceModel.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "initContinuityErrs.H" + #include "createFields.H" + #include "createFvOptions.H" + #include "correctPhi.H" + #include "CourantNo.H" + + turbulence->validate(); + + // create cfdemCloud + cfdemCloud particleCloud(mesh); + + #include "additionalChecks.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info<< "\nStarting time loop\n" << endl; + + while (runTime.loop()) + { + #include "CourantNo.H" + #include "alphaCourantNo.H" + + particleCloud.clockM().start(1,"Global"); + + Info<< "Time = " << runTime.timeName() << nl << endl; + + particleCloud.clockM().start(2,"Coupling"); + bool hasEvolved = particleCloud.evolve(voidfraction,Us,U); + + if(hasEvolved) + { + particleCloud.smoothingM().smoothen(particleCloud.forceM(0).impParticleForces()); + } + + Info << "update Ksl.internalField()" << endl; + Ksl = particleCloud.momCoupleM(0).impMomSource(); + Ksl.correctBoundaryConditions(); + + //Force Checks + vector fTotal(0,0,0); + vector fImpTotal = sum(mesh.V()*Ksl.internalField()*(Us.internalField()-U.internalField())).value(); + reduce(fImpTotal, sumOp()); + Info << "TotalForceExp: " << fTotal << endl; + Info << "TotalForceImp: " << fImpTotal << endl; + + #include "solverDebugInfo.H" + particleCloud.clockM().stop("Coupling"); + + particleCloud.clockM().start(26,"Flow"); + + #include "TEqn.H" + + if(particleCloud.solveFlow()) + { + mixture.solve(); + rho = mixture.rho(); + rhoEps = rho * voidfraction; + + // --- Pressure-velocity PIMPLE corrector loop + while (pimple.loop()) + { + #include "UEqn.H" + + // --- Pressure corrector loop + while (pimple.correct()) + { + #include "pEqn.H" + } + + if (pimple.turbCorr()) + { + turbulence->correct(); + } + } + } + else + { + Info << "skipping flow solution." << endl; + } + + runTime.write(); + + Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + + particleCloud.clockM().stop("Flow"); + particleCloud.clockM().stop("Global"); + } + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/correctPhi.H b/applications/solvers/cfdemSolverMultiphaseScalar/correctPhi.H new file mode 100644 index 00000000..9afcd58a --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/correctPhi.H @@ -0,0 +1,11 @@ +CorrectPhi +( + U, + phi, + p_rgh, + dimensionedScalar("rAUf", dimTime/rho.dimensions(), 1), + geometricZeroField(), + pimple +); + +#include "continuityErrs.H" diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H new file mode 100644 index 00000000..d1d2371a --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H @@ -0,0 +1,203 @@ +//=============================== +// particle interaction modelling +//=============================== + +Info<< "\nReading momentum exchange field Ksl\n" << endl; +volScalarField Ksl +( + IOobject + ( + "Ksl", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + //dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 1.0) +); + +Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl; +volScalarField voidfraction +( + IOobject + ( + "voidfraction", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); +voidfraction.oldTime(); + +Info<< "Reading particle velocity field Us\n" << endl; +volVectorField Us +( + IOobject + ( + "Us", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +Info<< "Reading field p_rgh\n" << endl; +volScalarField p_rgh +( + IOobject + ( + "p_rgh", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +Info<< "Reading field U\n" << endl; +volVectorField U +( + IOobject + ( + "U", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +Info<< "Reading/calculating face flux field phi\n" << endl; +surfaceScalarField phi + ( + IOobject + ( + "phi", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + linearInterpolate(U*voidfraction) & mesh.Sf() + ); + +multiphaseMixture mixture(U, phi, voidfraction); + +// Need to store rho for ddt(rho, U) +volScalarField rho +( + IOobject + ( + "rho", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mixture.rho() +); +rho.oldTime(); + +//======================== +// scalar field modelling +//======================== +Info<< "Reading/creating thermal fields\n" << endl; +volScalarField T +( + IOobject + ( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +volScalarField Tsource +( + IOobject + ( + "Tsource", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +volScalarField DT +( + IOobject + ( + "DT", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mixture.DT() +); + +//======================== + +volScalarField rhoEps ("rhoEps", rho * voidfraction); + +// Construct incompressible turbulence model +autoPtr turbulence +( + incompressible::turbulenceModel::New(U, phi, mixture) +); + + +#include "readGravitationalAcceleration.H" +#include "readhRef.H" +#include "gh.H" + + +volScalarField p +( + IOobject + ( + "p", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + p_rgh + rho*gh +); + +label pRefCell = 0; +scalar pRefValue = 0.0; +setRefCell +( + p, + p_rgh, + pimple.dict(), + pRefCell, + pRefValue +); + +if (p_rgh.needReference()) +{ + p += dimensionedScalar + ( + "p", + p.dimensions(), + pRefValue - getRefCellValue(p, pRefCell) + ); +} + +mesh.setFluxRequired(p_rgh.name()); + + diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files new file mode 100644 index 00000000..572171ec --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files @@ -0,0 +1,5 @@ +phase/phase.C +alphaContactAngle/alphaContactAngleFvPatchScalarField.C +multiphaseMixture.C + +LIB = $(CFDEM_LIB_DIR)/libcfdemMultiphaseInterFoam diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/options b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/options new file mode 100644 index 00000000..f8ffa1cf --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/options @@ -0,0 +1,13 @@ +EXE_INC = \ + -IalphaContactAngle \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels/interfaceProperties/lnInclude \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +LIB_LIBS = \ + -linterfaceProperties \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.C new file mode 100644 index 00000000..a0d433f4 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.C @@ -0,0 +1,146 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +\*---------------------------------------------------------------------------*/ + +#include "alphaContactAngleFvPatchScalarField.H" +#include "addToRunTimeSelectionTable.H" +#include "fvPatchFieldMapper.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +alphaContactAngleFvPatchScalarField::interfaceThetaProps::interfaceThetaProps +( + Istream& is +) +: + theta0_(readScalar(is)), + uTheta_(readScalar(is)), + thetaA_(readScalar(is)), + thetaR_(readScalar(is)) +{} + + +Istream& operator>> +( + Istream& is, + alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp +) +{ + is >> tp.theta0_ >> tp.uTheta_ >> tp.thetaA_ >> tp.thetaR_; + return is; +} + + +Ostream& operator<< +( + Ostream& os, + const alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp +) +{ + os << tp.theta0_ << token::SPACE + << tp.uTheta_ << token::SPACE + << tp.thetaA_ << token::SPACE + << tp.thetaR_; + + return os; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField +( + const fvPatch& p, + const DimensionedField& iF +) +: + zeroGradientFvPatchScalarField(p, iF) +{} + + +alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField +( + const alphaContactAngleFvPatchScalarField& gcpsf, + const fvPatch& p, + const DimensionedField& iF, + const fvPatchFieldMapper& mapper +) +: + zeroGradientFvPatchScalarField(gcpsf, p, iF, mapper), + thetaProps_(gcpsf.thetaProps_) +{} + + +alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField +( + const fvPatch& p, + const DimensionedField& iF, + const dictionary& dict +) +: + zeroGradientFvPatchScalarField(p, iF), + thetaProps_(dict.lookup("thetaProperties")) +{ + evaluate(); +} + + +alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField +( + const alphaContactAngleFvPatchScalarField& gcpsf, + const DimensionedField& iF +) +: + zeroGradientFvPatchScalarField(gcpsf, iF), + thetaProps_(gcpsf.thetaProps_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void alphaContactAngleFvPatchScalarField::write(Ostream& os) const +{ + fvPatchScalarField::write(os); + os.writeKeyword("thetaProperties") + << thetaProps_ << token::END_STATEMENT << nl; + writeEntry("value", os); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePatchTypeField +( + fvPatchScalarField, + alphaContactAngleFvPatchScalarField +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.H new file mode 100644 index 00000000..09249c72 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/alphaContactAngle/alphaContactAngleFvPatchScalarField.H @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 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 . + +Class + Foam::alphaContactAngleFvPatchScalarField + +Description + Contact-angle boundary condition for multi-phase interface-capturing + simulations. Used in conjuction with multiphaseMixture. + +SourceFiles + alphaContactAngleFvPatchScalarField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef alphaContactAngleFvPatchScalarField_H +#define alphaContactAngleFvPatchScalarField_H + +#include "zeroGradientFvPatchFields.H" +#include "multiphaseMixture.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class alphaContactAngleFvPatch Declaration +\*---------------------------------------------------------------------------*/ + +class alphaContactAngleFvPatchScalarField +: + public zeroGradientFvPatchScalarField +{ +public: + + class interfaceThetaProps + { + //- Equilibrium contact angle + scalar theta0_; + + //- Dynamic contact angle velocity scale + scalar uTheta_; + + //- Limiting advancing contact angle + scalar thetaA_; + + //- Limiting receeding contact angle + scalar thetaR_; + + + public: + + // Constructors + interfaceThetaProps() + {} + + interfaceThetaProps(Istream&); + + + // Member functions + + //- Return the equilibrium contact angle theta0 + scalar theta0(bool matched=true) const + { + if (matched) return theta0_; + else return 180.0 - theta0_; + } + + //- Return the dynamic contact angle velocity scale + scalar uTheta() const + { + return uTheta_; + } + + //- Return the limiting advancing contact angle + scalar thetaA(bool matched=true) const + { + if (matched) return thetaA_; + else return 180.0 - thetaA_; + } + + //- Return the limiting receeding contact angle + scalar thetaR(bool matched=true) const + { + if (matched) return thetaR_; + else return 180.0 - thetaR_; + } + + + // IO functions + + friend Istream& operator>>(Istream&, interfaceThetaProps&); + friend Ostream& operator<<(Ostream&, const interfaceThetaProps&); + }; + + typedef HashTable + < + interfaceThetaProps, + multiphaseMixture::interfacePair, + multiphaseMixture::interfacePair::hash + > thetaPropsTable; + + +private: + + // Private data + + thetaPropsTable thetaProps_; + + +public: + + //- Runtime type information + TypeName("alphaContactAngle"); + + + // Constructors + + //- Construct from patch and internal field + alphaContactAngleFvPatchScalarField + ( + const fvPatch&, + const DimensionedField& + ); + + //- Construct from patch, internal field and dictionary + alphaContactAngleFvPatchScalarField + ( + const fvPatch&, + const DimensionedField&, + const dictionary& + ); + + //- Construct by mapping given alphaContactAngleFvPatchScalarField + // onto a new patch + alphaContactAngleFvPatchScalarField + ( + const alphaContactAngleFvPatchScalarField&, + const fvPatch&, + const DimensionedField&, + const fvPatchFieldMapper& + ); + + //- Construct and return a clone + virtual tmp clone() const + { + return tmp + ( + new alphaContactAngleFvPatchScalarField(*this) + ); + } + + //- Construct as copy setting internal field reference + alphaContactAngleFvPatchScalarField + ( + const alphaContactAngleFvPatchScalarField&, + const DimensionedField& + ); + + //- Construct and return a clone setting internal field reference + virtual tmp clone + ( + const DimensionedField& iF + ) const + { + return tmp + ( + new alphaContactAngleFvPatchScalarField(*this, iF) + ); + } + + + // Member functions + + //- Return the contact angle properties + const thetaPropsTable& thetaProps() const + { + return thetaProps_; + } + + //- Write + virtual void write(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.C new file mode 120000 index 00000000..b5cf3fd0 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.C @@ -0,0 +1 @@ +../alphaContactAngle/alphaContactAngleFvPatchScalarField.C \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.H new file mode 120000 index 00000000..c7e4030f --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/alphaContactAngleFvPatchScalarField.H @@ -0,0 +1 @@ +../alphaContactAngle/alphaContactAngleFvPatchScalarField.H \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.C new file mode 120000 index 00000000..139112c3 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.C @@ -0,0 +1 @@ +../multiphaseMixture.C \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.H new file mode 120000 index 00000000..d780b93e --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/multiphaseMixture.H @@ -0,0 +1 @@ +../multiphaseMixture.H \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.C new file mode 120000 index 00000000..aba05d8b --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.C @@ -0,0 +1 @@ +../phase/phase.C \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.H new file mode 120000 index 00000000..0010ad9b --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/lnInclude/phase.H @@ -0,0 +1 @@ +../phase/phase.H \ No newline at end of file diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C new file mode 100644 index 00000000..ad255511 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C @@ -0,0 +1,807 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "multiphaseMixture.H" +#include "alphaContactAngleFvPatchScalarField.H" +#include "Time.H" +#include "subCycle.H" +#include "MULES.H" +#include "surfaceInterpolate.H" +#include "fvcGrad.H" +#include "fvcSnGrad.H" +#include "fvcDiv.H" +#include "fvcFlux.H" + +// * * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * // + +const Foam::scalar Foam::multiphaseMixture::convertToRad = + Foam::constant::mathematical::pi/180.0; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::multiphaseMixture::calcAlphas() +{ + scalar level = 0.0; + alphas_ == 0.0; + + forAllIter(PtrDictionary, phases_, iter) + { + alphas_ += level*iter(); + level += 1.0; + } +} + + +Foam::tmp +Foam::multiphaseMixture::calcNu() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnu = iter()*iter().nu(); + volScalarField& nu = tnu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nu += iter()*iter().nu(); + } + + return tnu; +} + +Foam::tmp +Foam::multiphaseMixture::calcStf() const +{ + tmp tstf + ( + new surfaceScalarField + ( + IOobject + ( + "stf", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar + ( + "stf", + dimensionSet(1, -2, -2, 0, 0), + 0.0 + ) + ) + ); + + surfaceScalarField& stf = tstf.ref(); + + forAllConstIter(PtrDictionary, phases_, iter1) + { + const phase& alpha1 = iter1(); + + PtrDictionary::const_iterator iter2 = iter1; + ++iter2; + + for (; iter2 != phases_.end(); ++iter2) + { + const phase& alpha2 = iter2(); + + sigmaTable::const_iterator sigma = + sigmas_.find(interfacePair(alpha1, alpha2)); + + if (sigma == sigmas_.end()) + { + FatalErrorInFunction + << "Cannot find interface " << interfacePair(alpha1, alpha2) + << " in list of sigma values" + << exit(FatalError); + } + + stf += dimensionedScalar("sigma", dimSigma_, sigma()) + *fvc::interpolate(K(alpha1, alpha2))* + ( + fvc::interpolate(alpha2)*fvc::snGrad(alpha1) + - fvc::interpolate(alpha1)*fvc::snGrad(alpha2) + ); + } + } + + return tstf; +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::multiphaseMixture::multiphaseMixture +( + const volVectorField& U, + const surfaceScalarField& phi, + const volScalarField& voidfraction +) +: + IOdictionary + ( + IOobject + ( + "transportProperties", + U.time().constant(), + U.db(), + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ), + + phases_(lookup("phases"), phase::iNew(U, phi)), + + mesh_(U.mesh()), + U_(U), + phi_(phi), + voidfraction_(voidfraction), + rhoPhi_ + ( + IOobject + ( + "rhoPhi", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh_, + dimensionedScalar("rhoPhi", dimMass/dimTime, 0.0) + ), + surfaceTensionForce_ + ( + IOobject + ( + "surfaceTensionForce", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh_, + dimensionedScalar("surfaceTensionForce", dimensionSet(1, -2, -2, 0, 0), 0.0) + ), + alphas_ + ( + IOobject + ( + "alphas", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh_, + dimensionedScalar("alphas", dimless, 0.0) + ), + + nu_ + ( + IOobject + ( + "nu", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + calcNu() + ), + + sigmas_(lookup("sigmas")), + dimSigma_(1, 0, -2, 0, 0), + deltaN_ + ( + "deltaN", + 1e-8/pow(average(mesh_.V()), 1.0/3.0) + ) +{ + calcAlphas(); + alphas_.write(); + surfaceTensionForce_ = calcStf(); + +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::tmp +Foam::multiphaseMixture::rho() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp trho = iter()*iter().rho(); + volScalarField& rho = trho.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rho += iter()*iter().rho(); + } + + return trho; +} + + +Foam::tmp +Foam::multiphaseMixture::rho(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp trho = iter().boundaryField()[patchi]*iter().rho().value(); + scalarField& rho = trho.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rho += iter().boundaryField()[patchi]*iter().rho().value(); + } + + return trho; +} + + +Foam::tmp +Foam::multiphaseMixture::mu() const +{ + Info << "In multiphasemixture mu()" << endl; + return rho()*nu(); +// PtrDictionary::const_iterator iter = phases_.begin(); + +// tmp tmu = iter()*iter().rho()*iter().nu(); +// volScalarField& mu = tmu.ref(); + +// for (++iter; iter != phases_.end(); ++iter) +// { +// mu += iter()*iter().rho()*iter().nu(); +// } + +// return tmu; +} + + +Foam::tmp +Foam::multiphaseMixture::mu(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tmu = + iter().boundaryField()[patchi] + *iter().rho().value() + *iter().nu(patchi); + scalarField& mu = tmu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + mu += + iter().boundaryField()[patchi] + *iter().rho().value() + *iter().nu(patchi); + } + + return tmu; +} + + +Foam::tmp +Foam::multiphaseMixture::muf() const +{ + + return nuf()*fvc::interpolate(rho()); +// PtrDictionary::const_iterator iter = phases_.begin(); + +// tmp tmuf = +// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); +// surfaceScalarField& muf = tmuf.ref(); + +// for (++iter; iter != phases_.end(); ++iter) +// { +// muf += +// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); +// } + +// return tmuf; +} + + +Foam::tmp +Foam::multiphaseMixture::nu() const +{ + return nu_; +} + + +Foam::tmp +Foam::multiphaseMixture::nu(const label patchi) const +{ + //return nu_.boundaryField()[patchi]; + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnu = + iter().boundaryField()[patchi] + *iter().nu(patchi); + scalarField& nu = tnu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nu += + iter().boundaryField()[patchi] + *iter().nu(patchi); + } + + return tnu; +} + + +Foam::tmp +Foam::multiphaseMixture::nuf() const +{ + //return muf()/fvc::interpolate(rho()); + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnuf = + fvc::interpolate(iter())*fvc::interpolate(iter().nu()); + surfaceScalarField& nuf = tnuf.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nuf += + fvc::interpolate(iter())*fvc::interpolate(iter().nu()); + } + + return tnuf; +} + +Foam::tmp +Foam::multiphaseMixture::DT() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tDT = iter()*iter().DT(); + volScalarField& DT = tDT.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + DT += iter()*iter().DT(); + } + + return tDT; +} + + +Foam::tmp +Foam::multiphaseMixture::DT(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tDT = iter().boundaryField()[patchi]*iter().DT().value(); + scalarField& DT = tDT.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + DT += iter().boundaryField()[patchi]*iter().DT().value(); + } + + return tDT; +} + +void Foam::multiphaseMixture::solve() +{ + correct(); + + const Time& runTime = mesh_.time(); + + volScalarField& alpha = phases_.first(); + + const dictionary& alphaControls = mesh_.solverDict("alpha"); + label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles"))); + scalar cAlpha(readScalar(alphaControls.lookup("cAlpha"))); + + if (nAlphaSubCycles > 1) + { + surfaceScalarField rhoPhiSum + ( + IOobject + ( + "rhoPhiSum", + runTime.timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("0", rhoPhi_.dimensions(), 0) + ); + + dimensionedScalar totalDeltaT = runTime.deltaT(); + + for + ( + subCycle alphaSubCycle(alpha, nAlphaSubCycles); + !(++alphaSubCycle).end(); + ) + { + FatalError << "Sub-cycling of the alpha equation not yet implemented!!" << abort(FatalError); + solveAlphas(cAlpha); + rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi_; + } + + rhoPhi_ = rhoPhiSum; + } + else + { + solveAlphas(cAlpha); + } + + // Update the mixture kinematic viscosity + nu_ = calcNu(); + + surfaceTensionForce_ = calcStf(); +} + + +void Foam::multiphaseMixture::correct() +{ + forAllIter(PtrDictionary, phases_, iter) + { + iter().correct(); + } +} + + +Foam::tmp Foam::multiphaseMixture::nHatfv +( + const volScalarField& alpha1, + const volScalarField& alpha2 +) const +{ + /* + // Cell gradient of alpha + volVectorField gradAlpha = + alpha2*fvc::grad(alpha1) - alpha1*fvc::grad(alpha2); + + // Interpolated face-gradient of alpha + surfaceVectorField gradAlphaf = fvc::interpolate(gradAlpha); + */ + + surfaceVectorField gradAlphaf + ( + fvc::interpolate(alpha2)*fvc::interpolate(fvc::grad(alpha1)) + - fvc::interpolate(alpha1)*fvc::interpolate(fvc::grad(alpha2)) + ); + + // Face unit interface normal + return gradAlphaf/(mag(gradAlphaf) + deltaN_); +} + + +Foam::tmp Foam::multiphaseMixture::nHatf +( + const volScalarField& alpha1, + const volScalarField& alpha2 +) const +{ + // Face unit interface normal flux + return nHatfv(alpha1, alpha2) & mesh_.Sf(); +} + + +// Correction for the boundary condition on the unit normal nHat on +// walls to produce the correct contact angle. + +// The dynamic contact angle is calculated from the component of the +// velocity on the direction of the interface, parallel to the wall. + +void Foam::multiphaseMixture::correctContactAngle +( + const phase& alpha1, + const phase& alpha2, + surfaceVectorField::Boundary& nHatb +) const +{ + const volScalarField::Boundary& gbf + = alpha1.boundaryField(); + + const fvBoundaryMesh& boundary = mesh_.boundary(); + + forAll(boundary, patchi) + { + if (isA(gbf[patchi])) + { + const alphaContactAngleFvPatchScalarField& acap = + refCast(gbf[patchi]); + + vectorField& nHatPatch = nHatb[patchi]; + + vectorField AfHatPatch + ( + mesh_.Sf().boundaryField()[patchi] + /mesh_.magSf().boundaryField()[patchi] + ); + + alphaContactAngleFvPatchScalarField::thetaPropsTable:: + const_iterator tp = + acap.thetaProps().find(interfacePair(alpha1, alpha2)); + + if (tp == acap.thetaProps().end()) + { + FatalErrorInFunction + << "Cannot find interface " << interfacePair(alpha1, alpha2) + << "\n in table of theta properties for patch " + << acap.patch().name() + << exit(FatalError); + } + + bool matched = (tp.key().first() == alpha1.name()); + + scalar theta0 = convertToRad*tp().theta0(matched); + scalarField theta(boundary[patchi].size(), theta0); + + scalar uTheta = tp().uTheta(); + + // Calculate the dynamic contact angle if required + if (uTheta > SMALL) + { + scalar thetaA = convertToRad*tp().thetaA(matched); + scalar thetaR = convertToRad*tp().thetaR(matched); + + // Calculated the component of the velocity parallel to the wall + vectorField Uwall + ( + U_.boundaryField()[patchi].patchInternalField() + - U_.boundaryField()[patchi] + ); + Uwall -= (AfHatPatch & Uwall)*AfHatPatch; + + // Find the direction of the interface parallel to the wall + vectorField nWall + ( + nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch + ); + + // Normalise nWall + nWall /= (mag(nWall) + SMALL); + + // Calculate Uwall resolved normal to the interface parallel to + // the interface + scalarField uwall(nWall & Uwall); + + theta += (thetaA - thetaR)*tanh(uwall/uTheta); + } + + + // Reset nHatPatch to correspond to the contact angle + + scalarField a12(nHatPatch & AfHatPatch); + + scalarField b1(cos(theta)); + + scalarField b2(nHatPatch.size()); + + forAll(b2, facei) + { + b2[facei] = cos(acos(a12[facei]) - theta[facei]); + } + + scalarField det(1.0 - a12*a12); + + scalarField a((b1 - a12*b2)/det); + scalarField b((b2 - a12*b1)/det); + + nHatPatch = a*AfHatPatch + b*nHatPatch; + + nHatPatch /= (mag(nHatPatch) + deltaN_.value()); + } + } +} + + +Foam::tmp Foam::multiphaseMixture::K +( + const phase& alpha1, + const phase& alpha2 +) const +{ + tmp tnHatfv = nHatfv(alpha1, alpha2); + + correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef()); + + // Simple expression for curvature + return -fvc::div(tnHatfv & mesh_.Sf()); +} + + +Foam::tmp +Foam::multiphaseMixture::nearInterface() const +{ + tmp tnearInt + ( + new volScalarField + ( + IOobject + ( + "nearInterface", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("nearInterface", dimless, 0.0) + ) + ); + + forAllConstIter(PtrDictionary, phases_, iter) + { + tnearInt.ref() = max(tnearInt(), pos(iter() - 0.01)*pos(0.99 - iter())); + } + + return tnearInt; +} + + +void Foam::multiphaseMixture::solveAlphas +( + const scalar cAlpha +) +{ + static label nSolves=-1; + nSolves++; + + word alphaScheme("div(phi,alpha)"); + word alpharScheme("div(phirb,alpha)"); + + surfaceScalarField phic(mag(phi_/mesh_.magSf())); + phic = min(cAlpha*phic, max(phic)); + + PtrList alphaPhiCorrs(phases_.size()); + int phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + phase& alpha = iter(); + + alphaPhiCorrs.set + ( + phasei, + new surfaceScalarField + ( + "phi" + alpha.name() + "Corr", + fvc::flux + ( + phi_, + alpha, + alphaScheme + ) + ) + ); + + surfaceScalarField& alphaPhiCorr = alphaPhiCorrs[phasei]; + + forAllIter(PtrDictionary, phases_, iter2) + { + phase& alpha2 = iter2(); + + if (&alpha2 == &alpha) continue; + + surfaceScalarField phir(phic*nHatf(alpha, alpha2)); + + alphaPhiCorr += fvc::flux + ( + -fvc::flux(-phir, alpha2, alpharScheme), + alpha, + alpharScheme + ); + } + + MULES::limit + ( + 1.0/mesh_.time().deltaT().value(), + voidfraction_, + alpha, + phi_, + alphaPhiCorr, + zeroField(), + zeroField(), + 1, + 0, + true + ); + + phasei++; + } + + MULES::limitSum(alphaPhiCorrs); + + rhoPhi_ = dimensionedScalar("0", dimensionSet(1, 0, -1, 0, 0), 0); + + volScalarField sumAlpha + ( + IOobject + ( + "sumAlpha", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("sumAlpha", dimless, 0) + ); + + phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + phase& alpha = iter(); + + surfaceScalarField& alphaPhi = alphaPhiCorrs[phasei]; + alphaPhi += upwind(mesh_, phi_).flux(alpha); + + MULES::explicitSolve + ( + voidfraction_, + alpha, + alphaPhi, + zeroField(), + zeroField() + ); + + rhoPhi_ += alphaPhi*alpha.rho(); + + Info<< alpha.name() << " volume fraction, min, max = " + << alpha.weightedAverage(mesh_.V()).value() + << ' ' << min(alpha).value() + << ' ' << max(alpha).value() + << endl; + + sumAlpha += alpha; + + phasei++; + } + + Info<< "Phase-sum volume fraction, min, max = " + << sumAlpha.weightedAverage(mesh_.V()).value() + << ' ' << min(sumAlpha).value() + << ' ' << max(sumAlpha).value() + << endl; + + calcAlphas(); +} + + +bool Foam::multiphaseMixture::read() +{ + if (transportModel::read()) + { + bool readOK = true; + + PtrList phaseData(lookup("phases")); + label phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + readOK &= iter().read(phaseData[phasei++].dict()); + } + + lookup("sigmas") >> sigmas_; + + return readOK; + } + else + { + return false; + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H new file mode 100644 index 00000000..3b093962 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H @@ -0,0 +1,290 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria + +Class + multiphaseMixture + +Description + This class is based on the OpenFOAM(R) Foam::multiphaseMixture class, + which is an incompressible multi-phase mixture with built in solution + for the phase fractions with interface compression for interface-capturing. + It has been extended to include the void fraction in the volume fraction + transport equations. + + Derived from transportModel so that it can be unsed in conjunction with + the incompressible turbulence models. + + Surface tension and contact-angle is handled for the interface + between each phase-pair. + +SourceFiles + multiphaseMixture.C +\*---------------------------------------------------------------------------*/ + +#ifndef multiphaseMixture_H +#define multiphaseMixture_H + +#include "incompressible/transportModel/transportModel.H" +#include "IOdictionary.H" +#include "phase.H" +#include "PtrDictionary.H" +#include "volFields.H" +#include "surfaceFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class multiphaseMixture Declaration +\*---------------------------------------------------------------------------*/ + +class multiphaseMixture +: + public IOdictionary, + public transportModel +{ +public: + + class interfacePair + : + public Pair + { + public: + + class hash + : + public Hash + { + public: + + hash() + {} + + label operator()(const interfacePair& key) const + { + return word::hash()(key.first()) + word::hash()(key.second()); + } + }; + + + // Constructors + + interfacePair() + {} + + interfacePair(const word& alpha1Name, const word& alpha2Name) + : + Pair(alpha1Name, alpha2Name) + {} + + interfacePair(const phase& alpha1, const phase& alpha2) + : + Pair(alpha1.name(), alpha2.name()) + {} + + + // Friend Operators + + friend bool operator== + ( + const interfacePair& a, + const interfacePair& b + ) + { + return + ( + ((a.first() == b.first()) && (a.second() == b.second())) + || ((a.first() == b.second()) && (a.second() == b.first())) + ); + } + + friend bool operator!= + ( + const interfacePair& a, + const interfacePair& b + ) + { + return (!(a == b)); + } + }; + + +private: + + // Private data + + //- Dictionary of phases + PtrDictionary phases_; + + const fvMesh& mesh_; + const volVectorField& U_; + const surfaceScalarField& phi_; + const volScalarField& voidfraction_; + surfaceScalarField rhoPhi_; + surfaceScalarField surfaceTensionForce_; + volScalarField alphas_; + + volScalarField nu_; + + typedef HashTable + sigmaTable; + + sigmaTable sigmas_; + dimensionSet dimSigma_; + + //- Stabilisation for normalisation of the interface normal + const dimensionedScalar deltaN_; + + //- Conversion factor for degrees into radians + static const scalar convertToRad; + + + // Private member functions + + void calcAlphas(); + + tmp calcNu() const; + + void solveAlphas(const scalar cAlpha); + + tmp nHatfv + ( + const volScalarField& alpha1, + const volScalarField& alpha2 + ) const; + + tmp nHatf + ( + const volScalarField& alpha1, + const volScalarField& alpha2 + ) const; + + void correctContactAngle + ( + const phase& alpha1, + const phase& alpha2, + surfaceVectorField::Boundary& nHatb + ) const; + + tmp K(const phase& alpha1, const phase& alpha2) const; + tmp calcStf() const; + +public: + + // Constructors + + //- Construct from components + multiphaseMixture + ( + const volVectorField& U, + const surfaceScalarField& phi, + const volScalarField& voidfraction + ); + + + //- Destructor + virtual ~multiphaseMixture() + {} + + + // Member Functions + + //- Return the phases + const PtrDictionary& phases() const + { + return phases_; + } + + //- Return the velocity + const volVectorField& U() const + { + return U_; + } + + //- Return the volumetric flux + const surfaceScalarField& phi() const + { + return phi_; + } + + const surfaceScalarField& rhoPhi() const + { + return rhoPhi_; + } + + //- Return the mixture density + tmp rho() const; + + //- Return the mixture density for patch + tmp rho(const label patchi) const; + + //- Return the dynamic laminar viscosity + tmp mu() const; + + //- Return the dynamic laminar viscosity for patch + tmp mu(const label patchi) const; + + //- Return the face-interpolated dynamic laminar viscosity + tmp muf() const; + + //- Return the kinematic laminar viscosity + tmp nu() const; + + //- Return the laminar viscosity for patch + tmp nu(const label patchi) const; + + //- Return the face-interpolated dynamic laminar viscosity + tmp nuf() const; + + //- Return the thermal diffusivity + tmp DT() const; + + //- Return the therm diffusivity for patch + tmp DT(const label patchi) const; + + tmp surfaceTensionForce() const + { + return surfaceTensionForce_; + } + + //- Indicator of the proximity of the interface + // Field values are 1 near and 0 away for the interface. + tmp nearInterface() const; + + //- Solve for the mixture phase-fractions + void solve(); + + //- Correct the mixture properties + void correct(); + + //- Read base transportProperties dictionary + bool read(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C new file mode 100644 index 00000000..192b672d --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2015 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 . + +\*---------------------------------------------------------------------------*/ + +#include "phase.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::phase::phase +( + const word& phaseName, + const dictionary& phaseDict, + const volVectorField& U, + const surfaceScalarField& phi +) +: + volScalarField + ( + IOobject + ( + IOobject::groupName("alpha", phaseName), + U.mesh().time().timeName(), + U.mesh(), + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + U.mesh() + ), + name_(phaseName), + phaseDict_(phaseDict), + nuModel_ + ( + viscosityModel::New + ( + IOobject::groupName("nu", phaseName), + phaseDict_, + U, + phi + ) + ), + rho_("rho", dimDensity, phaseDict_), + DT_("DT", (dimLength*dimLength/dimTime), phaseDict_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::autoPtr Foam::phase::clone() const +{ + NotImplemented; + return autoPtr(NULL); +} + + +void Foam::phase::correct() +{ + nuModel_->correct(); +} + + +bool Foam::phase::read(const dictionary& phaseDict) +{ + phaseDict_ = phaseDict; + + phaseDict_.lookup("DT") >> DT_; + + if (nuModel_->read(phaseDict_)) + { + phaseDict_.lookup("rho") >> rho_; + + return true; + } + else + { + return false; + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H new file mode 100644 index 00000000..748c6e2e --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H @@ -0,0 +1,169 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2015 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 . + +Class + Foam::phase + +Description + Single incompressible phase derived from the phase-fraction. + Used as part of the multiPhaseMixture for interface-capturing multi-phase + simulations. + +SourceFiles + phase.C + +\*---------------------------------------------------------------------------*/ + +#ifndef phase_H +#define phase_H + +#include "volFields.H" +#include "dictionaryEntry.H" +#include "incompressible/viscosityModels/viscosityModel/viscosityModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class phase Declaration +\*---------------------------------------------------------------------------*/ + +class phase +: + public volScalarField +{ + // Private data + + word name_; + dictionary phaseDict_; + autoPtr nuModel_; + dimensionedScalar rho_; + dimensionedScalar DT_; + +public: + + // Constructors + + //- Construct from components + phase + ( + const word& name, + const dictionary& phaseDict, + const volVectorField& U, + const surfaceScalarField& phi + ); + + //- Return clone + autoPtr clone() const; + + //- Return a pointer to a new phase created on freestore + // from Istream + class iNew + { + const volVectorField& U_; + const surfaceScalarField& phi_; + + public: + + iNew + ( + const volVectorField& U, + const surfaceScalarField& phi + ) + : + U_(U), + phi_(phi) + {} + + autoPtr operator()(Istream& is) const + { + dictionaryEntry ent(dictionary::null, is); + return autoPtr(new phase(ent.keyword(), ent, U_, phi_)); + } + }; + + + // Member Functions + + const word& name() const + { + return name_; + } + + const word& keyword() const + { + return name(); + } + + //- Return const-access to phase1 viscosityModel + const viscosityModel& nuModel() const + { + return nuModel_(); + } + + //- Return the kinematic laminar viscosity + tmp nu() const + { + return nuModel_->nu(); + } + + //- Return the laminar viscosity for patch + tmp nu(const label patchi) const + { + return nuModel_->nu(patchi); + } + + //- Return const-access to phase1 density + const dimensionedScalar& rho() const + { + return rho_; + } + + //- Return const-access to phase1 thermal diffusivity + const dimensionedScalar& DT() const + { + return DT_; + } + + //- Correct the phase properties + void correct(); + + //-Inherit read from volScalarField + using volScalarField::read; + + //- Read base transportProperties dictionary + bool read(const dictionary& phaseDict); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/pEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/pEqn.H new file mode 100644 index 00000000..e5a374f0 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/pEqn.H @@ -0,0 +1,73 @@ +{ + volScalarField rAU("rAU", 1.0/UEqn.A()); + surfaceScalarField rAUepsf("rAUepsf", fvc::interpolate(rAU*voidfraction)); + surfaceScalarField rAUepsSqf("rAUepsSqf", fvc::interpolate(rAU*voidfraction*voidfraction)); + volVectorField Ueps("Ueps", U * voidfraction); + + volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p_rgh)); + + surfaceScalarField phiHbyA + ( + "phiHbyA", + fvc::flux(HbyA*voidfraction) + + fvc::interpolate(voidfraction*rho*rAU)*fvc::ddtCorr(U, phi) + ); + + adjustPhi(phiHbyA, U, p_rgh); + + if (modelType == "A") + rAUepsf = rAUepsSqf; + + surfaceScalarField phig (-ghf*fvc::snGrad(rho)*rAUepsf*mesh.magSf()); + + surfaceScalarField phiSt (mixture.surfaceTensionForce()*rAUepsSqf*mesh.magSf()); + + surfaceScalarField phiS (fvc::flux(voidfraction*Us*Ksl*rAU)); + + phiHbyA += phig + phiSt + phiS; + + // Update the pressure BCs to ensure flux consistency + constrainPressure(p_rgh, Ueps, phiHbyA, rAUepsf); + + while (pimple.correctNonOrthogonal()) + { + fvScalarMatrix p_rghEqn + ( + fvm::laplacian(rAUepsf, p_rgh) == particleCloud.ddtVoidfraction() + fvc::div(phiHbyA) + ); + + p_rghEqn.setReference(pRefCell, getRefCellValue(p_rgh, pRefCell)); + + p_rghEqn.solve(mesh.solver(p_rgh.select(pimple.finalInnerIter()))); + + if (pimple.finalNonOrthogonalIter()) + { + phi = phiHbyA - p_rghEqn.flux(); + + p_rgh.relax(); + + if (modelType == "A") + U = HbyA + voidfraction*rAU*fvc::reconstruct((phig-p_rghEqn.flux()+phiSt)/rAUepsf) + rAU*Us*Ksl; + else + U = HbyA + rAU*fvc::reconstruct((phig-p_rghEqn.flux()+phiSt)/rAUepsf) + rAU*Us*Ksl; + + U.correctBoundaryConditions(); + fvOptions.correct(U); + } + } + + #include "continuityErrs.H" + + p == p_rgh + rho*gh; + + if (p_rgh.needReference()) + { + p += dimensionedScalar + ( + "p", + p.dimensions(), + pRefValue - getRefCellValue(p, pRefCell) + ); + p_rgh = p - rho*gh; + } +} From 44ade768203d33d2f0cc271704afe242ff042579 Mon Sep 17 00:00:00 2001 From: s126103 Date: Tue, 26 Jun 2018 11:24:39 +0200 Subject: [PATCH 10/47] Solver development --- .../Make/linux64GccDPInt32Opt/options | 1 + .../cfdemSolverMultiphaseScalar/Make/options | 2 +- .../cfdemSolverMultiphaseScalar/TEqn.H | 27 ++++++--- .../cfdemSolverMultiphaseScalar.C | 6 +- .../createFields.H | 23 ++++++-- .../multiphaseMixture/Make/files | 2 +- .../multiphaseMixture/multiphaseMixture.C | 56 +++++++++++++++---- .../multiphaseMixture/multiphaseMixture.H | 14 +++-- .../multiphaseMixture/phase/phase.C | 6 +- .../multiphaseMixture/phase/phase.H | 15 +++-- etc/solver-list.txt | 1 + 11 files changed, 116 insertions(+), 37 deletions(-) diff --git a/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/Make/linux64GccDPInt32Opt/options b/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/Make/linux64GccDPInt32Opt/options index a815f8a3..a2de1b02 100644 --- a/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/Make/linux64GccDPInt32Opt/options +++ b/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/Make/linux64GccDPInt32Opt/options @@ -45,6 +45,7 @@ + # 8 "" 2 diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/Make/options b/applications/solvers/cfdemSolverMultiphaseScalar/Make/options index 78dc7582..5d1853b8 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/Make/options +++ b/applications/solvers/cfdemSolverMultiphaseScalar/Make/options @@ -16,7 +16,7 @@ EXE_INC = \ EXE_LIBS = \ -L$(CFDEM_LIB_DIR)\ - -lcfdemMultiphaseInterFoam \ + -lcfdemMultiphaseInterFoamScalar \ -linterfaceProperties \ -lincompressibleTransportModels \ -lturbulenceModels \ diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H index 6513b654..50bbb640 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H @@ -1,15 +1,28 @@ - // get scalar source from DEM - particleCloud.forceM(1).manipulateScalarField(Tsource); - Tsource.correctBoundaryConditions(); +// get scalar source from DEM + particleCloud.forceM(1).manipulateScalarField(ETsource); + ETsource.correctBoundaryConditions(); - // solve scalar transport equation + // solve scalar transport equation fvScalarMatrix TEqn ( fvm::ddt(voidfraction,T) - fvm::Sp(fvc::ddt(voidfraction),T) + fvm::div(phi, T) - fvm::Sp(fvc::div(phi),T) - - fvm::laplacian(DT*voidfraction, T) + - fvc::div(kT*voidfraction/(rho*Cp)*fvc::grad(T)) == - Tsource + ETsource/(rho*Cp) ); + + // solve scalar transport equation +/* fvScalarMatrix TEqn + ( + fvm::ddt(voidfraction*rho*Cp,T) + + fvm::div(phi*fvc::interpolate(rho*Cp),T) + - fvc::div(kT*voidfraction*fvc::grad(T)) + == + ETsource + ); +*/ + + TEqn.relax(); - TEqn.solve(); \ No newline at end of file + TEqn.solve(); diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C index 6bcb8e36..321aecf4 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C @@ -17,7 +17,7 @@ License Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria Application - cfdemSolverMultiphase + cfdemSolverMultiphaseScalar Description CFD-DEM solver for n incompressible fluids which captures the interfaces and @@ -100,7 +100,9 @@ int main(int argc, char *argv[]) particleCloud.clockM().start(26,"Flow"); - #include "TEqn.H" + Cp = mixture.Cp(); + kT = mixture.kT(); + #include "TEqn.H" if(particleCloud.solveFlow()) { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H index d1d2371a..a7615a8b 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H @@ -122,11 +122,11 @@ volScalarField T mesh ); -volScalarField Tsource +volScalarField ETsource ( IOobject ( - "Tsource", + "ETsource", runTime.timeName(), mesh, IOobject::MUST_READ, @@ -135,17 +135,30 @@ volScalarField Tsource mesh ); -volScalarField DT +volScalarField Cp ( IOobject ( - "DT", + "Cp", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), - mixture.DT() + mixture.Cp() +); + +volScalarField kT +( + IOobject + ( + "kT", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mixture.kT() ); //======================== diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files index 572171ec..998255e4 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/Make/files @@ -2,4 +2,4 @@ phase/phase.C alphaContactAngle/alphaContactAngleFvPatchScalarField.C multiphaseMixture.C -LIB = $(CFDEM_LIB_DIR)/libcfdemMultiphaseInterFoam +LIB = $(CFDEM_LIB_DIR)/libcfdemMultiphaseInterFoamScalar diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C index ad255511..00584871 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C @@ -368,37 +368,71 @@ Foam::multiphaseMixture::nuf() const } Foam::tmp -Foam::multiphaseMixture::DT() const +Foam::multiphaseMixture::Cp() const { PtrDictionary::const_iterator iter = phases_.begin(); - tmp tDT = iter()*iter().DT(); - volScalarField& DT = tDT.ref(); + tmp tCp = iter()*iter().Cp(); + volScalarField& Cp = tCp.ref(); for (++iter; iter != phases_.end(); ++iter) { - DT += iter()*iter().DT(); + Cp += iter()*iter().Cp(); } - return tDT; + return tCp; } - +/* Foam::tmp -Foam::multiphaseMixture::DT(const label patchi) const +Foam::multiphaseMixture::Cp(const label patchi) const { PtrDictionary::const_iterator iter = phases_.begin(); - tmp tDT = iter().boundaryField()[patchi]*iter().DT().value(); - scalarField& DT = tDT.ref(); + tmp tCp = iter().boundaryField()[patchi]*iter().Cp().value(); + scalarField& Cp = tCp.ref(); for (++iter; iter != phases_.end(); ++iter) { - DT += iter().boundaryField()[patchi]*iter().DT().value(); + Cp += iter().boundaryField()[patchi]*iter().Cp().value(); } - return tDT; + return tCp; } +*/ +Foam::tmp +Foam::multiphaseMixture::kT() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tkT = iter()*iter().kT(); + volScalarField& kT = tkT.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + kT += iter()*iter().kT(); + } + + return tkT; +} + +/* +Foam::tmp +Foam::multiphaseMixture::kT(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tkT = iter().boundaryField()[patchi]*iter().kT().value(); + scalarField& kT = tkT.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + kT += iter().boundaryField()[patchi]*iter().kT().value(); + } + + return tkT; +} +*/ void Foam::multiphaseMixture::solve() { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H index 3b093962..e8b47805 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H @@ -253,11 +253,17 @@ public: //- Return the face-interpolated dynamic laminar viscosity tmp nuf() const; - //- Return the thermal diffusivity - tmp DT() const; + //- Return the heat capacity + tmp Cp() const; - //- Return the therm diffusivity for patch - tmp DT(const label patchi) const; + //- Return the heat capacity for patch + //tmp Cp(const label patchi) const; + + //- Return the thermal conductivity + tmp kT() const; + + //- Return the thermal conductivity for patch + //tmp kT(const label patchi) const; tmp surfaceTensionForce() const { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C index 192b672d..01825435 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C @@ -60,7 +60,8 @@ Foam::phase::phase ) ), rho_("rho", dimDensity, phaseDict_), - DT_("DT", (dimLength*dimLength/dimTime), phaseDict_) + Cp_("Cp", (dimSpecificHeatCapacity), phaseDict_), + kT_("kT", (dimPower/dimLength/dimTemperature), phaseDict_) {} @@ -83,7 +84,8 @@ bool Foam::phase::read(const dictionary& phaseDict) { phaseDict_ = phaseDict; - phaseDict_.lookup("DT") >> DT_; + phaseDict_.lookup("Cp") >> Cp_; + phaseDict_.lookup("kT") >> kT_; if (nuModel_->read(phaseDict_)) { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H index 748c6e2e..290b348e 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H @@ -60,7 +60,8 @@ class phase dictionary phaseDict_; autoPtr nuModel_; dimensionedScalar rho_; - dimensionedScalar DT_; + dimensionedScalar Cp_; + dimensionedScalar kT_; public: @@ -141,10 +142,16 @@ public: return rho_; } - //- Return const-access to phase1 thermal diffusivity - const dimensionedScalar& DT() const + //- Return const-access to phase1 heat capacity + const dimensionedScalar& Cp() const { - return DT_; + return Cp_; + } + + //- Return const-access to phase1 thermal conductivity + const dimensionedScalar& kT() const + { + return kT_; } //- Correct the phase properties diff --git a/etc/solver-list.txt b/etc/solver-list.txt index 52a74b1f..d0eb853b 100644 --- a/etc/solver-list.txt +++ b/etc/solver-list.txt @@ -4,3 +4,4 @@ cfdemSolverRhoPimple/dir cfdemSolverIB/dir cfdemSolverPisoScalar/dir cfdemSolverMultiphase/dir +cfdemSolverMultiphaseScalar/dir From 2c6312325bd4b4929ce37fe0e6ff83cb56ab8815 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 2 Jul 2018 11:07:09 +0200 Subject: [PATCH 11/47] mixing rules --- .../cfdemSolverMultiphaseScalar/TEqn.H | 27 +- .../cfdemSolverMultiphaseScalar.C | 12 +- .../createFields.H | 6 +- .../multiphaseMixture/#multiphaseMixture.C# | 816 ++++++++++++++++++ .../multiphaseMixture/multiphaseMixture.C | 61 +- .../multiphaseMixture/multiphaseMixture.H | 8 +- .../multiphaseMixture/phase/phase.C | 4 +- .../multiphaseMixture/phase/phase.H | 6 +- 8 files changed, 865 insertions(+), 75 deletions(-) create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H index 50bbb640..370e2e26 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H @@ -1,28 +1,33 @@ // get scalar source from DEM - particleCloud.forceM(1).manipulateScalarField(ETsource); - ETsource.correctBoundaryConditions(); +particleCloud.energyContributions(ETsource); +//particleCloud.energyCoefficients(ETcoeff); + // solve scalar transport equation fvScalarMatrix TEqn ( - fvm::ddt(voidfraction,T) - fvm::Sp(fvc::ddt(voidfraction),T) + fvm::ddt(voidfraction,T) - fvm::Sp(fvc::ddt(voidfraction),T) + fvm::div(phi, T) - fvm::Sp(fvc::div(phi),T) - - fvc::div(kT*voidfraction/(rho*Cp)*fvc::grad(T)) + - fvc::div(kf*voidfraction/(rho*Cp)*fvc::grad(T)) == ETsource/(rho*Cp) ); - // solve scalar transport equation -/* fvScalarMatrix TEqn +/* + fvScalarMatrix TEqn ( - fvm::ddt(voidfraction*rho*Cp,T) - + fvm::div(phi*fvc::interpolate(rho*Cp),T) - - fvc::div(kT*voidfraction*fvc::grad(T)) + fvm::ddt(voidfraction*rho*Cp,T) + + fvm::div(phi*fvc::interpolate(rho*Cp),T) + - fvc::div(kf*voidfraction*fvc::grad(T)) == - ETsource + ETsource //+ fvm::Sp(ETcoeff,T) ); */ - TEqn.relax(); + fvOptions.constrain(TEqn); TEqn.solve(); + + particleCloud.clockM().start(31,"postFlow"); + particleCloud.postFlow(); + particleCloud.clockM().stop("postFlow"); diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C index 321aecf4..dc076734 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C @@ -36,7 +36,7 @@ Description #include "fvOptions.H" #include "CorrectPhi.H" -#include "cfdemCloud.H" +#include "cfdemCloudEnergy.H" #include "implicitCouple.H" #include "clockModel.H" #include "smoothingModel.H" @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) turbulence->validate(); // create cfdemCloud - cfdemCloud particleCloud(mesh); + cfdemCloudEnergy particleCloud(mesh); #include "additionalChecks.H" @@ -100,10 +100,6 @@ int main(int argc, char *argv[]) particleCloud.clockM().start(26,"Flow"); - Cp = mixture.Cp(); - kT = mixture.kT(); - #include "TEqn.H" - if(particleCloud.solveFlow()) { mixture.solve(); @@ -132,6 +128,10 @@ int main(int argc, char *argv[]) Info << "skipping flow solution." << endl; } + Cp = mixture.Cp(); + kf = mixture.kf(); + #include "TEqn.H" + runTime.write(); Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H index a7615a8b..34598585 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H @@ -148,17 +148,17 @@ volScalarField Cp mixture.Cp() ); -volScalarField kT +volScalarField kf ( IOobject ( - "kT", + "kf", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), - mixture.kT() + mixture.kf() ); //======================== diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# new file mode 100644 index 00000000..2b2e645f --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# @@ -0,0 +1,816 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "multiphaseMixture.H" +#include "alphaContactAngleFvPatchScalarField.H" +#include "Time.H" +#include "subCycle.H" +#include "MULES.H" +#include "surfaceInterpolate.H" +#include "fvcGrad.H" +#include "fvcSnGrad.H" +#include "fvcDiv.H" +#include "fvcFlux.H" + +// * * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * // + +const Foam::scalar Foam::multiphaseMixture::convertToRad = + Foam::constant::mathematical::pi/180.0; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::multiphaseMixture::calcAlphas() +{ + scalar level = 0.0; + alphas_ == 0.0; + + forAllIter(PtrDictionary, phases_, iter) + { + alphas_ += level*iter(); + level += 1.0; + } +} + + +Foam::tmp +Foam::multiphaseMixture::calcNu() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnu = iter()*iter().nu(); + volScalarField& nu = tnu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nu += iter()*iter().nu(); + } + + return tnu; +} + +Foam::tmp +Foam::multiphaseMixture::calcStf() const +{ + tmp tstf + ( + new surfaceScalarField + ( + IOobject + ( + "stf", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar + ( + "stf", + dimensionSet(1, -2, -2, 0, 0), + 0.0 + ) + ) + ); + + surfaceScalarField& stf = tstf.ref(); + + forAllConstIter(PtrDictionary, phases_, iter1) + { + const phase& alpha1 = iter1(); + + PtrDictionary::const_iterator iter2 = iter1; + ++iter2; + + for (; iter2 != phases_.end(); ++iter2) + { + const phase& alpha2 = iter2(); + + sigmaTable::const_iterator sigma = + sigmas_.find(interfacePair(alpha1, alpha2)); + + if (sigma == sigmas_.end()) + { + FatalErrorInFunction + << "Cannot find interface " << interfacePair(alpha1, alpha2) + << " in list of sigma values" + << exit(FatalError); + } + + stf += dimensionedScalar("sigma", dimSigma_, sigma()) + *fvc::interpolate(K(alpha1, alpha2))* + ( + fvc::interpolate(alpha2)*fvc::snGrad(alpha1) + - fvc::interpolate(alpha1)*fvc::snGrad(alpha2) + ); + } + } + + return tstf; +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::multiphaseMixture::multiphaseMixture +( + const volVectorField& U, + const surfaceScalarField& phi, + const volScalarField& voidfraction +) +: + IOdictionary + ( + IOobject + ( + "transportProperties", + U.time().constant(), + U.db(), + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ), + + phases_(lookup("phases"), phase::iNew(U, phi)), + + mesh_(U.mesh()), + U_(U), + phi_(phi), + voidfraction_(voidfraction), + rhoPhi_ + ( + IOobject + ( + "rhoPhi", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh_, + dimensionedScalar("rhoPhi", dimMass/dimTime, 0.0) + ), + surfaceTensionForce_ + ( + IOobject + ( + "surfaceTensionForce", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh_, + dimensionedScalar("surfaceTensionForce", dimensionSet(1, -2, -2, 0, 0), 0.0) + ), + alphas_ + ( + IOobject + ( + "alphas", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh_, + dimensionedScalar("alphas", dimless, 0.0) + ), + + nu_ + ( + IOobject + ( + "nu", + mesh_.time().timeName(), + mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + calcNu() + ), + + sigmas_(lookup("sigmas")), + dimSigma_(1, 0, -2, 0, 0), + deltaN_ + ( + "deltaN", + 1e-8/pow(average(mesh_.V()), 1.0/3.0) + ) +{ + calcAlphas(); + alphas_.write(); + surfaceTensionForce_ = calcStf(); + +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::tmp +Foam::multiphaseMixture::rho() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp trho = iter()*iter().rho(); + volScalarField& rho = trho.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rho += iter()*iter().rho(); + } + + return trho; +} + + +Foam::tmp +Foam::multiphaseMixture::rho(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp trho = iter().boundaryField()[patchi]*iter().rho().value(); + scalarField& rho = trho.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rho += iter().boundaryField()[patchi]*iter().rho().value(); + } + + return trho; +} + + +Foam::tmp +Foam::multiphaseMixture::mu() const +{ + Info << "In multiphasemixture mu()" << endl; + return rho()*nu(); +// PtrDictionary::const_iterator iter = phases_.begin(); + +// tmp tmu = iter()*iter().rho()*iter().nu(); +// volScalarField& mu = tmu.ref(); + +// for (++iter; iter != phases_.end(); ++iter) +// { +// mu += iter()*iter().rho()*iter().nu(); +// } + +// return tmu; +} + + +Foam::tmp +Foam::multiphaseMixture::mu(const label patchi) const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tmu = + iter().boundaryField()[patchi] + *iter().rho().value() + *iter().nu(patchi); + scalarField& mu = tmu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + mu += + iter().boundaryField()[patchi] + *iter().rho().value() + *iter().nu(patchi); + } + + return tmu; +} + + +Foam::tmp +Foam::multiphaseMixture::muf() const +{ + + return nuf()*fvc::interpolate(rho()); +// PtrDictionary::const_iterator iter = phases_.begin(); + +// tmp tmuf = +// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); +// surfaceScalarField& muf = tmuf.ref(); + +// for (++iter; iter != phases_.end(); ++iter) +// { +// muf += +// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); +// } + +// return tmuf; +} + + +Foam::tmp +Foam::multiphaseMixture::nu() const +{ + return nu_; +} + +Foam::tmp +Foam::multiphaseMixture::nu(const label patchi) const +{ + //return nu_.boundaryField()[patchi]; + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnu = + iter().boundaryField()[patchi] + *iter().nu(patchi); + scalarField& nu = tnu.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nu += + iter().boundaryField()[patchi] + *iter().nu(patchi); + } + + return tnu; +} + + +Foam::tmp +Foam::multiphaseMixture::nuf() const +{ + //return muf()/fvc::interpolate(rho()); + PtrDictionary::const_iterator iter = phases_.begin(); + + tmp tnuf = + fvc::interpolate(iter())*fvc::interpolate(iter().nu()); + surfaceScalarField& nuf = tnuf.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + nuf += + fvc::interpolate(iter())*fvc::interpolate(iter().nu()); + } + + return tnuf; +} + +Foam::tmp +Foam::multiphaseMixture::Cp() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + // rho*Cp + tmp trhoCp = iter()*iter().Cp()*iter().rho(); + volScalarField& rhoCp = trhoCp.ref(); + + // Cp + tmp tCp = iter()*iter().Cp(); + volScalarField& Cp = tCp.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rhoCp += iter()*iter().Cp()*iter().rho(); + } + Cp = rhoCp/rho(); + return tCp; +} + +Foam::tmp +Foam::multiphaseMixture::kf() const +{ + PtrDictionary::const_iterator iter = phases_.begin(); + + // rho*Cp/kf + tmp trhoCpkf = iter()*iter().rho()*iter().Cp()/iter().kf(); + volScalarField& rhoCpkf = trhoCpkf.ref(); + + // kf + tmp tkf = iter()*iter().kf(); + volScalarField& kf = tkf.ref(); + + for (++iter; iter != phases_.end(); ++iter) + { + rhoCpkf += iter()*iter().rho()*iter().Cp()/iter().kf(); + } + + kf = rho()*Cp()/rhoCpkf; + return tkf; +} + +void Foam::multiphaseMixture::solve() +{ + correct(); + + const Time& runTime = mesh_.time(); + + volScalarField& alpha = phases_.first(); + + const dictionary& alphaControls = mesh_.solverDict("alpha"); + label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles"))); + scalar cAlpha(readScalar(alphaControls.lookup("cAlpha"))); + + if (nAlphaSubCycles > 1) + { + surfaceScalarField rhoPhiSum + ( + IOobject + ( + "rhoPhiSum", + runTime.timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("0", rhoPhi_.dimensions(), 0) + ); + + dimensionedScalar totalDeltaT = runTime.deltaT(); + + for + ( + subCycle alphaSubCycle(alpha, nAlphaSubCycles); + !(++alphaSubCycle).end(); + ) + { + FatalError << "Sub-cycling of the alpha equation not yet implemented!!" << abort(FatalError); + solveAlphas(cAlpha); + rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi_; + } + + rhoPhi_ = rhoPhiSum; + } + else + { + solveAlphas(cAlpha); + } + + // Update the mixture kinematic viscosity + nu_ = calcNu(); + + surfaceTensionForce_ = calcStf(); +} + + +void Foam::multiphaseMixture::correct() +{ + forAllIter(PtrDictionary, phases_, iter) + { + iter().correct(); + } +} + + +Foam::tmp Foam::multiphaseMixture::nHatfv +( + const volScalarField& alpha1, + const volScalarField& alpha2 +) const +{ + /* + // Cell gradient of alpha + volVectorField gradAlpha = + alpha2*fvc::grad(alpha1) - alpha1*fvc::grad(alpha2); + + // Interpolated face-gradient of alpha + surfaceVectorField gradAlphaf = fvc::interpolate(gradAlpha); + */ + + surfaceVectorField gradAlphaf + ( + fvc::interpolate(alpha2)*fvc::interpolate(fvc::grad(alpha1)) + - fvc::interpolate(alpha1)*fvc::interpolate(fvc::grad(alpha2)) + ); + + // Face unit interface normal + return gradAlphaf/(mag(gradAlphaf) + deltaN_); +} + + +Foam::tmp Foam::multiphaseMixture::nHatf +( + const volScalarField& alpha1, + const volScalarField& alpha2 +) const +{ + // Face unit interface normal flux + return nHatfv(alpha1, alpha2) & mesh_.Sf(); +} + + +// Correction for the boundary condition on the unit normal nHat on +// walls to produce the correct contact angle. + +// The dynamic contact angle is calculated from the component of the +// velocity on the direction of the interface, parallel to the wall. + +void Foam::multiphaseMixture::correctContactAngle +( + const phase& alpha1, + const phase& alpha2, + surfaceVectorField::Boundary& nHatb +) const +{ + const volScalarField::Boundary& gbf + = alpha1.boundaryField(); + + const fvBoundaryMesh& boundary = mesh_.boundary(); + + forAll(boundary, patchi) + { + if (isA(gbf[patchi])) + { + const alphaContactAngleFvPatchScalarField& acap = + refCast(gbf[patchi]); + + vectorField& nHatPatch = nHatb[patchi]; + + vectorField AfHatPatch + ( + mesh_.Sf().boundaryField()[patchi] + /mesh_.magSf().boundaryField()[patchi] + ); + + alphaContactAngleFvPatchScalarField::thetaPropsTable:: + const_iterator tp = + acap.thetaProps().find(interfacePair(alpha1, alpha2)); + + if (tp == acap.thetaProps().end()) + { + FatalErrorInFunction + << "Cannot find interface " << interfacePair(alpha1, alpha2) + << "\n in table of theta properties for patch " + << acap.patch().name() + << exit(FatalError); + } + + bool matched = (tp.key().first() == alpha1.name()); + + scalar theta0 = convertToRad*tp().theta0(matched); + scalarField theta(boundary[patchi].size(), theta0); + + scalar uTheta = tp().uTheta(); + + // Calculate the dynamic contact angle if required + if (uTheta > SMALL) + { + scalar thetaA = convertToRad*tp().thetaA(matched); + scalar thetaR = convertToRad*tp().thetaR(matched); + + // Calculated the component of the velocity parallel to the wall + vectorField Uwall + ( + U_.boundaryField()[patchi].patchInternalField() + - U_.boundaryField()[patchi] + ); + Uwall -= (AfHatPatch & Uwall)*AfHatPatch; + + // Find the direction of the interface parallel to the wall + vectorField nWall + ( + nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch + ); + + // Normalise nWall + nWall /= (mag(nWall) + SMALL); + + // Calculate Uwall resolved normal to the interface parallel to + // the interface + scalarField uwall(nWall & Uwall); + + theta += (thetaA - thetaR)*tanh(uwall/uTheta); + } + + + // Reset nHatPatch to correspond to the contact angle + + scalarField a12(nHatPatch & AfHatPatch); + + scalarField b1(cos(theta)); + + scalarField b2(nHatPatch.size()); + + forAll(b2, facei) + { + b2[facei] = cos(acos(a12[facei]) - theta[facei]); + } + + scalarField det(1.0 - a12*a12); + + scalarField a((b1 - a12*b2)/det); + scalarField b((b2 - a12*b1)/det); + + nHatPatch = a*AfHatPatch + b*nHatPatch; + + nHatPatch /= (mag(nHatPatch) + deltaN_.value()); + } + } +} + + +Foam::tmp Foam::multiphaseMixture::K +( + const phase& alpha1, + const phase& alpha2 +) const +{ + tmp tnHatfv = nHatfv(alpha1, alpha2); + + correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef()); + + // Simple expression for curvature + return -fvc::div(tnHatfv & mesh_.Sf()); +} + + +Foam::tmp +Foam::multiphaseMixture::nearInterface() const +{ + tmp tnearInt + ( + new volScalarField + ( + IOobject + ( + "nearInterface", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("nearInterface", dimless, 0.0) + ) + ); + + forAllConstIter(PtrDictionary, phases_, iter) + { + tnearInt.ref() = max(tnearInt(), pos(iter() - 0.01)*pos(0.99 - iter())); + } + + return tnearInt; +} + + +void Foam::multiphaseMixture::solveAlphas +( + const scalar cAlpha +) +{ + static label nSolves=-1; + nSolves++; + + word alphaScheme("div(phi,alpha)"); + word alpharScheme("div(phirb,alpha)"); + + surfaceScalarField phic(mag(phi_/mesh_.magSf())); + phic = min(cAlpha*phic, max(phic)); + + PtrList alphaPhiCorrs(phases_.size()); + int phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + phase& alpha = iter(); + + alphaPhiCorrs.set + ( + phasei, + new surfaceScalarField + ( + "phi" + alpha.name() + "Corr", + fvc::flux + ( + phi_, + alpha, + alphaScheme + ) + ) + ); + + surfaceScalarField& alphaPhiCorr = alphaPhiCorrs[phasei]; + + forAllIter(PtrDictionary, phases_, iter2) + { + phase& alpha2 = iter2(); + + if (&alpha2 == &alpha) continue; + + surfaceScalarField phir(phic*nHatf(alpha, alpha2)); + + alphaPhiCorr += fvc::flux + ( + -fvc::flux(-phir, alpha2, alpharScheme), + alpha, + alpharScheme + ); + } + + MULES::limit + ( + 1.0/mesh_.time().deltaT().value(), + voidfraction_, + alpha, + phi_, + alphaPhiCorr, + zeroField(), + zeroField(), + 1, + 0, + true + ); + + phasei++; + } + + MULES::limitSum(alphaPhiCorrs); + + rhoPhi_ = dimensionedScalar("0", dimensionSet(1, 0, -1, 0, 0), 0); + + volScalarField sumAlpha + ( + IOobject + ( + "sumAlpha", + mesh_.time().timeName(), + mesh_ + ), + mesh_, + dimensionedScalar("sumAlpha", dimless, 0) + ); + + phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + phase& alpha = iter(); + + surfaceScalarField& alphaPhi = alphaPhiCorrs[phasei]; + alphaPhi += upwind(mesh_, phi_).flux(alpha); + + MULES::explicitSolve + ( + voidfraction_, + alpha, + alphaPhi, + zeroField(), + zeroField() + ); + + rhoPhi_ += alphaPhi*alpha.rho(); + + Info<< alpha.name() << " volume fraction, min, max = " + << alpha.weightedAverage(mesh_.V()).value() + << ' ' << min(alpha).value() + << ' ' << max(alpha).value() + << endl; + + sumAlpha += alpha; + + phasei++; + } + + Info<< "Phase-sum volume fraction, min, max = " + << sumAlpha.weightedAverage(mesh_.V()).value() + << ' ' << min(sumAlpha).value() + << ' ' << max(sumAlpha).value() + << endl; + + calcAlphas(); +} + + +bool Foam::multiphaseMixture::read() +{ + if (transportModel::read()) + { + bool readOK = true; + + PtrList phaseData(lookup("phases")); + label phasei = 0; + + forAllIter(PtrDictionary, phases_, iter) + { + readOK &= iter().read(phaseData[phasei++].dict()); + } + + lookup("sigmas") >> sigmas_; + + return readOK; + } + else + { + return false; + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C index 00584871..2b2e645f 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C @@ -325,7 +325,6 @@ Foam::multiphaseMixture::nu() const return nu_; } - Foam::tmp Foam::multiphaseMixture::nu(const label patchi) const { @@ -372,68 +371,44 @@ Foam::multiphaseMixture::Cp() const { PtrDictionary::const_iterator iter = phases_.begin(); + // rho*Cp + tmp trhoCp = iter()*iter().Cp()*iter().rho(); + volScalarField& rhoCp = trhoCp.ref(); + + // Cp tmp tCp = iter()*iter().Cp(); volScalarField& Cp = tCp.ref(); for (++iter; iter != phases_.end(); ++iter) { - Cp += iter()*iter().Cp(); + rhoCp += iter()*iter().Cp()*iter().rho(); } - + Cp = rhoCp/rho(); return tCp; } -/* -Foam::tmp -Foam::multiphaseMixture::Cp(const label patchi) const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tCp = iter().boundaryField()[patchi]*iter().Cp().value(); - scalarField& Cp = tCp.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - Cp += iter().boundaryField()[patchi]*iter().Cp().value(); - } - - return tCp; -} -*/ Foam::tmp -Foam::multiphaseMixture::kT() const +Foam::multiphaseMixture::kf() const { PtrDictionary::const_iterator iter = phases_.begin(); - tmp tkT = iter()*iter().kT(); - volScalarField& kT = tkT.ref(); + // rho*Cp/kf + tmp trhoCpkf = iter()*iter().rho()*iter().Cp()/iter().kf(); + volScalarField& rhoCpkf = trhoCpkf.ref(); + + // kf + tmp tkf = iter()*iter().kf(); + volScalarField& kf = tkf.ref(); for (++iter; iter != phases_.end(); ++iter) { - kT += iter()*iter().kT(); + rhoCpkf += iter()*iter().rho()*iter().Cp()/iter().kf(); } - return tkT; + kf = rho()*Cp()/rhoCpkf; + return tkf; } -/* -Foam::tmp -Foam::multiphaseMixture::kT(const label patchi) const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tkT = iter().boundaryField()[patchi]*iter().kT().value(); - scalarField& kT = tkT.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - kT += iter().boundaryField()[patchi]*iter().kT().value(); - } - - return tkT; -} -*/ - void Foam::multiphaseMixture::solve() { correct(); diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H index e8b47805..c7334d4a 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.H @@ -256,14 +256,8 @@ public: //- Return the heat capacity tmp Cp() const; - //- Return the heat capacity for patch - //tmp Cp(const label patchi) const; - //- Return the thermal conductivity - tmp kT() const; - - //- Return the thermal conductivity for patch - //tmp kT(const label patchi) const; + tmp kf() const; tmp surfaceTensionForce() const { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C index 01825435..5b0d90ec 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.C @@ -61,7 +61,7 @@ Foam::phase::phase ), rho_("rho", dimDensity, phaseDict_), Cp_("Cp", (dimSpecificHeatCapacity), phaseDict_), - kT_("kT", (dimPower/dimLength/dimTemperature), phaseDict_) + kf_("kf", (dimPower/dimLength/dimTemperature), phaseDict_) {} @@ -85,7 +85,7 @@ bool Foam::phase::read(const dictionary& phaseDict) phaseDict_ = phaseDict; phaseDict_.lookup("Cp") >> Cp_; - phaseDict_.lookup("kT") >> kT_; + phaseDict_.lookup("kf") >> kf_; if (nuModel_->read(phaseDict_)) { diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H index 290b348e..e61f63c9 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/phase/phase.H @@ -61,7 +61,7 @@ class phase autoPtr nuModel_; dimensionedScalar rho_; dimensionedScalar Cp_; - dimensionedScalar kT_; + dimensionedScalar kf_; public: @@ -149,9 +149,9 @@ public: } //- Return const-access to phase1 thermal conductivity - const dimensionedScalar& kT() const + const dimensionedScalar& kf() const { - return kT_; + return kf_; } //- Correct the phase properties From 7dcb0fee45e8289992866fcbb1321581281d9961 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:17:31 +0200 Subject: [PATCH 12/47] virtual mass force optimization (minor) --- .../subModels/forceModel/virtualMassForce/virtualMassForce.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 35d2b498..0f1db4c9 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -114,7 +114,6 @@ virtualMassForce::virtualMassForce Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; Info << "WARNING: ignoring user-set Cadd \n"; - bool getParticleDensities_ = dict.lookupOrDefault("getParticleDensities",false); if(!dict.lookupOrDefault("getParticleDensities",false)) FatalError << "Virtual mass model: useFelderhof=true requires getParticleDensities=true in couplingProperties" << abort(FatalError); } @@ -144,7 +143,8 @@ virtualMassForce::~virtualMassForce() void virtualMassForce::setForce() const { - reAllocArrays(); + if (!useUs_ || !splitUrelCalculation_ ) + reAllocArrays(); scalar dt = U_.mesh().time().deltaT().value(); From da25c871c542806df3fe2334375db2e3f1db98c6 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:25:26 +0200 Subject: [PATCH 13/47] Solver improvement, made Gunn and Syamlal models compatible with multiphase --- .../cfdemSolverMultiphaseScalar/EEqn.H | 26 ++++++++++++ .../cfdemSolverMultiphaseScalar/TEqn.H | 33 --------------- .../cfdemSolverMultiphaseScalar.C | 10 +++-- .../createFields.H | 42 ++++++++++++++++--- .../heatTransferGunn/heatTransferGunn.C | 14 ++++++- .../heatTransferGunn/heatTransferGunn.H | 10 +++++ .../SyamlalThermCond/SyamlalThermCond.C | 17 ++++++-- .../SyamlalThermCond/SyamlalThermCond.H | 10 +++++ .../thermCondModel/noTherm/noThermCond.C | 2 +- 9 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/EEqn.H delete mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/EEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/EEqn.H new file mode 100644 index 00000000..b9392817 --- /dev/null +++ b/applications/solvers/cfdemSolverMultiphaseScalar/EEqn.H @@ -0,0 +1,26 @@ + // get mixture properties + Cp = mixture.Cp(); + kf = mixture.kf(); + keff=particleCloud.thermCondM().thermCond(); + + // get scalar source from DEM + particleCloud.energyContributions(Qsource); + particleCloud.energyCoefficients(QCoeff); + + fvScalarMatrix EEqn + ( + rho*Cp*(fvm::ddt(voidfraction,T) + + fvm::div(phi,T)) + - fvc::div(keff*voidfraction*fvc::grad(T)) + == + Qsource + fvm::Sp(QCoeff,T) + ); + + + EEqn.relax(); + fvOptions.constrain(EEqn); + EEqn.solve(); + + particleCloud.clockM().start(31,"postFlow"); + particleCloud.postFlow(); + particleCloud.clockM().stop("postFlow"); diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H b/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H deleted file mode 100644 index 370e2e26..00000000 --- a/applications/solvers/cfdemSolverMultiphaseScalar/TEqn.H +++ /dev/null @@ -1,33 +0,0 @@ -// get scalar source from DEM -particleCloud.energyContributions(ETsource); -//particleCloud.energyCoefficients(ETcoeff); - - - // solve scalar transport equation - fvScalarMatrix TEqn - ( - fvm::ddt(voidfraction,T) - fvm::Sp(fvc::ddt(voidfraction),T) - + fvm::div(phi, T) - fvm::Sp(fvc::div(phi),T) - - fvc::div(kf*voidfraction/(rho*Cp)*fvc::grad(T)) - == - ETsource/(rho*Cp) - ); - -/* - fvScalarMatrix TEqn - ( - fvm::ddt(voidfraction*rho*Cp,T) - + fvm::div(phi*fvc::interpolate(rho*Cp),T) - - fvc::div(kf*voidfraction*fvc::grad(T)) - == - ETsource //+ fvm::Sp(ETcoeff,T) - ); -*/ - - TEqn.relax(); - fvOptions.constrain(TEqn); - TEqn.solve(); - - particleCloud.clockM().start(31,"postFlow"); - particleCloud.postFlow(); - particleCloud.clockM().stop("postFlow"); diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C index dc076734..0174eeee 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/cfdemSolverMultiphaseScalar.C @@ -41,6 +41,10 @@ Description #include "clockModel.H" #include "smoothingModel.H" #include "forceModel.H" +#include "thermCondModel.H" +#include "energyModel.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) @@ -105,6 +109,8 @@ int main(int argc, char *argv[]) mixture.solve(); rho = mixture.rho(); rhoEps = rho * voidfraction; + + #include "EEqn.H" // --- Pressure-velocity PIMPLE corrector loop while (pimple.loop()) @@ -128,10 +134,6 @@ int main(int argc, char *argv[]) Info << "skipping flow solution." << endl; } - Cp = mixture.Cp(); - kf = mixture.kf(); - #include "TEqn.H" - runTime.write(); Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H index 34598585..9a7d6281 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H +++ b/applications/solvers/cfdemSolverMultiphaseScalar/createFields.H @@ -122,17 +122,32 @@ volScalarField T mesh ); -volScalarField ETsource +volScalarField Qsource ( IOobject ( - "ETsource", + "Qsource", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::NO_READ, IOobject::AUTO_WRITE ), - mesh + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) +); + +volScalarField QCoeff +( + IOobject + ( + "Qsource", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) ); volScalarField Cp @@ -142,7 +157,7 @@ volScalarField Cp "Cp", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), mixture.Cp() @@ -155,12 +170,27 @@ volScalarField kf "kf", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), mixture.kf() ); +volScalarField keff +( + IOobject + ( + "keff", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0) +); + + //======================== volScalarField rhoEps ("rhoEps", rho * voidfraction); diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C index 69175e97..fcc677ea 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C @@ -122,7 +122,12 @@ heatTransferGunn::heatTransferGunn partHeatFluxName_(propsDict_.lookup("partHeatFluxName")), partHeatFlux_(NULL), partRe_(NULL), - partNu_(NULL) + partNu_(NULL), + multiphase_(propsDict_.lookupOrDefault("multiphase",false)), + kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + kfField_(sm.mesh().lookupObject (kfFieldName_)), + CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + CpField_(sm.mesh().lookupObject (CpFieldName_)) { allocateMyArrays(); @@ -260,6 +265,13 @@ void heatTransferGunn::calcEnergyContribution() magUr = mag(Ufluid - Us); ds = 2.*particleCloud_.radius(index); muf = mufField[cellI]; + + if(multiphase_) + { + kf0_ = kfField_[cellI]; + Cp_ = CpField_[cellI]; + } + Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; Pr = max(SMALL, Cp_ * muf / kf0_); diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H index 4862e5ed..9c7b8416 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H @@ -95,6 +95,16 @@ protected: mutable double **partNu_; + bool multiphase_; + + word kfFieldName_; + + const volScalarField& kfField_; + + word CpFieldName_; + + const volScalarField& CpField_; + void allocateMyArrays() const; scalar Nusselt(scalar, scalar, scalar) const; diff --git a/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.C b/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.C index c0d450d2..b02f52ae 100644 --- a/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.C +++ b/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.C @@ -67,7 +67,12 @@ SyamlalThermCond::SyamlalThermCond sm.mesh(), dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 1.0) ), - hasWallQFactor_(false) + hasWallQFactor_(false), + multiphase_(propsDict_.lookupOrDefault("multiphase",false)), + kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + kfField_(sm.mesh().lookupObject (kfFieldName_)), + CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + CpField_(sm.mesh().lookupObject (CpFieldName_)) { if (wallQFactor_.headerOk()) { @@ -106,7 +111,10 @@ tmp SyamlalThermCond::thermCond() const volScalarField& svf = tvf.ref(); - svf = (1-sqrt(1-voidfraction_+SMALL)) / (voidfraction_) * kf0_; + if (multiphase_) + svf = (1-sqrt(1-voidfraction_+SMALL)) / (voidfraction_) * kfField_; + else + svf = (1-sqrt(1-voidfraction_+SMALL)) / (voidfraction_) * kf0_; // if a wallQFactor field is present, use it to scale heat transport through a patch if (hasWallQFactor_) @@ -121,7 +129,10 @@ tmp SyamlalThermCond::thermCond() const tmp SyamlalThermCond::thermDiff() const { - return thermCond()/(rho_*Cp_); + if (multiphase_) + return thermCond()/(rho_*CpField_); + else + return thermCond()/(rho_*Cp_); } diff --git a/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.H b/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.H index ae1c4c28..95426099 100644 --- a/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.H +++ b/src/lagrangian/cfdemParticle/subModels/thermCondModel/SyamlalThermCond/SyamlalThermCond.H @@ -68,6 +68,16 @@ private: bool hasWallQFactor_; + bool multiphase_; + + word kfFieldName_; + + const volScalarField& kfField_; + + word CpFieldName_; + + const volScalarField& CpField_; + public: //- Runtime type information diff --git a/src/lagrangian/cfdemParticle/subModels/thermCondModel/noTherm/noThermCond.C b/src/lagrangian/cfdemParticle/subModels/thermCondModel/noTherm/noThermCond.C index bc666c96..35921de7 100644 --- a/src/lagrangian/cfdemParticle/subModels/thermCondModel/noTherm/noThermCond.C +++ b/src/lagrangian/cfdemParticle/subModels/thermCondModel/noTherm/noThermCond.C @@ -71,7 +71,7 @@ tmp noThermCond::thermCond() const dimensionedScalar ( "zero", - dimensionSet(0,2,-1,0,0,0,0), + dimensionSet(1,1,-3,-1,0,0,0), 0.0 ) ) From ba9f4964c4a1385b6442e1a8f71097184a92e557 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:27:41 +0200 Subject: [PATCH 14/47] Virtual mass model optimization (minor) --- .../subModels/forceModel/virtualMassForce/virtualMassForce.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 35d2b498..0f1db4c9 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -114,7 +114,6 @@ virtualMassForce::virtualMassForce Info << "Virtual mass model: using Cadd correlation by Felderhof \n"; Info << "WARNING: ignoring user-set Cadd \n"; - bool getParticleDensities_ = dict.lookupOrDefault("getParticleDensities",false); if(!dict.lookupOrDefault("getParticleDensities",false)) FatalError << "Virtual mass model: useFelderhof=true requires getParticleDensities=true in couplingProperties" << abort(FatalError); } @@ -144,7 +143,8 @@ virtualMassForce::~virtualMassForce() void virtualMassForce::setForce() const { - reAllocArrays(); + if (!useUs_ || !splitUrelCalculation_ ) + reAllocArrays(); scalar dt = U_.mesh().time().deltaT().value(); From 97949216e7cc1ddaf549ffd05fcba7debcf4c7c9 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:31:18 +0200 Subject: [PATCH 15/47] reverted timeStepFraction check to warning --- src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index 7158bcfc..be323366 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -629,9 +629,9 @@ bool cfdemCloud::evolve // IMPLICIT FORCE CONTRIBUTION AND SOLVER USE EXACTLY THE SAME AVERAGED // QUANTITIES AT THE GRID! Info << "\n timeStepFraction() = " << dataExchangeM().timeStepFraction() << endl; - if(dataExchangeM().timeStepFraction() > 1.001) + if(dataExchangeM().timeStepFraction() > 1.0000001) { - FatalError << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); + Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); } clockM().start(24,"interpolateEulerFields"); From 65921d48f3fc60a8360a452f70471e640036628d Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:32:34 +0200 Subject: [PATCH 16/47] reverted timeStepFraction check to warning --- src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index 7158bcfc..be323366 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -629,9 +629,9 @@ bool cfdemCloud::evolve // IMPLICIT FORCE CONTRIBUTION AND SOLVER USE EXACTLY THE SAME AVERAGED // QUANTITIES AT THE GRID! Info << "\n timeStepFraction() = " << dataExchangeM().timeStepFraction() << endl; - if(dataExchangeM().timeStepFraction() > 1.001) + if(dataExchangeM().timeStepFraction() > 1.0000001) { - FatalError << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); + Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); } clockM().start(24,"interpolateEulerFields"); From 77511e50b95955ea0ae47c45eed693ff71c04318 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:36:07 +0200 Subject: [PATCH 17/47] Forgot to remove abort --- src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index be323366..c82533b8 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -631,7 +631,7 @@ bool cfdemCloud::evolve Info << "\n timeStepFraction() = " << dataExchangeM().timeStepFraction() << endl; if(dataExchangeM().timeStepFraction() > 1.0000001) { - Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); + Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << endl; } clockM().start(24,"interpolateEulerFields"); From 0778651870cf942144ee20bcb17868cf119990ee Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 13 Aug 2018 16:37:09 +0200 Subject: [PATCH 18/47] Forgot to remove abort --- src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index be323366..c82533b8 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -631,7 +631,7 @@ bool cfdemCloud::evolve Info << "\n timeStepFraction() = " << dataExchangeM().timeStepFraction() << endl; if(dataExchangeM().timeStepFraction() > 1.0000001) { - Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); + Warning << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << endl; } clockM().start(24,"interpolateEulerFields"); From 1b4df091599482c60f12176eefe68643ea35c619 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 16 Jan 2019 10:06:20 +0100 Subject: [PATCH 19/47] added ParmarBassetForce and constDiffAndTemporalSmoothing --- src/lagrangian/cfdemParticle/Make/files | 2 + .../subModels/forceModel/MeiLift/MeiLift.C | 4 +- .../ParmarBassetForce/ParmarBassetForce.C | 556 ++++++++++++++++++ .../ParmarBassetForce/ParmarBassetForce.H | 155 +++++ .../constDiffAndTemporalSmoothing.C | 265 +++++++++ .../constDiffAndTemporalSmoothing.H | 114 ++++ src/lagrangian/cfdemParticleComp/Make/files | 1 + 7 files changed, 1095 insertions(+), 2 deletions(-) create mode 100644 src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C create mode 100644 src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.H create mode 100644 src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.C create mode 100644 src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.H diff --git a/src/lagrangian/cfdemParticle/Make/files b/src/lagrangian/cfdemParticle/Make/files index 58ae9abe..16b761c9 100644 --- a/src/lagrangian/cfdemParticle/Make/files +++ b/src/lagrangian/cfdemParticle/Make/files @@ -56,6 +56,7 @@ $(forceModels)/KochHillDrag/KochHillDrag.C $(forceModels)/KochHillRWDrag/KochHillRWDrag.C $(forceModels)/LaEuScalarTemp/LaEuScalarTemp.C $(forceModels)/virtualMassForce/virtualMassForce.C +$(forceModels)/ParmarBassetForce/ParmarBassetForce.C $(forceModels)/gradPForce/gradPForce.C $(forceModels)/viscForce/viscForce.C $(forceModels)/MeiLift/MeiLift.C @@ -166,5 +167,6 @@ $(smoothingModels)/smoothingModel/newSmoothingModel.C $(smoothingModels)/noSmoothing/noSmoothing.C $(smoothingModels)/constDiffSmoothing/constDiffSmoothing.C $(smoothingModels)/temporalSmoothing/temporalSmoothing.C +$(smoothingModels)/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.C LIB = $(CFDEM_LIB_DIR)/lib$(CFDEM_LIB_NAME) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C index 31c59592..7c6ccd53 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C @@ -121,13 +121,13 @@ MeiLift::MeiLift particleCloud_.probeM().vectorFields_.append("liftForce"); //first entry must the be the force particleCloud_.probeM().vectorFields_.append("Urel"); //other are debug particleCloud_.probeM().vectorFields_.append("vorticity"); - particleCloud_.probeM().vectorFields_.append("Ang velocity"); + particleCloud_.probeM().vectorFields_.append("Ang_velocity"); particleCloud_.probeM().scalarFields_.append("Rep"); particleCloud_.probeM().scalarFields_.append("Rew"); particleCloud_.probeM().scalarFields_.append("J*"); particleCloud_.probeM().scalarFields_.append("Cl(shear)"); particleCloud_.probeM().scalarFields_.append("Cl*(spin)"); - particleCloud_.probeM().scalarFields_.append("Omega eq"); + particleCloud_.probeM().scalarFields_.append("Omega_eq"); particleCloud_.probeM().scalarFields_.append("Cl(combined)"); particleCloud_.probeM().writeHeader(); } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C new file mode 100644 index 00000000..7cc125a2 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C @@ -0,0 +1,556 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling - Open Source CFD-DEM coupling + + CFDEMcoupling is part of the CFDEMproject + www.cfdem.com + Christoph Goniva, christoph.goniva@cfdem.com + Copyright 2009-2012 JKU Linz + Copyright 2012- DCS Computing GmbH, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling. + + CFDEMcoupling 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. + + CFDEMcoupling 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 CFDEMcoupling; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + This code is designed to realize coupled CFD-DEM simulations using LIGGGHTS + and OpenFOAM(R). Note: this code is not part of OpenFOAM(R) (see DISCLAIMER). +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "ParmarBassetForce.H" +#include "addToRunTimeSelectionTable.H" +#include "smoothingModel.H" +#include "constDiffSmoothing.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +#define NOTONCPU 9999 + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(ParmarBassetForce, 0); + +addToRunTimeSelectionTable +( + forceModel, + ParmarBassetForce, + dictionary +); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +ParmarBassetForce::ParmarBassetForce +( + const dictionary& dict, + cfdemCloud& sm +) +: + forceModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + velFieldName_(propsDict_.lookup("velFieldName")), + U_(sm.mesh().lookupObject (velFieldName_)), + UsFieldName_(propsDict_.lookup("granVelFieldName")), + Us_(sm.mesh().lookupObject (UsFieldName_)), + nInt_(readScalar(propsDict_.lookup("nIntegral"))), + discOrder_(1), + nHist_(nInt_+2*discOrder_), + ddtUrelHist_(nHist_,NULL), // UrelHist_[ndt in past][particle ID][dim] + rHist_(nHist_,NULL), // rHist_[ndt in past][particle ID][0] + FHist_(2,List(3,NULL)), // FHist_[k={1,2}-1][ndt in past][particle ID][dim] + gH0_(NULL), + tRef_(NULL), + mRef_(NULL), + lRef_(NULL), + Urel_ + ( IOobject + ( + "Urel", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedVector("zero", dimensionSet(0,1,-1,0,0,0,0), vector(0,0,0)) + ), + ddtUrel_ + ( IOobject + ( + "ddtUrel", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedVector("zero", dimensionSet(0,1,-2,0,0,0,0), vector(0,0,0)) + ), + smoothingModel_ + ( + smoothingModel::New + ( + propsDict_, + sm + ) + ) +{ + + // init force sub model + setForceSubModels(propsDict_); + // define switches which can be read from dict + forceSubM(0).setSwitchesList(SW_TREAT_FORCE_EXPLICIT,true); // activate treatExplicit switch + forceSubM(0).setSwitchesList(SW_INTERPOLATION,true); // activate search for interpolate switch + forceSubM(0).readSwitches(); + + //Extra switches/settings + particleCloud_.checkCG(true); + + if (discOrder_!=1) + FatalError << "Parmar Basset Force: Discretisation order > 1 not implemented!" << endl; + + //Append the field names to be probed + particleCloud_.probeM().initialize(typeName, typeName+".logDat"); + particleCloud_.probeM().vectorFields_.append("ParmarBassetForce"); //first entry must the be the force + particleCloud_.probeM().vectorFields_.append("Urel"); + particleCloud_.probeM().vectorFields_.append("ddtUrel"); + particleCloud_.probeM().vectorFields_.append("Fshort"); + particleCloud_.probeM().vectorFields_.append("Flong1"); + particleCloud_.probeM().vectorFields_.append("Flong2"); + particleCloud_.probeM().scalarFields_.append("ReRef"); + particleCloud_.probeM().scalarFields_.append("tRef"); + particleCloud_.probeM().scalarFields_.append("mRef"); + particleCloud_.probeM().scalarFields_.append("lRef"); + particleCloud_.probeM().scalarFields_.append("r"); + particleCloud_.probeM().scalarFields_.append("t0"); + particleCloud_.probeM().scalarFields_.append("nKnown"); + particleCloud_.probeM().writeHeader(); + + Urel_ = Us_ - U_; +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +ParmarBassetForce::~ParmarBassetForce() +{ + particleCloud_.dataExchangeM().destroy(gH0_, 1); + particleCloud_.dataExchangeM().destroy(tRef_, 1); + particleCloud_.dataExchangeM().destroy(mRef_, 1); + particleCloud_.dataExchangeM().destroy(lRef_, 1); + + for (int i=0; i UrelInterpolator_(Urel_); + interpolationCellPoint ddtUrelInterpolator_(ddtUrel_); + + for(int index = 0;index < particleCloud_.numberOfParticles(); index++) + { + vector ParmarBassetForce(0,0,0); + vector Fshort(0,0,0); + label cellI = particleCloud_.cellIDs()[index][0]; + + if (cellI > -1) // particle Found + { + // particle position (m) + position = particleCloud_.position(index); + + // relative velocity (m/s) + if(forceSubM(0).interpolation()) + Urel = UrelInterpolator_.interpolate(position,cellI); + else + Urel = Urel_[cellI]; + + // acceleration (m/s2) + if(forceSubM(0).interpolation()) + ddtUrel = ddtUrelInterpolator_.interpolate(position,cellI); + else + ddtUrel = ddtUrel_[cellI]; + + //********* set/get reference point *********// + + scalar rs = particleCloud_.radius(index); + scalar Re = 2.*rs*mag(Urel)/nufField[cellI]; + scalar gH = (0.75 + 0.105*Re)/(Re+SMALL); // Eq. 3.3 + scalar r = 1; + + if (gH0_[index][0]!=NOTONCPU) + r = pow(gH0_[index][0]/gH,1.5); // Eq. 3.4 + + if (gH0_[index][0]==NOTONCPU || r<.25 || r>2.) + { + // calculate new reference values + scalar tRef = (rs*rs) / nufField[cellI] * (gH*gH) * 4.3354; // (256/pi)^(1/3) = 4.3354 (Eq 3.1) + scalar Vs = rs*rs*rs*M_PI*4/3; + scalar mRef = Vs*rhoField[cellI] * gH * 5.2863; // 9/(2*sqrt(pi))*(256/pi)^(1/6) = 5.2863 (Eq. 3.2) + + // rescale history to new reference point + if (r<.25 || r>2.) + { + // old/new + scalar tScale = tRef_[index][0]/tRef; + scalar mScale = mRef_[index][0]/mRef; + scalar lScale = lRef_[index][0]/rs; + scalar rScale = gH0_[index][0]/gH; + + rescaleHist(tScale, mScale, lScale, rScale, index); + } + + gH0_[index][0] = gH; + tRef_[index][0] = tRef; + mRef_[index][0] = mRef; + lRef_[index][0] = rs; + } + + scalar mps = lRef_[index][0]/tRef_[index][0]; // m/s + scalar mpss = mps/tRef_[index][0]; // m/s^2 + scalar newton = mpss*mRef_[index][0]; // kg*m/s^2 + scalar dt = U_.mesh().time().deltaT().value() / tRef_[index][0]; // dim.less + scalar t0 = nInt_*dt; // dim.less + + //********* update histories *********// + + // non-dimensionlise + Urel /= mps; + ddtUrel /= mpss; + + // warning for too small t0 + if (t00; j--) // loop over past times + ddtUrelHist_[j][index][i] = ddtUrelHist_[j-1][index][i]; + + ddtUrelHist_[0][index][i] = ddtUrel[i]; + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void Foam::ParmarBassetForce::update_rHist(scalar r, int index) const +{ + for (int j=nHist_-1; j>0; j--) // loop over past times + rHist_[j][index][0] = rHist_[j-1][index][0]; + + rHist_[0][index][0] = r; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void Foam::ParmarBassetForce::update_FHist(vector F1, vector F2, int index) const +{ + for (int i=0; i<3; i++) // loop over dimensions + { + for (int k=0; k<2; k++) // loop over F1, F2 + for (int j=2*discOrder_; j>0; j--) // loop over past times + FHist_[k][j][index][i] = FHist_[k][j-1][index][i]; + + FHist_[0][0][index][i] = F1[i]; + FHist_[1][0][index][i] = F2[i]; + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void Foam::ParmarBassetForce::calculateCoeffs(int k, scalar t0, scalar r, double c[2][4][3], double chi[2][4][2], double C[4]) const +{ + for (int j=0; j<4; j++) // loop over terms + { + C[j] = (c[k][j][0] * pow((t0 + c[k][j][1]),c[k][j][2])); //t0 dependency + C[j] *= (1 + chi[k][j][0]*(r-1) + chi[k][j][1]*(r-1)*(r-1)); // r dependency + } +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void Foam::ParmarBassetForce::solveFlongODE(int k, double C[4], scalar dt, int index, int discOrder_) const +{ + if (discOrder_==1) + { + for (int i=0; i<3; i++) // loop over dimensions + { + FHist_[k][0][index][i] = + ( + ( C[1]/dt+2/dt/dt) * FHist_[k][1][index][i] + - ( 1/dt/dt) * FHist_[k][2][index][i] + - (C[2]+C[3]/dt ) * ddtUrelHist_[nHist_-2][index][i] + + ( C[3]/dt ) * ddtUrelHist_[nHist_-1][index][i] + ) / (C[0]+C[1]/dt+1/dt/dt); // Eq. 3.20 using first order temporal discretisation + } + } +} + +void Foam::ParmarBassetForce::rescaleHist(scalar tScale, scalar mScale, scalar lScale, scalar rScale, int index) const +{ + for (int i=0; i<3; i++) // loop over dimensions + { + // rescale ddtU history + for (int j=0; j ddtUrelHist_; + + mutable List rHist_; + + mutable List> FHist_; + + mutable double** gH0_; + + mutable double** tRef_; + + mutable double** mRef_; + + mutable double** lRef_; + + mutable volVectorField Urel_; + + mutable volVectorField ddtUrel_; + + autoPtr smoothingModel_; + + +public: + + //- Runtime type information + TypeName("ParmarBassetForce"); + + + // Constructors + + //- Construct from components + ParmarBassetForce + ( + const dictionary& dict, + cfdemCloud& sm + ); + + // Destructor + + ~ParmarBassetForce(); + + + // Member Functions + void setForce() const; + + + void reAllocArrays() const; + + inline const smoothingModel& smoothingM() const + { + return smoothingModel_; + } + + scalar calculateK0(scalar r, scalar dt) const; + + scalar trapWeight(int i, int n) const; + + void update_ddtUrelHist(vector ddtUrel, int index) const; + + void update_rHist(scalar r, int index) const; + + void update_FHist(vector F1, vector F2, int index) const; + + void calculateCoeffs(int k, scalar t0, scalar r, double c[2][4][3], double chi[2][4][2], double C[4]) const; + + void solveFlongODE(int k, double C[4], scalar dt, int index, int discOrder_) const; + + void rescaleHist(scalar tScale, scalar mScale, scalar lScale, scalar rScale, int index) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.C b/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.C new file mode 100644 index 00000000..a12e566f --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.C @@ -0,0 +1,265 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling - Open Source CFD-DEM coupling + + CFDEMcoupling is part of the CFDEMproject + www.cfdem.com + Christoph Goniva, christoph.goniva@cfdem.com + Copyright 2009-2012 JKU Linz + Copyright 2012- DCS Computing GmbH, Linz + Copyright (C) 2013- Graz University of + Technology, IPPT +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling. + + CFDEMcoupling 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. + + CFDEMcoupling 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 CFDEMcoupling; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + This code is designed to realize coupled CFD-DEM simulations using LIGGGHTS + and OpenFOAM(R). Note: this code is not part of OpenFOAM(R) (see DISCLAIMER). +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "constDiffAndTemporalSmoothing.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(constDiffAndTemporalSmoothing, 0); + +addToRunTimeSelectionTable +( + smoothingModel, + constDiffAndTemporalSmoothing, + dictionary +); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +constDiffAndTemporalSmoothing::constDiffAndTemporalSmoothing +( + const dictionary& dict, + cfdemCloud& sm +) +: + smoothingModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + lowerLimit_(readScalar(propsDict_.lookup("lowerLimit"))), + upperLimit_(readScalar(propsDict_.lookup("upperLimit"))), + smoothingLength_(dimensionedScalar("smoothingLength",dimensionSet(0,1,0,0,0,0,0), readScalar(propsDict_.lookup("smoothingLength")))), + smoothingLengthReferenceField_(dimensionedScalar("smoothingLengthReferenceField",dimensionSet(0,1,0,0,0,0,0), readScalar(propsDict_.lookup("smoothingLength")))), + DT_("DT", dimensionSet(0,2,-1,0,0), 0.), + gamma_(readScalar(propsDict_.lookup("smoothingStrength"))), + correctBoundary_(propsDict_.lookupOrDefault("correctBoundary",false)), + verbose_(false) +{ + + if(propsDict_.found("verbose")) + verbose_ = true; + + if(propsDict_.found("smoothingLengthReferenceField")) + smoothingLengthReferenceField_.value() = double(readScalar(propsDict_.lookup("smoothingLengthReferenceField"))); + + checkFields(sSmoothField_); + checkFields(vSmoothField_); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +constDiffAndTemporalSmoothing::~constDiffAndTemporalSmoothing() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +bool constDiffAndTemporalSmoothing::doSmoothing() const +{ + return true; +} + + +void constDiffAndTemporalSmoothing::smoothen(volScalarField& fieldSrc) const +{ + // Create scalar smooth field from virgin scalar smooth field template + volScalarField sSmoothField = sSmoothField_; + + sSmoothField.dimensions().reset(fieldSrc.dimensions()); + sSmoothField.ref()=fieldSrc.internalField(); + sSmoothField.correctBoundaryConditions(); + sSmoothField.oldTime().dimensions().reset(fieldSrc.dimensions()); + sSmoothField.oldTime()=fieldSrc; + sSmoothField.oldTime().correctBoundaryConditions(); + + double deltaT = sSmoothField.mesh().time().deltaTValue(); + DT_.value() = smoothingLength_.value() * smoothingLength_.value() / deltaT; + + // do smoothing + solve + ( + fvm::ddt(sSmoothField) + -fvm::laplacian(DT_, sSmoothField) + ); + + // bound sSmoothField_ + forAll(sSmoothField,cellI) + { + sSmoothField[cellI]=max(lowerLimit_,min(upperLimit_,sSmoothField[cellI])); + } + + // get data from working sSmoothField - will copy only values at new time + fieldSrc=sSmoothField; + fieldSrc.correctBoundaryConditions(); + + if(verbose_) + { + Info << "min/max(fieldoldTime) (unsmoothed): " << min(sSmoothField.oldTime()) << tab << max(sSmoothField.oldTime()) << endl; + Info << "min/max(fieldSrc): " << min(fieldSrc) << tab << max(fieldSrc) << endl; + Info << "min/max(fieldSrc.oldTime): " << min(fieldSrc.oldTime()) << tab << max(fieldSrc.oldTime()) << endl; + } + +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void constDiffAndTemporalSmoothing::smoothen(volVectorField& fieldSrc) const +{ + // Create scalar smooth field from virgin scalar smooth field template + volVectorField vSmoothField = vSmoothField_; + + vSmoothField.dimensions().reset(fieldSrc.dimensions()); + vSmoothField.ref()=fieldSrc.internalField(); + vSmoothField.correctBoundaryConditions(); + vSmoothField.oldTime().dimensions().reset(fieldSrc.dimensions()); + vSmoothField.oldTime()=fieldSrc; + vSmoothField.oldTime().correctBoundaryConditions(); + + dimensionedScalar deltaT = vSmoothField.mesh().time().deltaT(); + DT_.value() = smoothingLength_.value() * smoothingLength_.value() / deltaT.value(); + + // do spacial smoothing + solve + ( + fvm::ddt(vSmoothField) + -fvm::laplacian(DT_, vSmoothField) + ); + + // create fields for temporal smoothing + volVectorField refField = vSmoothField; + + vSmoothField.ref()=fieldSrc.oldTime().internalField(); + vSmoothField.correctBoundaryConditions(); + vSmoothField.oldTime()=fieldSrc.oldTime(); + vSmoothField.oldTime().correctBoundaryConditions(); + + // do temporal smoothing + solve + ( + fvm::ddt(vSmoothField) + - + gamma_/deltaT * (refField - fvm::Sp(1.0,vSmoothField)) + ); + + // create temporally smoothened boundary field + if (correctBoundary_) + vSmoothField.boundaryFieldRef() = 1/(1+gamma_)*fieldSrc.oldTime().boundaryField() + gamma_/(1+gamma_)*fieldSrc.boundaryField(); + + // get data from working vSmoothField + fieldSrc=vSmoothField; + fieldSrc.correctBoundaryConditions(); + + if(verbose_) + { + Info << "min/max(fieldoldTime) (unsmoothed): " << min(vSmoothField.oldTime()) << tab << max(vSmoothField.oldTime()) << endl; + Info << "min/max(fieldSrc): " << min(fieldSrc) << tab << max(fieldSrc) << endl; + Info << "min/max(fieldSrc.oldTime): " << min(fieldSrc.oldTime()) << tab << max(fieldSrc.oldTime()) << endl; + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +void constDiffAndTemporalSmoothing::smoothenReferenceField(volVectorField& fieldSrc) const +{ + // Create scalar smooth field from virgin scalar smooth field template + volVectorField vSmoothField = vSmoothField_; + + vSmoothField.dimensions().reset(fieldSrc.dimensions()); + vSmoothField.ref()=fieldSrc.internalField(); + vSmoothField.correctBoundaryConditions(); + vSmoothField.oldTime().dimensions().reset(fieldSrc.dimensions()); + vSmoothField.oldTime()=fieldSrc; + vSmoothField.oldTime().correctBoundaryConditions(); + + double sourceStrength = 1e5; //large number to keep reference values constant + + dimensionedScalar deltaT = vSmoothField.mesh().time().deltaT(); + DT_.value() = smoothingLengthReferenceField_.value() + * smoothingLengthReferenceField_.value() / deltaT.value(); + + tmp NLarge + ( + new volScalarField + ( + IOobject + ( + "NLarge", + particleCloud_.mesh().time().timeName(), + particleCloud_.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + particleCloud_.mesh(), + 0.0 + ) + ); + + + //loop over particles and map max particle diameter to Euler Grid + forAll(vSmoothField,cellI) + { + if ( mag(vSmoothField.oldTime().internalField()[cellI]) > 0.0f) // have a vector in the OLD vSmoothField, so keep it! + NLarge.ref()[cellI] = sourceStrength; + } + + // do the smoothing + solve + ( + fvm::ddt(vSmoothField) + -fvm::laplacian( DT_, vSmoothField) + == + NLarge() / deltaT * vSmoothField.oldTime() //add source to keep cell values constant + -fvm::Sp( NLarge() / deltaT, vSmoothField) //add sink to keep cell values constant + ); + + // get data from working vSmoothField + fieldSrc=vSmoothField; + fieldSrc.correctBoundaryConditions(); + + if(verbose_) + { + Info << "min/max(fieldoldTime) (unsmoothed): " << min(vSmoothField.oldTime()) << tab << max(vSmoothField.oldTime()) << endl; + Info << "min/max(fieldSrc): " << min(fieldSrc) << tab << max(fieldSrc) << endl; + Info << "min/max(fieldSrc.oldTime): " << min(fieldSrc.oldTime()) << tab << max(fieldSrc.oldTime()) << endl; + } + +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.H b/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.H new file mode 100644 index 00000000..16d962de --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/smoothingModel/constDiffAndTemporalSmoothing/constDiffAndTemporalSmoothing.H @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling - Open Source CFD-DEM coupling + + CFDEMcoupling is part of the CFDEMproject + www.cfdem.com + Christoph Goniva, christoph.goniva@cfdem.com + Copyright 2009-2012 JKU Linz + Copyright 2012- DCS Computing GmbH, Linz + Copyright (C) 2013- Graz University of + Technology, IPPT +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling. + + CFDEMcoupling 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. + + CFDEMcoupling 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 CFDEMcoupling; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + This code is designed to realize coupled CFD-DEM simulations using LIGGGHTS + and OpenFOAM(R). Note: this code is not part of OpenFOAM(R) (see DISCLAIMER). + +Class + constDiffAndTemporalSmoothing + +SourceFiles + constDiffAndTemporalSmoothing.C + +\*---------------------------------------------------------------------------*/ + +#ifndef constDiffAndTemporalSmoothing_H +#define constDiffAndTemporalSmoothing_H + +#include "smoothingModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class constDiffAndTemporalSmoothing Declaration +\*---------------------------------------------------------------------------*/ + +class constDiffAndTemporalSmoothing +: + public smoothingModel +{ + +private: + + dictionary propsDict_; + scalar lowerLimit_; + scalar upperLimit_; + dimensionedScalar smoothingLength_; + dimensionedScalar smoothingLengthReferenceField_; + mutable dimensionedScalar DT_; + scalar gamma_; + bool correctBoundary_; + bool verbose_; + +public: + + //- Runtime type information + TypeName("constDiffAndTemporalSmoothing"); + + + // Constructors + + //- Construct from components + constDiffAndTemporalSmoothing + ( + const dictionary& dict, + cfdemCloud& sm + ); + + // Destructor + + ~constDiffAndTemporalSmoothing(); + + + // Member Functions + bool doSmoothing() const; + + //void dSmoothing(volScalarField&) const; + + void smoothen(volScalarField&) const; + + void smoothen(volVectorField&) const; + + void smoothenReferenceField(volVectorField&) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticleComp/Make/files b/src/lagrangian/cfdemParticleComp/Make/files index b119a3b3..1d36d4da 100644 --- a/src/lagrangian/cfdemParticleComp/Make/files +++ b/src/lagrangian/cfdemParticleComp/Make/files @@ -54,6 +54,7 @@ $(forceModels)/ShirgaonkarIB/ShirgaonkarIB.C $(forceModels)/KochHillDrag/KochHillDrag.C $(forceModels)/LaEuScalarTemp/LaEuScalarTemp.C $(forceModels)/virtualMassForce/virtualMassForce.C +$(forceModels)/ParmarBassetForce/ParmarBassetForce.C $(forceModels)/gradPForce/gradPForce.C $(forceModels)/viscForce/viscForce.C $(forceModels)/MeiLift/MeiLift.C From 37a71048494b64a9a5e1da27b8caccbcb1f6d9c9 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 30 Jan 2019 09:56:46 +0100 Subject: [PATCH 20/47] added second order discretisation to ParmarBassetForce --- .../ParmarBassetForce/ParmarBassetForce.C | 63 +++++++++++++------ .../ParmarBassetForce/ParmarBassetForce.H | 2 +- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C index 7cc125a2..ad80f07b 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/ParmarBassetForce/ParmarBassetForce.C @@ -72,11 +72,11 @@ ParmarBassetForce::ParmarBassetForce UsFieldName_(propsDict_.lookup("granVelFieldName")), Us_(sm.mesh().lookupObject (UsFieldName_)), nInt_(readScalar(propsDict_.lookup("nIntegral"))), - discOrder_(1), - nHist_(nInt_+2*discOrder_), + discOrder_(readScalar(propsDict_.lookup("discretisationOrder"))), + nHist_(nInt_+discOrder_+1), ddtUrelHist_(nHist_,NULL), // UrelHist_[ndt in past][particle ID][dim] rHist_(nHist_,NULL), // rHist_[ndt in past][particle ID][0] - FHist_(2,List(3,NULL)), // FHist_[k={1,2}-1][ndt in past][particle ID][dim] + FHist_(2,List(2*discOrder_+1,NULL)), // FHist_[k={1,2}-1][ndt in past][particle ID][dim] gH0_(NULL), tRef_(NULL), mRef_(NULL), @@ -125,8 +125,8 @@ ParmarBassetForce::ParmarBassetForce //Extra switches/settings particleCloud_.checkCG(true); - if (discOrder_!=1) - FatalError << "Parmar Basset Force: Discretisation order > 1 not implemented!" << endl; + if (discOrder_!=1 || discOrder_!=2) + FatalError << "Parmar Basset Force: Discretisation order > 2 not implemented!" << endl; //Append the field names to be probed particleCloud_.probeM().initialize(typeName, typeName+".logDat"); @@ -183,7 +183,7 @@ void ParmarBassetForce::setForce() const vector Urel(0,0,0); vector ddtUrel(0,0,0); - scalar t0min = 0.001; + scalar t0min = 0.01; const volScalarField& nufField = forceSubM(0).nuField(); const volScalarField& rhoField = forceSubM(0).rhoField(); @@ -270,6 +270,8 @@ void ParmarBassetForce::setForce() const scalar lScale = lRef_[index][0]/rs; scalar rScale = gH0_[index][0]/gH; + r = 1; + rescaleHist(tScale, mScale, lScale, rScale, index); } @@ -291,14 +293,18 @@ void ParmarBassetForce::setForce() const Urel /= mps; ddtUrel /= mpss; - // warning for too small t0 - if (t0 UrelInterpolator_(Urel_); interpolationCellPoint ddtUrelInterpolator_(ddtUrel_); + // + interpolationCellPoint UrelNoSmoothInterpolator_(UrelNoSmooth_); + interpolationCellPoint ddtUrelNoSmoothInterpolator_(ddtUrelNoSmooth_); + // + for(int index = 0;index < particleCloud_.numberOfParticles(); index++) { vector ParmarBassetForce(0,0,0); @@ -249,36 +263,32 @@ void ParmarBassetForce::setForce() const scalar rs = particleCloud_.radius(index); scalar Re = 2.*rs*mag(Urel)/nufField[cellI]; scalar gH = (0.75 + 0.105*Re)/(Re+SMALL); // Eq. 3.3 - scalar r = 1; + scalar r; if (gH0_[index][0]!=NOTONCPU) + { r = pow(gH0_[index][0]/gH,1.5); // Eq. 3.4 - if (gH0_[index][0]==NOTONCPU || r<.25 || r>2.) + if (r<.25 || r>2.) + { + gH0_[index][0] = NOTONCPU; //reset reference + ddtUrelHist_[0][index][0] = NOTONCPU; //reset ddtU history (only component used for checking nKnown) + } + + } + + if (gH0_[index][0]==NOTONCPU) { // calculate new reference values scalar tRef = (rs*rs) / nufField[cellI] * (gH*gH) * 4.3354; // (256/pi)^(1/3) = 4.3354 (Eq 3.1) scalar Vs = rs*rs*rs*M_PI*4/3; scalar mRef = Vs*rhoField[cellI] * gH * 5.2863; // 9/(2*sqrt(pi))*(256/pi)^(1/6) = 5.2863 (Eq. 3.2) - // rescale history to new reference point - if (r<.25 || r>2.) - { - // old/new - scalar tScale = tRef_[index][0]/tRef; - scalar mScale = mRef_[index][0]/mRef; - scalar lScale = lRef_[index][0]/rs; - scalar rScale = gH0_[index][0]/gH; - - r = 1; - - rescaleHist(tScale, mScale, lScale, rScale, index); - } - gH0_[index][0] = gH; tRef_[index][0] = tRef; mRef_[index][0] = mRef; lRef_[index][0] = rs; + r = 1; } scalar mps = lRef_[index][0]/tRef_[index][0]; // m/s @@ -345,7 +355,7 @@ void ParmarBassetForce::setForce() const // update F1, F2 history update_FHist(vector(0., 0., 0.),vector(0., 0., 0.),index); - // initialise ddtUrel(t0) as 0 and r(t0) as 1 + // initialise ddtUrel(t0) and Flong(:) as 0 and r(t0) as 1 if (nKnown == nInt_) { for (int j=nInt_; j Date: Tue, 2 Apr 2019 12:52:15 +0200 Subject: [PATCH 25/47] virtual mass force: added smoothing model, revised ddtU_rel calculations --- .../virtualMassForce/virtualMassForce.C | 179 ++++++++++-------- .../virtualMassForce/virtualMassForce.H | 9 + 2 files changed, 113 insertions(+), 75 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C index 0f1db4c9..2746a118 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.C @@ -77,7 +77,27 @@ virtualMassForce::virtualMassForce splitUrelCalculation_(propsDict_.lookupOrDefault("splitUrelCalculation",false)), useUs_(propsDict_.lookupOrDefault("useUs",false)), useFelderhof_(propsDict_.lookupOrDefault("useFelderhof",false)), - Cadd_(0.5) + Cadd_(0.5), + DDtUrel_ + ( IOobject + ( + "DDtUrel", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedVector("zero", dimensionSet(0,1,-2,0,0,0,0), vector(0,0,0)) + ), + smoothingModel_ + ( + smoothingModel::New + ( + propsDict_, + sm + ) + ) { if (particleCloud_.dataExchangeM().maxNumberOfParticles() > 0) @@ -108,6 +128,11 @@ virtualMassForce::virtualMassForce { Info << "Virtual mass model: using averaged Us \n"; Info << "WARNING: ignoring virtual mass of relative particle motion/collisions \n"; + + if(splitUrelCalculation_) + { + FatalError << "Virtual mass model: useUs=true requires splitUrelCalculation_=false" << abort(FatalError); + } } if(useFelderhof_) { @@ -124,9 +149,14 @@ virtualMassForce::virtualMassForce particleCloud_.probeM().initialize(typeName, typeName+".logDat"); particleCloud_.probeM().vectorFields_.append("virtualMassForce"); //first entry must the be the force particleCloud_.probeM().vectorFields_.append("acceleration"); + // + particleCloud_.probeM().vectorFields_.append("accelerationNoSmooth"); + // particleCloud_.probeM().scalarFields_.append("Cadd"); particleCloud_.probeM().scalarFields_.append("Vs"); particleCloud_.probeM().scalarFields_.append("rho"); + particleCloud_.probeM().scalarFields_.append("voidfraction"); + particleCloud_.probeM().scalarFields_.append("specificGravity"); particleCloud_.probeM().writeHeader(); } @@ -148,34 +178,22 @@ void virtualMassForce::setForce() const scalar dt = U_.mesh().time().deltaT().value(); - vector position(0,0,0); - vector Ufluid(0,0,0); - vector Urel(0,0,0); - vector DDtU(0,0,0); - vector ddtUs(0,0,0); - vector Us(0,0,0); - vector UrelOld(0,0,0); - vector ddtUrel(0,0,0); - vector accel(0,0,0); + //acceleration field + if(splitUrelCalculation_) + DDtUrel_ = fvc::ddt(U_) + fvc::div(phi_, U_); //Total Derivative of fluid velocity + else if(useUs_) + DDtUrel_ = fvc::ddt(U_) + fvc::div(phi_, U_) - fvc::ddt(Us_); //Total Derivative of fluid velocity minus average particle velocity - scalar voidfraction(1); - scalar epsilons(0); - scalar sg(1); - scalar logsg(0); + // + volVectorField DDtUrelNoSmooth_ = DDtUrel_; + interpolationCellPoint DDtUrelNoSmoothInterpolator_(DDtUrelNoSmooth_); + // + + // smoothen + smoothingM().smoothen(DDtUrel_); - //DDtU - volVectorField DDtU_(0.0*U_/U_.mesh().time().deltaT()); - if(splitUrelCalculation_ || useUs_ ) - DDtU_ = fvc::ddt(U_) + fvc::div(phi_, U_); //Total Derivative of fluid velocity - - //ddtUs - volVectorField ddtUs_(0.0*U_/U_.mesh().time().deltaT()); - if (useUs_) - ddtUs_ = fvc::ddt(Us_); - - interpolationCellPoint UInterpolator_( U_); - interpolationCellPoint ddtUsInterpolator_(ddtUs_); - interpolationCellPoint DDtUInterpolator_(DDtU_); + interpolationCellPoint UInterpolator_(U_); + interpolationCellPoint DDtUrelInterpolator_(DDtUrel_); interpolationCellPoint voidfractionInterpolator_(voidfraction_); #include "setupProbeModel.H" @@ -185,79 +203,72 @@ void virtualMassForce::setForce() const for(int index = 0;index < particleCloud_.numberOfParticles(); index++) { vector virtualMassForce(0,0,0); + vector position(0,0,0); + vector DDtUrel(0,0,0); + + scalar voidfraction(1); + scalar sg(1); + label cellI = particleCloud_.cellIDs()[index][0]; if (cellI > -1) // particle Found { - // particle position and fluid velocity + // particle position if(forceSubM(0).interpolation()) - { - position = particleCloud_.position(index); - Ufluid = UInterpolator_.interpolate(position,cellI); - } - else - { - Ufluid = U_[cellI]; - } + position = particleCloud_.position(index); - // DDtU / relative velocity + //********* acceleration value *********// if(splitUrelCalculation_ || useUs_ ) { - if(forceSubM(0).interpolation()) - DDtU = DDtUInterpolator_.interpolate(position,cellI); + // DDtUrel from acceleration field + if(forceSubM(0).interpolation()) + DDtUrel = DDtUrelInterpolator_.interpolate(position,cellI); else - DDtU = DDtU_[cellI]; + DDtUrel = DDtUrel_[cellI]; } else { - Us = particleCloud_.velocity(index); - Urel = Ufluid - Us; - } + // DDtUrel from UrelOld + vector Ufluid(0,0,0); - // averaged Us - if(useUs_ && !splitUrelCalculation_ ) - { - if(forceSubM(0).interpolation()) - ddtUs = ddtUsInterpolator_.interpolate(position,cellI); - else - ddtUs = ddtUs_[cellI]; - } + // relative velocity + if(forceSubM(0).interpolation()) + Ufluid = UInterpolator_.interpolate(position,cellI); + else + Ufluid = U_[cellI]; - // ddtUrel from UrelOld - if (!useUs_ || !splitUrelCalculation_ ) - { - //Check of particle was on this CPU the last step + vector Us = particleCloud_.velocity(index); + vector Urel = Ufluid - Us; + + //Check of particle was on this CPU the last step if(UrelOld_[index][0]==NOTONCPU) //use 1. element to indicate that particle was on this CPU the last time step haveUrelOld_ = false; else haveUrelOld_ = true; - vector UrelOld(0.,0.,0.); - vector ddtUrel(0.,0.,0.); + vector UrelOld(0,0,0); + for(int j=0;j<3;j++) { UrelOld[j] = UrelOld_[index][j]; UrelOld_[index][j] = Urel[j]; } if(haveUrelOld_ ) //only compute force if we have old (relative) velocity - ddtUrel = (Urel-UrelOld)/dt; + DDtUrel = (Urel-UrelOld)/dt; } - // take right expression for the acceleration term - if(splitUrelCalculation_) - accel = DDtU; - else if (useUs_) - accel = DDtU - ddtUs; - else - accel = ddtUrel; - - // take right expression for Cadd + //********* Cadd value *********// scalar rho = forceSubM(0).rhoField()[cellI]; scalar ds = 2*particleCloud_.radius(index); scalar Vs = ds*ds*ds*M_PI/6; - + + scalar Cadd; + if (useFelderhof_) - { + { + scalar epsilons(0); + scalar logsg(0); + if(forceSubM(0).interpolation()) voidfraction = voidfractionInterpolator_.interpolate(position,cellI); else @@ -267,14 +278,19 @@ void virtualMassForce::setForce() const logsg = log(sg); epsilons = 1-voidfraction; - Cadd_ = 0.5 + Cadd = 0.5 + ( 0.047*logsg + 0.13)*epsilons + (-0.066*logsg - 0.58)*epsilons*epsilons + ( 1.42)*epsilons*epsilons*epsilons; } + else + { + // use predefined value + Cadd = Cadd_; + } - // calculate force - virtualMassForce = Cadd_ * rho * Vs * accel; + //********* calculate force *********// + virtualMassForce = Cadd_ * rho * Vs * DDtUrel; if( forceSubM(0).verbose() ) //&& index>100 && index < 105) { @@ -285,17 +301,30 @@ void virtualMassForce::setForce() const // Set value fields and write the probe if(probeIt_) { + // + vector DDtUrelNoSmooth(0,0,0); + if(forceSubM(0).interpolation()) + DDtUrelNoSmooth = DDtUrelInterpolator_.interpolate(position,cellI); + else + DDtUrelNoSmooth = DDtUrelNoSmooth_[cellI]; + // #include "setupProbeModelfields.H" vValues.append(virtualMassForce); //first entry must the be the force - vValues.append(accel); - sValues.append(Cadd_); + vValues.append(DDtUrel); + // + vValues.append(DDtUrelNoSmooth); + // + sValues.append(Cadd); sValues.append(Vs); sValues.append(rho); + sValues.append(voidfraction); + sValues.append(sg); particleCloud_.probeM().writeProbe(index, sValues, vValues); } } else //particle not on this CPU - UrelOld_[index][0]=NOTONCPU; + if (!useUs_ || !splitUrelCalculation_ ) + UrelOld_[index][0] = NOTONCPU; // write particle based data to global array forceSubM(0).partToArray(index,virtualMassForce,vector::zero); diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H index 6c302458..9cd1a3ad 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/virtualMassForce/virtualMassForce.H @@ -86,6 +86,10 @@ private: mutable double Cadd_; //custom Cadd value + mutable volVectorField DDtUrel_; + + autoPtr smoothingModel_; + public: @@ -112,6 +116,11 @@ public: void setForce() const; void reAllocArrays() const; + + inline const smoothingModel& smoothingM() const + { + return smoothingModel_; + } }; From e4a33e4c1d2c968c110f242a3a7582a3d49e66a8 Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 22 Jul 2019 16:58:27 +0200 Subject: [PATCH 26/47] added dollar ($) to ligggtsCommandModel --- .../liggghtsCommandModel/liggghtsCommandModel.C | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C index 9b6ef7f4..078b1423 100644 --- a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C +++ b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C @@ -276,6 +276,7 @@ void liggghtsCommandModel::parseCommandList(wordList& commandList,labelList& lab else if (add=="dot") add = "."; else if (add=="dotdot") add = ".."; else if (add=="slash") add = "/"; + else if (add=="dollar") add = "$"; else if (add=="noBlanks") // no blanks after the following words { add = ""; From c28480a8028c7924db073a2130cce55b698f3a8e Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 22 Jul 2019 17:03:57 +0200 Subject: [PATCH 27/47] added square and curly brackets to liggghtsCommandModel --- .../liggghtsCommandModel/liggghtsCommandModel.C | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C index 078b1423..3011917f 100644 --- a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C +++ b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C @@ -277,6 +277,10 @@ void liggghtsCommandModel::parseCommandList(wordList& commandList,labelList& lab else if (add=="dotdot") add = ".."; else if (add=="slash") add = "/"; else if (add=="dollar") add = "$"; + else if (add=="curlyOpen") add = "{"; + else if (add=="curlyClose") add = "}"; + else if (add=="squareOpen") add = "["; + else if (add=="squareClose") add = "]"; else if (add=="noBlanks") // no blanks after the following words { add = ""; From 39f6e7d0566033712ded003e85eec96c26108413 Mon Sep 17 00:00:00 2001 From: s126103 Date: Tue, 23 Jul 2019 09:13:56 +0200 Subject: [PATCH 28/47] pressure eqn and bc updates --- applications/solvers/cfdemSolverPiso/pEqn.H | 4 ++-- .../uniformFixedValueTubeFvPatchField.C | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/solvers/cfdemSolverPiso/pEqn.H b/applications/solvers/cfdemSolverPiso/pEqn.H index 96ca1d77..d4216118 100644 --- a/applications/solvers/cfdemSolverPiso/pEqn.H +++ b/applications/solvers/cfdemSolverPiso/pEqn.H @@ -21,7 +21,7 @@ phi = phiHbyA + rAUf*(fvc::interpolate(Ksl/rho) * phiS); MRF.makeRelative(phi); // adjustment of phi (only in cases w.o. p boundary conditions) not tested yet -adjustPhi(phi, U, p); +//adjustPhi(phi, U, p); // Update the pressure BCs to ensure flux consistency constrainPressure(p, Uvoidfraction, phiHbyA, rAUvoidfraction, MRF); @@ -55,4 +55,4 @@ else U = HbyA - voidfraction*rAU*fvc::grad(p) + Ksl/rho*Us*rAU; U.correctBoundaryConditions(); -fvOptions.correct(U); \ No newline at end of file +fvOptions.correct(U); diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C index 00f0033b..e843c66e 100755 --- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C @@ -89,7 +89,7 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField : fixedValueFvPatchField(p, iF), uniformValue_(Function1::New("uniformValue", dict)), - pName_("p"), //JOKER + pName_("p_rgh"), //JOKER phiName_("phi"), //JOKER velocityFieldName_("U"), densityFieldName_("rho"), @@ -110,7 +110,7 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField : fixedValueFvPatchField(ptf), uniformValue_(ptf.uniformValue_().clone().ptr()), - pName_("p"), //JOKER + pName_("p_rgh"), //JOKER phiName_("phi"), //JOKER velocityFieldName_("U"), densityFieldName_("rho"), @@ -132,7 +132,7 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField : fixedValueFvPatchField(ptf, iF), uniformValue_(ptf.uniformValue_().clone().ptr()), - pName_("p"), //JOKER + pName_("p_rgh"), //JOKER phiName_("phi"), //JOKER velocityFieldName_("U"), densityFieldName_("rho"), @@ -181,7 +181,7 @@ void uniformFixedValueTubeFvPatchField::updateCoeffs() //calc cell velocity from flux phip //scalar vel = phip/this->patch().magSf(); // some relaxation might be useful? - + // calc pressure drop // fvPatchField::operator==(0.5*zeta*density*mag(velocity)*mag(velocity)*uniformValue_->value(t)); //dP = zeta * l/d * rho u^2 / 2 From db0a544f28f702e10b98cac9ed25b124c8b12934 Mon Sep 17 00:00:00 2001 From: s126103 Date: Tue, 30 Jul 2019 11:43:57 +0200 Subject: [PATCH 29/47] Mei lift sign fix --- .../cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C index 7c6ccd53..b5368c17 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/MeiLift/MeiLift.C @@ -278,17 +278,19 @@ void MeiLift::setForce() const if (magUr>0.0 && magVorticity>0.0) { //Loth and Dorgan (2009), Eq (27) + // please note: in Loth and Dorgan Vrel = Vp-Uf, here Urel = Uf-Vp. Hence the reversed cross products. lift = 0.125 * constant::mathematical::pi * rho * Clcombined * magUr * magUr - * (vorticity ^ Ur) / mag(vorticity ^ Ur) // force direction + * (Ur ^ vorticity) / mag(Ur ^ vorticity) // force direction * ds * ds; } } else { //Loth and Dorgan (2009), Eq (36) + // please note: in Loth and Dorgan Vrel = Vp-Uf, here Urel = Uf-Vp. Hence the reversed cross products. if (useShearInduced_) { if (magUr>0.0 && magVorticity>0.0) @@ -298,7 +300,7 @@ void MeiLift::setForce() const * rho * Clshear * magUr * magUr - * (vorticity ^ Ur) / mag(vorticity ^ Ur) // force direction + * (Ur ^ vorticity) / mag(Ur ^ vorticity) // force direction * ds * ds; } } @@ -310,7 +312,7 @@ void MeiLift::setForce() const lift += 0.125 * constant::mathematical::pi * rho * Clspin_star - * (Omega ^ Ur) + * (Ur ^ Omega) * ds * ds * ds; } } From f8949cf4fe45674f03256e1fc20aca13df46971b Mon Sep 17 00:00:00 2001 From: s126103 Date: Tue, 12 Nov 2019 11:32:48 +0100 Subject: [PATCH 30/47] added p0 to uniformFixedValueTube --- .../uniformFixedValueTubeFvPatchField.C | 18 ++++++++++++------ .../uniformFixedValueTubeFvPatchField.H | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C index e843c66e..8f99d85a 100755 --- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C @@ -48,7 +48,8 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField densityFieldName_("rho"), tubeLength_(-1.), tubeDiameter_(-1.), - zeta_(-1) + zeta_(-1), + p0_(-1) { Info << "error, wrong constructor1!" << endl; } @@ -71,7 +72,8 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField densityFieldName_("rho"), tubeLength_(ptf.tubeLength_), tubeDiameter_(ptf.tubeDiameter_), - zeta_(ptf.zeta_) + zeta_(ptf.zeta_), + p0_(ptf.p0_) { const scalar t = this->db().time().timeOutputValue(); fvPatchField::operator==(uniformValue_->value(t)); @@ -95,7 +97,8 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField densityFieldName_("rho"), tubeLength_(readScalar(dict.lookup("tubeLength"))), tubeDiameter_(readScalar(dict.lookup("tubeDiameter"))), - zeta_(readScalar(dict.lookup("zeta"))) + zeta_(readScalar(dict.lookup("zeta"))), + p0_(readScalar(dict.lookup("p0"))) { const scalar t = this->db().time().timeOutputValue(); fvPatchField::operator==(uniformValue_->value(t)); @@ -116,7 +119,8 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField densityFieldName_("rho"), tubeLength_(ptf.tubeLength_), tubeDiameter_(ptf.tubeDiameter_), - zeta_(ptf.zeta_) + zeta_(ptf.zeta_), + p0_(ptf.p0_) { const scalar t = this->db().time().timeOutputValue(); fvPatchField::operator==(uniformValue_->value(t)); @@ -138,7 +142,8 @@ uniformFixedValueTubeFvPatchField::uniformFixedValueTubeFvPatchField densityFieldName_("rho"), tubeLength_(ptf.tubeLength_), tubeDiameter_(ptf.tubeDiameter_), - zeta_(ptf.zeta_) + zeta_(ptf.zeta_), + p0_(ptf.p0_) { const scalar t = this->db().time().timeOutputValue(); fvPatchField::operator==(uniformValue_->value(t)); @@ -185,7 +190,7 @@ void uniformFixedValueTubeFvPatchField::updateCoeffs() // calc pressure drop // fvPatchField::operator==(0.5*zeta*density*mag(velocity)*mag(velocity)*uniformValue_->value(t)); //dP = zeta * l/d * rho u^2 / 2 - fvPatchField::operator==((pressure+(0.5*zeta_*tubeLength_/tubeDiameter_*density*phip/this->patch().magSf()*phip/this->patch().magSf()-pressure)*uRelFact)*uniformValue_->value(t)); + fvPatchField::operator==((pressure+p0_+(0.5*zeta_*tubeLength_/tubeDiameter_*density*phip/this->patch().magSf()*phip/this->patch().magSf()-pressure)*uRelFact)*uniformValue_->value(t)); //fvPatchField::operator==((100.*uniformValue_->value(t))); fixedValueFvPatchField::updateCoeffs(); } @@ -200,6 +205,7 @@ void uniformFixedValueTubeFvPatchField::write(Ostream& os) const os.writeKeyword("tubeLength") << tubeLength_ << token::END_STATEMENT << nl; os.writeKeyword("tubeDiameter") << tubeDiameter_ << token::END_STATEMENT << nl; os.writeKeyword("zeta") << zeta_ << token::END_STATEMENT << nl; + os.writeKeyword("p0") << p0_ << token::END_STATEMENT << nl; } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.H index d86a92f2..ab4f859f 100755 --- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.H +++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.H @@ -74,6 +74,8 @@ class uniformFixedValueTubeFvPatchField scalar zeta_; + scalar p0_; + public: //- Runtime type information From 9e64ecc86c001697520ef72d190fb1afcd04368e Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 20 Nov 2019 16:59:54 +0100 Subject: [PATCH 31/47] update uniformFixedValueTube --- .../uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C index 8f99d85a..0b96120e 100755 --- a/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/uniformFixedValueTube/uniformFixedValueTubeFvPatchField.C @@ -190,7 +190,7 @@ void uniformFixedValueTubeFvPatchField::updateCoeffs() // calc pressure drop // fvPatchField::operator==(0.5*zeta*density*mag(velocity)*mag(velocity)*uniformValue_->value(t)); //dP = zeta * l/d * rho u^2 / 2 - fvPatchField::operator==((pressure+p0_+(0.5*zeta_*tubeLength_/tubeDiameter_*density*phip/this->patch().magSf()*phip/this->patch().magSf()-pressure)*uRelFact)*uniformValue_->value(t)); + fvPatchField::operator==((pressure+(0.5*zeta_*tubeLength_/tubeDiameter_*density*phip/this->patch().magSf()*phip/this->patch().magSf()+p0_-pressure)*uRelFact)*uniformValue_->value(t)); //fvPatchField::operator==((100.*uniformValue_->value(t))); fixedValueFvPatchField::updateCoeffs(); } From dbdf80ef922a66115318ad2e84642e32f41abb53 Mon Sep 17 00:00:00 2001 From: 20181526 Date: Wed, 11 Dec 2019 11:35:19 +0100 Subject: [PATCH 32/47] added Yagi wall heat transfer model --- src/lagrangian/cfdemParticle/Make/files | 1 + .../energyModel/YagiWallHT/YagiWallHT.C | 293 ++++++++++++++++++ .../energyModel/YagiWallHT/YagiWallHT.H | 141 +++++++++ src/lagrangian/cfdemParticleComp/Make/files | 1 + 4 files changed, 436 insertions(+) create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H diff --git a/src/lagrangian/cfdemParticle/Make/files b/src/lagrangian/cfdemParticle/Make/files index 58ae9abe..3bc0cb8d 100644 --- a/src/lagrangian/cfdemParticle/Make/files +++ b/src/lagrangian/cfdemParticle/Make/files @@ -33,6 +33,7 @@ $(energyModels)/energyModel/energyModel.C $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C +$(energyModels)/YagiWallHT/YagiWallHT.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C new file mode 100644 index 00000000..5dbb605a --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------------*\ +License + +This 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. + +This code 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 this code. If not, see . + +Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "YagiWallHT.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + + defineTypeNameAndDebug(YagiWallHT, 0); + + addToRunTimeSelectionTable(energyModel, YagiWallHT, dictionary); + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + + YagiWallHT::YagiWallHT + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ) + : + energyModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + interpolation_(propsDict_.lookupOrDefault("interpolation",false)), + verbose_(propsDict_.lookupOrDefault("verbose",false)), + QWallFluidName_(propsDict_.lookupOrDefault("QWallFluidName","QWallFluid")), + QWallFluid_ + ( IOobject + ( + QWallFluidName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ), + WallTempField_ + ( IOobject + ( + "WallTemp", + 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) // should i fix the wall temp here if its constant or fix it in BC? + ), + ReField_ + ( IOobject + ( + "ReField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + PrField_ + ( IOobject + ( + "PrField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + + tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), + tempField_(sm.mesh().lookupObject (tempFieldName_)), + voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + maxSource_(1e30), + velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), + U_(sm.mesh().lookupObject (velFieldName_)), + UsFieldName_(propsDict_.lookup("granVelFieldName")), + Us_(sm.mesh().lookupObject (UsFieldName_)), + densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), + rho_(sm.mesh().lookupObject (densityFieldName_)), + WallTempName_(propsDict_.lookup("WallTempName")), + WallTemp_(sm.mesh().lookupObject (WallTempName_)), + partRe_(NULL), + multiphase_(propsDict_.lookupOrDefault("multiphase",false)), + + kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + kfField_(sm.mesh().lookupObject (kfFieldName_)), + + CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + CpField_(sm.mesh().lookupObject (CpFieldName_)) + { + allocateMyArrays(); + + if (propsDict_.found("maxSource")) + { + maxSource_=readScalar(propsDict_.lookup ("maxSource")); + Info << "limiting eulerian source field to: " << maxSource_ << endl; + } + + if (verbose_) + { + ReField_.writeOpt() = IOobject::AUTO_WRITE; + PrField_.writeOpt() = IOobject::AUTO_WRITE; + ReField_.write(); + PrField_.write(); + } + } + + // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + + YagiWallHT::~YagiWallHT() + { + particleCloud_.dataExchangeM().destroy(partRe_,1); + } + + // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // + void YagiWallHT::allocateMyArrays() const + { + // get memory for 2d arrays + double initVal=0.0; + + if(verbose_) + { + particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); + } + } + + // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + + void YagiWallHT::calcEnergyContribution() + { + allocateMyArrays(); + + QWallFluid_.primitiveFieldRef() = 0.0; + + + + #ifdef compre + const volScalarField mufField = particleCloud_.turbulence().mu(); + #else + const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; + #endif + + + + // calc La based heat flux + scalar voidfraction(1); + vector Ufluid(0,0,0); + label cellI=0; + vector Us(0,0,0); + scalar ds(0); + scalar muf(0); + scalar magUr(0); + scalar Rep(0); + scalar H(0); + + interpolationCellPoint voidfractionInterpolator_(voidfraction_); + interpolationCellPoint UInterpolator_(U_); + interpolationCellPoint TInterpolator_(tempField_); + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + if(interpolation_) + { + vector position = particleCloud_.position(index); + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + Ufluid = UInterpolator_.interpolate(position,cellI); + } + else + { + voidfraction = voidfraction_[cellI]; + Ufluid = U_[cellI]; + } + + if (voidfraction < 0.01) + voidfraction = 0.01; + + Us = particleCloud_.velocity(index); + magUr = mag(Ufluid - Us); + ds = 2.*particleCloud_.radius(index); + muf = mufField[cellI]; + + Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; + partRe_[index][0] = Rep; + } + } + + // calculate Rep field + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + ReField_, + partRe_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); + + // calculate Pr field + PrField_ = CpField_ * mufField / kfField_; + // mass_flow_rate = magUr * rho_[cellI]; + + const fvPatchList& patches = U_.mesh().boundary(); + + forAll(patches, patchi) + { + const fvPatch& curPatch = patches[patchi]; + + if (WallTemp_.boundaryField().types()[patchi] == "fixedValue") + { + forAll(curPatch, facei) + { + label faceCelli = curPatch.faceCells()[facei]; + // calculate Urel + scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; + // calculate H + //H = 0.2087 * (pow(ReField_[faceCelli] , -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))); + H = 1; + // get delta T + //scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_.boundaryField()[patchi][facei]; + scalar deltaT = 100; + // get facei.area + scalar area = curPatch.magSf()[facei]; + scalar volume = U_.mesh().V()[faceCelli]; + + //Info << "faceID: " << facei << " area: " << area << " volume: " << volume << endl; + + QWallFluid_[faceCelli] = H*deltaT*area/volume; + } + } + } + +// h = 0.2087 * (pow(partRe_ , -0.20)) * CpField_ * magUr * rho_ / (pow(PrField_ , (2/3))); + + // limit source term + forAll(QWallFluid_,cellI) + { + scalar EuFieldInCell = QWallFluid_[cellI]; + + if(mag(EuFieldInCell) > maxSource_ ) + { + Pout << "limiting source term\n" << endl ; + QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; + } + } + + QWallFluid_.correctBoundaryConditions(); + + + } + + void YagiWallHT::addEnergyContribution(volScalarField& Qsource) const + { + Qsource += QWallFluid_; + } + + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H new file mode 100644 index 00000000..c535f538 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -0,0 +1,141 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + + Description + Correlation for Nusselt number according to + Gunn, D. J. International Journal of Heat and Mass Transfer 21.4 (1978) + +\*---------------------------------------------------------------------------*/ + +#ifndef YagiWallHT_H +#define YagiWallHT_H + +#include "fvCFD.H" +#include "cfdemCloudEnergy.H" +#include "energyModel.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class heatTransferGunn Declaration +\*---------------------------------------------------------------------------*/ + +class YagiWallHT +: + public energyModel +{ +protected: + + dictionary propsDict_; + + bool interpolation_; + + bool verbose_; + + word QWallFluidName_; + + volScalarField QWallFluid_; + + volScalarField WallTempField_; + + volScalarField ReField_; + + volScalarField PrField_; + + word tempFieldName_; + + const volScalarField& tempField_; + + word voidfractionFieldName_; + + const volScalarField& voidfraction_; + + scalar maxSource_; + + word velFieldName_; + + const volVectorField& U_; + + word UsFieldName_; + + const volVectorField& Us_; + + word densityFieldName_; + + const volScalarField& rho_; + + word WallTempName_; + + const volScalarField& WallTemp_; // Lagrangian array + + mutable double **partRe_; + + bool multiphase_; + + word kfFieldName_; + + const volScalarField& kfField_; + + word CpFieldName_; + + const volScalarField& CpField_; + + void allocateMyArrays() const; + + +public: + + //- Runtime type information + TypeName("YagiWallHT"); + + // Constructors + + //- Construct from components + YagiWallHT + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ); + + + // Destructor + + virtual ~YagiWallHT(); + + + // Member Functions + + void addEnergyContribution(volScalarField&) const; + + void addEnergyCoefficient(volScalarField&) const {} + + void calcEnergyContribution(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticleComp/Make/files b/src/lagrangian/cfdemParticleComp/Make/files index b119a3b3..754ba717 100644 --- a/src/lagrangian/cfdemParticleComp/Make/files +++ b/src/lagrangian/cfdemParticleComp/Make/files @@ -32,6 +32,7 @@ $(energyModels)/energyModel/energyModel.C $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C +$(energyModels)/YagiWallHT/YagiWallHT.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C From 898f4cb1f0469212890ea095dfe66d12668ed5dd Mon Sep 17 00:00:00 2001 From: s126103 Date: Thu, 12 Dec 2019 14:54:37 +0100 Subject: [PATCH 33/47] changed YagiWallHT to use temperature gradient --- .../energyModel/YagiWallHT/YagiWallHT.C | 62 +++++++++++-------- .../energyModel/YagiWallHT/YagiWallHT.H | 5 +- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 5dbb605a..9f088239 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -103,17 +103,15 @@ namespace Foam velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), U_(sm.mesh().lookupObject (velFieldName_)), UsFieldName_(propsDict_.lookup("granVelFieldName")), - Us_(sm.mesh().lookupObject (UsFieldName_)), + Us_(sm.mesh().lookupObject (UsFieldName_)), densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), rho_(sm.mesh().lookupObject (densityFieldName_)), WallTempName_(propsDict_.lookup("WallTempName")), WallTemp_(sm.mesh().lookupObject (WallTempName_)), partRe_(NULL), multiphase_(propsDict_.lookupOrDefault("multiphase",false)), - kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase kfField_(sm.mesh().lookupObject (kfFieldName_)), - CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase CpField_(sm.mesh().lookupObject (CpFieldName_)) { @@ -169,8 +167,6 @@ namespace Foam const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; #endif - - // calc La based heat flux scalar voidfraction(1); vector Ufluid(0,0,0); @@ -180,7 +176,6 @@ namespace Foam scalar muf(0); scalar magUr(0); scalar Rep(0); - scalar H(0); interpolationCellPoint voidfractionInterpolator_(voidfraction_); interpolationCellPoint UInterpolator_(U_); @@ -239,30 +234,47 @@ namespace Foam if (WallTemp_.boundaryField().types()[patchi] == "fixedValue") { - forAll(curPatch, facei) - { - label faceCelli = curPatch.faceCells()[facei]; - // calculate Urel - scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; - // calculate H - //H = 0.2087 * (pow(ReField_[faceCelli] , -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))); - H = 1; - // get delta T - //scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_.boundaryField()[patchi][facei]; - scalar deltaT = 100; - // get facei.area - scalar area = curPatch.magSf()[facei]; - scalar volume = U_.mesh().V()[faceCelli]; + if(tempField_.boundaryField().types()[patchi] == "fixedGradient") + { + fixedGradientFvPatchField& tempGradField(refCast>(tempField_.boundaryFieldRef()[patchi])); - //Info << "faceID: " << facei << " area: " << area << " volume: " << volume << endl; + forAll(curPatch, facei) + { + label faceCelli = curPatch.faceCells()[facei]; + // calculate Urel + scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; - QWallFluid_[faceCelli] = H*deltaT*area/volume; - } + // calculate H + scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); + + // get delta T + scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_.boundaryField()[patchi][facei]; + + // calculate heat flux + scalar heatFlux = H*deltaT; + scalar TGrad = -heatFlux/kfField_[faceCelli]; + tempGradField.gradient()[facei] = TGrad; + + Info << "####################" << endl; + Info << "G : " << magG << endl; + Info << "Re: " << ReField_[faceCelli] << endl; + Info << "Pr: " << PrField_[faceCelli] << endl; + Info << "Cp: " << CpField_[faceCelli] << endl; + Info << "kf: " << kfField_[faceCelli] << endl; + Info << "H : " << H << endl; + Info << "dT: " << deltaT << endl; + Info << "q': " << heatFlux << endl; + Info << "gradT: " << TGrad << endl; + } + } + else + { + FatalError << "YagiWallHT requires fixedGradient BC for temperature field" << endl; + } + } } -// h = 0.2087 * (pow(partRe_ , -0.20)) * CpField_ * magUr * rho_ / (pow(PrField_ , (2/3))); - // limit source term forAll(QWallFluid_,cellI) { diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index c535f538..40d25a9b 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -28,6 +28,7 @@ License #include "fvCFD.H" #include "cfdemCloudEnergy.H" #include "energyModel.H" +#include "fixedGradientFvPatchFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -61,7 +62,7 @@ protected: word tempFieldName_; - const volScalarField& tempField_; + volScalarField tempField_; word voidfractionFieldName_; @@ -83,7 +84,7 @@ protected: word WallTempName_; - const volScalarField& WallTemp_; // Lagrangian array + const volScalarField& WallTemp_; mutable double **partRe_; From 26b740e2968220f8ca8a19f3e83d7208867ec1ce Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 13 Dec 2019 15:48:43 +0100 Subject: [PATCH 34/47] fixed missing brackets in liggghtsCommandModel --- .../liggghtsCommandModel/liggghtsCommandModel.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C index 3011917f..c7b75f2d 100644 --- a/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C +++ b/src/lagrangian/cfdemParticle/subModels/liggghtsCommandModel/liggghtsCommandModel/liggghtsCommandModel.C @@ -146,7 +146,7 @@ void liggghtsCommandModel::checkTimeSettings(const dictionary& propsDict) // if this makes troubles try floor((startTime_+SMALL)/.. as above firstCouplingStep_ = floor((startTime_+SMALL-simStartTime)/DEMts/couplingInterval); lastCouplingStep_ = floor((endTime_+SMALL-simStartTime)/DEMts/couplingInterval); - couplingStepInterval_ = floor(timeInterval_+SMALL/DEMts/couplingInterval); + couplingStepInterval_ = floor((timeInterval_+SMALL)/DEMts/couplingInterval); } else //runEveryCouplingStep or writeStep { From 7711ea597416195d38e22632ac07eab9d890289b Mon Sep 17 00:00:00 2001 From: s126103 Date: Mon, 17 Feb 2020 13:59:59 +0100 Subject: [PATCH 35/47] debugging --- .../energyModel/YagiWallHT/YagiWallHT.C | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 9f088239..0c1d1c43 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -236,7 +236,8 @@ namespace Foam { if(tempField_.boundaryField().types()[patchi] == "fixedGradient") { - fixedGradientFvPatchField& tempGradField(refCast>(tempField_.boundaryFieldRef()[patchi])); + fixedGradientFvPatchField& tempGradPatch(refCast>(tempField_.boundaryFieldRef()[patchi])); + scalarField& tempGradField = tempGradPatch.gradient(); forAll(curPatch, facei) { @@ -248,12 +249,16 @@ namespace Foam scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); // get delta T - scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_.boundaryField()[patchi][facei]; + scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_[faceCelli]; + + Info << "Gradbefore: " << tempGradField[facei] << endl; // calculate heat flux scalar heatFlux = H*deltaT; scalar TGrad = -heatFlux/kfField_[faceCelli]; - tempGradField.gradient()[facei] = TGrad; + tempGradField[facei] = TGrad; + + Info << "Gradafter: " << tempGradField[facei] << endl; Info << "####################" << endl; Info << "G : " << magG << endl; @@ -262,10 +267,12 @@ namespace Foam Info << "Cp: " << CpField_[faceCelli] << endl; Info << "kf: " << kfField_[faceCelli] << endl; Info << "H : " << H << endl; + Info << "Twall: " << WallTemp_.boundaryField()[patchi][facei] << endl; + Info << "Tfluid: " << tempField_[faceCelli] << endl; Info << "dT: " << deltaT << endl; Info << "q': " << heatFlux << endl; Info << "gradT: " << TGrad << endl; - } + } } else { @@ -273,6 +280,7 @@ namespace Foam } } + } // limit source term From 25eef6b5e7035e6290de18d4a5d7f8a68be202f5 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 21 Feb 2020 09:44:05 +0100 Subject: [PATCH 36/47] major revamp of Yagi model --- .../energyModel/YagiWallHT/YagiWallHT.C | 202 +++++++++--------- .../energyModel/YagiWallHT/YagiWallHT.H | 17 +- 2 files changed, 111 insertions(+), 108 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 0c1d1c43..87c2e272 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -47,28 +47,29 @@ namespace Foam verbose_(propsDict_.lookupOrDefault("verbose",false)), QWallFluidName_(propsDict_.lookupOrDefault("QWallFluidName","QWallFluid")), QWallFluid_ + ( IOobject + ( + QWallFluidName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ), + wallTempName_(propsDict_.lookup("wallTempName")), + wallTemp_ ( IOobject ( - QWallFluidName_, + wallTempName_, sm.mesh().time().timeName(), sm.mesh(), IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), sm.mesh(), - dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) - ), - WallTempField_ - ( IOobject - ( - "WallTemp", - 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) // should i fix the wall temp here if its constant or fix it in BC? + dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0) ), ReField_ ( IOobject @@ -94,7 +95,6 @@ namespace Foam sm.mesh(), dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) ), - tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), tempField_(sm.mesh().lookupObject (tempFieldName_)), voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), @@ -106,8 +106,6 @@ namespace Foam Us_(sm.mesh().lookupObject (UsFieldName_)), densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), rho_(sm.mesh().lookupObject (densityFieldName_)), - WallTempName_(propsDict_.lookup("WallTempName")), - WallTemp_(sm.mesh().lookupObject (WallTempName_)), partRe_(NULL), multiphase_(propsDict_.lookupOrDefault("multiphase",false)), kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase @@ -119,8 +117,8 @@ namespace Foam if (propsDict_.found("maxSource")) { - maxSource_=readScalar(propsDict_.lookup ("maxSource")); - Info << "limiting eulerian source field to: " << maxSource_ << endl; + maxSource_=readScalar(propsDict_.lookup ("maxSource")); + Info << "limiting wall source field to: " << maxSource_ << endl; } if (verbose_) @@ -130,6 +128,14 @@ namespace Foam ReField_.write(); PrField_.write(); } + + // currently it is detected if field was auto generated or defined + // improvement would be changing the type here automatically + forAll(wallTemp_.boundaryField(),patchI) + if(wallTemp_.boundaryField()[patchI].type()=="calculated") + FatalError <<"Scalar field:"<< wallTemp_.name() << " must be defined.\n" << abort(FatalError); + + wallTemp_.writeOpt() = IOobject::AUTO_WRITE; } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // @@ -157,35 +163,28 @@ namespace Foam { allocateMyArrays(); + // reset Scalar field QWallFluid_.primitiveFieldRef() = 0.0; - - #ifdef compre const volScalarField mufField = particleCloud_.turbulence().mu(); #else const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; #endif - // calc La based heat flux - scalar voidfraction(1); - vector Ufluid(0,0,0); - label cellI=0; - vector Us(0,0,0); - scalar ds(0); - scalar muf(0); - scalar magUr(0); - scalar Rep(0); - interpolationCellPoint voidfractionInterpolator_(voidfraction_); interpolationCellPoint UInterpolator_(U_); interpolationCellPoint TInterpolator_(tempField_); + // calculate Rep for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) { - cellI = particleCloud_.cellIDs()[index][0]; + label cellI = particleCloud_.cellIDs()[index][0]; if(cellI >= 0) { + scalar voidfraction; + vector Ufluid; + if(interpolation_) { vector position = particleCloud_.position(index); @@ -199,14 +198,14 @@ namespace Foam } if (voidfraction < 0.01) - voidfraction = 0.01; + voidfraction = 0.01; - Us = particleCloud_.velocity(index); - magUr = mag(Ufluid - Us); - ds = 2.*particleCloud_.radius(index); - muf = mufField[cellI]; + vector Us = particleCloud_.velocity(index); + scalar magUr = mag(Ufluid - Us); + scalar ds = 2.*particleCloud_.radius(index); + scalar muf = mufField[cellI]; - Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; + scalar Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; partRe_[index][0] = Rep; } } @@ -224,87 +223,94 @@ namespace Foam // calculate Pr field PrField_ = CpField_ * mufField / kfField_; - // mass_flow_rate = magUr * rho_[cellI]; const fvPatchList& patches = U_.mesh().boundary(); - forAll(patches, patchi) + // calculate flux + forAll(patches, patchi) + { + const fvPatch& curPatch = patches[patchi]; + + if (wallTemp_.boundaryField().types()[patchi] == "fixedValue") + { + if(tempField_.boundaryField().types()[patchi] == "zeroGradient") { - const fvPatch& curPatch = patches[patchi]; + + //fixedGradientFvPatchField& tempGradPatch(refCast>(tempField_.boundaryFieldRef()[patchi])); + //scalarField& tempGradField = tempGradPatch.gradient(); - if (WallTemp_.boundaryField().types()[patchi] == "fixedValue") + forAll(curPatch, facei) + { + label faceCelli = curPatch.faceCells()[facei]; + // calculate Urel + scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; + + // calculate H + scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); + + // get delta T (wall-fluid) + scalar deltaT = wallTemp_.boundaryField()[patchi][facei] - tempField_[faceCelli]; + + //Info << "Gradbefore: " << tempGradField[facei] << endl; + + // calculate heat flux + scalar heatFlux = H*deltaT; + scalar area = curPatch.magSf()[facei]; + QWallFluid_[faceCelli] += heatFlux * area; + //scalar TGrad = -heatFlux/kfField_[faceCelli]; + //tempGradField[facei] = TGrad; + + //Info << "Gradafter: " << tempGradField[facei] << endl; + + if(particleCloud_.verbose() && facei >=0 && facei <2) { - if(tempField_.boundaryField().types()[patchi] == "fixedGradient") - { - fixedGradientFvPatchField& tempGradPatch(refCast>(tempField_.boundaryFieldRef()[patchi])); - scalarField& tempGradField = tempGradPatch.gradient(); - - forAll(curPatch, facei) - { - label faceCelli = curPatch.faceCells()[facei]; - // calculate Urel - scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; - - // calculate H - scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); - - // get delta T - scalar deltaT = WallTemp_.boundaryField()[patchi][facei] - tempField_[faceCelli]; - - Info << "Gradbefore: " << tempGradField[facei] << endl; - - // calculate heat flux - scalar heatFlux = H*deltaT; - scalar TGrad = -heatFlux/kfField_[faceCelli]; - tempGradField[facei] = TGrad; - - Info << "Gradafter: " << tempGradField[facei] << endl; - - Info << "####################" << endl; - Info << "G : " << magG << endl; - Info << "Re: " << ReField_[faceCelli] << endl; - Info << "Pr: " << PrField_[faceCelli] << endl; - Info << "Cp: " << CpField_[faceCelli] << endl; - Info << "kf: " << kfField_[faceCelli] << endl; - Info << "H : " << H << endl; - Info << "Twall: " << WallTemp_.boundaryField()[patchi][facei] << endl; - Info << "Tfluid: " << tempField_[faceCelli] << endl; - Info << "dT: " << deltaT << endl; - Info << "q': " << heatFlux << endl; - Info << "gradT: " << TGrad << endl; - } - } - else - { - FatalError << "YagiWallHT requires fixedGradient BC for temperature field" << endl; - } - + Info << "####################" << endl; + Info << "cellID: " << faceCelli << endl; + Info << "G : " << magG << endl; + Info << "Re: " << ReField_[faceCelli] << endl; + Info << "Pr: " << PrField_[faceCelli] << endl; + Info << "Cp: " << CpField_[faceCelli] << endl; + Info << "kf: " << kfField_[faceCelli] << endl; + Info << "H : " << H << endl; + Info << "Twall: " << wallTemp_.boundaryField()[patchi][facei] << endl; + Info << "Tfluid: " << tempField_[faceCelli] << endl; + Info << "dT: " << deltaT << endl; + Info << "q: " << heatFlux << endl; + Info << "area: " << area << endl; + Info << "Q:" << QWallFluid_[faceCelli] << endl; + //Info << "gradT: " << TGrad << endl; } - + } } + else + { + FatalError << "YagiWallHT requires zeroGradient BC for temperature field" << endl; + } + } + } + + QWallFluid_.primitiveFieldRef() /= QWallFluid_.mesh().V(); // limit source term forAll(QWallFluid_,cellI) { - scalar EuFieldInCell = QWallFluid_[cellI]; + scalar EuFieldInCell = QWallFluid_[cellI]; - if(mag(EuFieldInCell) > maxSource_ ) - { - Pout << "limiting source term\n" << endl ; - QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; - } + if(mag(EuFieldInCell) > maxSource_ ) + { + Pout << "limiting source term\n" << endl ; + QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; + } } QWallFluid_.correctBoundaryConditions(); - } void YagiWallHT::addEnergyContribution(volScalarField& Qsource) const - { +{ Qsource += QWallFluid_; - } - +} // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index 40d25a9b..45ccdaa4 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -28,7 +28,6 @@ License #include "fvCFD.H" #include "cfdemCloudEnergy.H" #include "energyModel.H" -#include "fixedGradientFvPatchFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -51,10 +50,12 @@ protected: bool verbose_; word QWallFluidName_; - + volScalarField QWallFluid_; - volScalarField WallTempField_; + word wallTempName_; + + volScalarField wallTemp_; volScalarField ReField_; @@ -62,13 +63,13 @@ protected: word tempFieldName_; - volScalarField tempField_; + const volScalarField& tempField_; word voidfractionFieldName_; const volScalarField& voidfraction_; - scalar maxSource_; + scalar maxSource_; // max (limited) value of src field word velFieldName_; @@ -82,10 +83,6 @@ protected: const volScalarField& rho_; - word WallTempName_; - - const volScalarField& WallTemp_; - mutable double **partRe_; bool multiphase_; @@ -123,7 +120,7 @@ public: // Member Functions - void addEnergyContribution(volScalarField&) const; + void addEnergyContribution(volScalarField&) const; void addEnergyCoefficient(volScalarField&) const {} From f056bc66ad128095f23f6cd830278b998c36ae23 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 26 Feb 2020 10:58:12 +0100 Subject: [PATCH 37/47] fix verbose --- .../subModels/energyModel/YagiWallHT/YagiWallHT.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 87c2e272..c320a1c7 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -262,7 +262,7 @@ namespace Foam //Info << "Gradafter: " << tempGradField[facei] << endl; - if(particleCloud_.verbose() && facei >=0 && facei <2) + if(verbose_ && facei >=0 && facei <2) { Info << "####################" << endl; Info << "cellID: " << faceCelli << endl; @@ -298,7 +298,7 @@ namespace Foam if(mag(EuFieldInCell) > maxSource_ ) { - Pout << "limiting source term\n" << endl ; + Pout << "limiting source term" << endl ; QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; } } From 4996b8b5efb797c1e69d878b59287fe8232aff33 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 26 Feb 2020 15:30:54 +0100 Subject: [PATCH 38/47] updated literature ref --- .../subModels/energyModel/YagiWallHT/YagiWallHT.H | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index 45ccdaa4..58db5dcf 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -17,8 +17,8 @@ License Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria Description - Correlation for Nusselt number according to - Gunn, D. J. International Journal of Heat and Mass Transfer 21.4 (1978) + Correlation for wall-to-bed heat transfer according to + Yagi, S. A.I.Ch.E. Journal 5.1 (1959) \*---------------------------------------------------------------------------*/ From ab250deb8d9a425d6215fa7714f764b163955322 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 26 Feb 2020 15:39:36 +0100 Subject: [PATCH 39/47] doc update --- .../cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index 58db5dcf..f819360a 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -34,7 +34,7 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class heatTransferGunn Declaration + Class YagiWallHT Declaration \*---------------------------------------------------------------------------*/ class YagiWallHT From a886e439ecc4ed2743a5466713e871fb6130d1f7 Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 26 Feb 2020 15:58:01 +0100 Subject: [PATCH 40/47] initial commit for YagiWallHTImplicit --- src/lagrangian/cfdemParticle/Make/files | 1 + .../YagiWallHTImplicit/YagiWallHTImplicit.C | 161 ++++++++++++++++++ .../YagiWallHTImplicit/YagiWallHTImplicit.H | 99 +++++++++++ src/lagrangian/cfdemParticleComp/Make/files | 1 + 4 files changed, 262 insertions(+) create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H diff --git a/src/lagrangian/cfdemParticle/Make/files b/src/lagrangian/cfdemParticle/Make/files index 6c74a362..c3ec28be 100644 --- a/src/lagrangian/cfdemParticle/Make/files +++ b/src/lagrangian/cfdemParticle/Make/files @@ -34,6 +34,7 @@ $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C $(energyModels)/YagiWallHT/YagiWallHT.C +$(energyModels)/YagiWallHTImplicit/YagiWallHTImplicit.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C new file mode 100644 index 00000000..931e3deb --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C @@ -0,0 +1,161 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "YagiWallHTImplicit.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(YagiWallHTImplicit, 0); + +addToRunTimeSelectionTable(energyModel, YagiWallHTImplicit, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +YagiWallHTImplicit::YagiWallHTImplicit +( + const dictionary& dict, + cfdemCloudEnergy& sm +) +: + YagiWallHT(dict,sm), + QPartFluidCoeffName_(propsDict_.lookupOrDefault("QPartFluidCoeffName","QPartFluidCoeff")), + QPartFluidCoeff_ + ( IOobject + ( + QPartFluidCoeffName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) + ), + partHeatFluxCoeff_(NULL) +{ + allocateMyArrays(); + + // no limiting necessary for implicit heat transfer + maxSource_ = 1e30; +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +YagiWallHTImplicit::~YagiWallHTImplicit() +{ + particleCloud_.dataExchangeM().destroy(partHeatFluxCoeff_,1); +} + +// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // +void YagiWallHTImplicit::allocateMyArrays() const +{ +// YagiWallHT::allocateMyArrays(); + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partHeatFluxCoeff_,initVal,1); +} +// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + +void YagiWallHTImplicit::calcEnergyContribution() +{ + allocateMyArrays(); + + YagiWallHT::calcEnergyContribution(); + + QPartFluidCoeff_.primitiveFieldRef() = 0.0; + + particleCloud_.averagingM().setScalarSum + ( + QPartFluidCoeff_, + partHeatFluxCoeff_, + particleCloud_.particleWeights(), + NULL + ); + + QPartFluidCoeff_.primitiveFieldRef() /= -QPartFluidCoeff_.mesh().V(); + +// QPartFluidCoeff_.correctBoundaryConditions(); + +} + +void YagiWallHTImplicit::addEnergyCoefficient(volScalarField& Qsource) const +{ + Qsource += QPartFluidCoeff_; +} + +void YagiWallHTImplicit::heatFlux(label index, scalar h, scalar As, scalar Tfluid) +{ + partHeatFlux_[index][0] = -h * As * partTemp_[index][0]; +} + +void YagiWallHTImplicit::heatFluxCoeff(label index, scalar h, scalar As) +{ + partHeatFluxCoeff_[index][0] = h * As; +} + +void YagiWallHTImplicit::giveData(int call) +{ + if(call == 1) + { + //Info << "total convective particle-fluid heat flux [W] (Eulerian) = " << gSum(QPartFluid_*1.0*QPartFluid_.mesh().V()) << endl; + + particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_); + } +} + +void YagiWallHTImplicit::postFlow() +{ + label cellI; + scalar Tfluid(0.0); + scalar Tpart(0.0); + interpolationCellPoint TInterpolator_(tempField_); + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + if(interpolation_) + { + vector position = particleCloud_.position(index); + Tfluid = TInterpolator_.interpolate(position,cellI); + } + else + Tfluid = tempField_[cellI]; + + Tpart = partTemp_[index][0]; + partHeatFlux_[index][0] = (Tfluid - Tpart) * partHeatFluxCoeff_[index][0]; + } + } + + giveData(1); +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H new file mode 100644 index 00000000..ea31d4fd --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + + Description + Correlation for wall-to-bed heat transfer according to + Yagi, S. A.I.Ch.E. Journal 5.1 (1959) + +\*---------------------------------------------------------------------------*/ + +#ifndef YagiWallHTImplicit_H +#define YagiWallHTImplicit_H + +#include "fvCFD.H" +#include "cfdemCloudEnergy.H" +#include "YagiWallHT.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class YagiWallHTImplicit Declaration +\*---------------------------------------------------------------------------*/ + +class YagiWallHTImplicit +: + public YagiWallHT +{ +private: + + word QPartFluidCoeffName_; + + volScalarField QPartFluidCoeff_; + + mutable double **partHeatFluxCoeff_; // Lagrangian array + + void allocateMyArrays() const; + + void giveData(int); + + void heatFlux(label, scalar, scalar, scalar); + + void heatFluxCoeff(label, scalar, scalar); + +public: + + //- Runtime type information + TypeName("YagiWallHTImplicit"); + + // Constructors + + //- Construct from components + YagiWallHTImplicit + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ); + + + // Destructor + + virtual ~YagiWallHTImplicit(); + + + // Member Functions + + void addEnergyCoefficient(volScalarField&) const; + + void calcEnergyContribution(); + + void postFlow(); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticleComp/Make/files b/src/lagrangian/cfdemParticleComp/Make/files index cdf12f6b..17a7f1bf 100644 --- a/src/lagrangian/cfdemParticleComp/Make/files +++ b/src/lagrangian/cfdemParticleComp/Make/files @@ -33,6 +33,7 @@ $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C $(energyModels)/YagiWallHT/YagiWallHT.C +$(energyModels)/YagiWallHTImplicit/YagiWallHTImplicit.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C From bedf3e37c9116d775e672f3c0b30f6e93caac75d Mon Sep 17 00:00:00 2001 From: s126103 Date: Wed, 26 Feb 2020 16:20:24 +0100 Subject: [PATCH 41/47] created YagiWallHTImplicit --- .../energyModel/YagiWallHT/YagiWallHT.C | 36 +++++++--- .../energyModel/YagiWallHT/YagiWallHT.H | 3 + .../YagiWallHTImplicit/YagiWallHTImplicit.C | 69 ++++--------------- .../YagiWallHTImplicit/YagiWallHTImplicit.H | 14 ++-- 4 files changed, 47 insertions(+), 75 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index c320a1c7..707cd69a 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -242,6 +242,7 @@ namespace Foam forAll(curPatch, facei) { label faceCelli = curPatch.faceCells()[facei]; + // calculate Urel scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; @@ -249,14 +250,19 @@ namespace Foam scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); // get delta T (wall-fluid) - scalar deltaT = wallTemp_.boundaryField()[patchi][facei] - tempField_[faceCelli]; + scalar Twall = wallTemp_.boundaryField()[patchi][facei]; + scalar Tfluid = tempField_[faceCelli]; + scalar deltaT = Twall - Tfluid; //Info << "Gradbefore: " << tempGradField[facei] << endl; - // calculate heat flux - scalar heatFlux = H*deltaT; + // get area scalar area = curPatch.magSf()[facei]; - QWallFluid_[faceCelli] += heatFlux * area; + + // calculate heat flux + heatFlux(faceCelli, H, area, Twall, Tfluid); + heatFluxCoeff(faceCelli, H, area); + //scalar TGrad = -heatFlux/kfField_[faceCelli]; //tempGradField[facei] = TGrad; @@ -272,12 +278,12 @@ namespace Foam Info << "Cp: " << CpField_[faceCelli] << endl; Info << "kf: " << kfField_[faceCelli] << endl; Info << "H : " << H << endl; - Info << "Twall: " << wallTemp_.boundaryField()[patchi][facei] << endl; - Info << "Tfluid: " << tempField_[faceCelli] << endl; + Info << "Twall: " << Twall << endl; + Info << "Tfluid: " << Tfluid << endl; Info << "dT: " << deltaT << endl; - Info << "q: " << heatFlux << endl; + Info << "q: " << H*deltaT << endl; Info << "area: " << area << endl; - Info << "Q:" << QWallFluid_[faceCelli] << endl; + Info << "Q:" << H*deltaT*area << endl; //Info << "gradT: " << TGrad << endl; } } @@ -308,9 +314,19 @@ namespace Foam } void YagiWallHT::addEnergyContribution(volScalarField& Qsource) const -{ + { Qsource += QWallFluid_; -} + } + + void YagiWallHT::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) + { + QWallFluid_[faceCelli] += H * area * (Twall - Tfluid); + } + + void YagiWallHT::heatFluxCoeff(label faceCelli, scalar H, scalar area) + { + //no heat transfer coefficient in explicit model + } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index f819360a..3d88eaaa 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -97,6 +97,9 @@ protected: void allocateMyArrays() const; + virtual void heatFlux(label, scalar, scalar, scalar, scalar); + + virtual void heatFluxCoeff(label, scalar, scalar); public: diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C index 931e3deb..cf2936db 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C @@ -42,11 +42,11 @@ YagiWallHTImplicit::YagiWallHTImplicit ) : YagiWallHT(dict,sm), - QPartFluidCoeffName_(propsDict_.lookupOrDefault("QPartFluidCoeffName","QPartFluidCoeff")), - QPartFluidCoeff_ + QWallFluidCoeffName_(propsDict_.lookupOrDefault("QWallFluidCoeffName","QWallFluidCoeff")), + QWallFluidCoeff_ ( IOobject ( - QPartFluidCoeffName_, + QWallFluidCoeffName_, sm.mesh().time().timeName(), sm.mesh(), IOobject::READ_IF_PRESENT, @@ -84,76 +84,31 @@ void YagiWallHTImplicit::calcEnergyContribution() { allocateMyArrays(); + QWallFluidCoeff_.primitiveFieldRef() = 0.0; + YagiWallHT::calcEnergyContribution(); - QPartFluidCoeff_.primitiveFieldRef() = 0.0; + QWallFluidCoeff_.primitiveFieldRef() /= -QWallFluidCoeff_.mesh().V(); - particleCloud_.averagingM().setScalarSum - ( - QPartFluidCoeff_, - partHeatFluxCoeff_, - particleCloud_.particleWeights(), - NULL - ); - - QPartFluidCoeff_.primitiveFieldRef() /= -QPartFluidCoeff_.mesh().V(); - -// QPartFluidCoeff_.correctBoundaryConditions(); +// QWallFluidCoeff_.correctBoundaryConditions(); } void YagiWallHTImplicit::addEnergyCoefficient(volScalarField& Qsource) const { - Qsource += QPartFluidCoeff_; + Qsource += QWallFluidCoeff_; } -void YagiWallHTImplicit::heatFlux(label index, scalar h, scalar As, scalar Tfluid) +void YagiWallHTImplicit::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) { - partHeatFlux_[index][0] = -h * As * partTemp_[index][0]; + QWallFluid_[faceCelli] += H * area * Twall; } -void YagiWallHTImplicit::heatFluxCoeff(label index, scalar h, scalar As) +void YagiWallHTImplicit::heatFluxCoeff(label faceCelli, scalar H, scalar area) { - partHeatFluxCoeff_[index][0] = h * As; + QWallFluidCoeff_[faceCelli] -= H * area; } -void YagiWallHTImplicit::giveData(int call) -{ - if(call == 1) - { - //Info << "total convective particle-fluid heat flux [W] (Eulerian) = " << gSum(QPartFluid_*1.0*QPartFluid_.mesh().V()) << endl; - - particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_); - } -} - -void YagiWallHTImplicit::postFlow() -{ - label cellI; - scalar Tfluid(0.0); - scalar Tpart(0.0); - interpolationCellPoint TInterpolator_(tempField_); - - for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) - { - cellI = particleCloud_.cellIDs()[index][0]; - if(cellI >= 0) - { - if(interpolation_) - { - vector position = particleCloud_.position(index); - Tfluid = TInterpolator_.interpolate(position,cellI); - } - else - Tfluid = tempField_[cellI]; - - Tpart = partTemp_[index][0]; - partHeatFlux_[index][0] = (Tfluid - Tpart) * partHeatFluxCoeff_[index][0]; - } - } - - giveData(1); -} // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H index ea31d4fd..8b5cb12b 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H @@ -43,19 +43,17 @@ class YagiWallHTImplicit { private: - word QPartFluidCoeffName_; + word QWallFluidCoeffName_; - volScalarField QPartFluidCoeff_; + volScalarField QWallFluidCoeff_; mutable double **partHeatFluxCoeff_; // Lagrangian array void allocateMyArrays() const; - - void giveData(int); - - void heatFlux(label, scalar, scalar, scalar); - - void heatFluxCoeff(label, scalar, scalar); + + virtual void heatFlux(label, scalar, scalar, scalar, scalar); + + virtual void heatFluxCoeff(label, scalar, scalar); public: From 73e6b03778d653c80e2b66c4b2b15a75cc2655c8 Mon Sep 17 00:00:00 2001 From: s126103 Date: Thu, 27 Feb 2020 12:16:47 +0100 Subject: [PATCH 42/47] cleanup and fix --- .../subModels/energyModel/YagiWallHT/YagiWallHT.C | 13 +------------ .../YagiWallHTImplicit/YagiWallHTImplicit.C | 2 +- .../YagiWallHTImplicit/YagiWallHTImplicit.H | 2 -- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 707cd69a..949e7493 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -235,9 +235,6 @@ namespace Foam { if(tempField_.boundaryField().types()[patchi] == "zeroGradient") { - - //fixedGradientFvPatchField& tempGradPatch(refCast>(tempField_.boundaryFieldRef()[patchi])); - //scalarField& tempGradField = tempGradPatch.gradient(); forAll(curPatch, facei) { @@ -247,26 +244,19 @@ namespace Foam scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; // calculate H - scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL, -0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli] , (2/3))+SMALL); + scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); // get delta T (wall-fluid) scalar Twall = wallTemp_.boundaryField()[patchi][facei]; scalar Tfluid = tempField_[faceCelli]; scalar deltaT = Twall - Tfluid; - //Info << "Gradbefore: " << tempGradField[facei] << endl; - // get area scalar area = curPatch.magSf()[facei]; // calculate heat flux heatFlux(faceCelli, H, area, Twall, Tfluid); heatFluxCoeff(faceCelli, H, area); - - //scalar TGrad = -heatFlux/kfField_[faceCelli]; - //tempGradField[facei] = TGrad; - - //Info << "Gradafter: " << tempGradField[facei] << endl; if(verbose_ && facei >=0 && facei <2) { @@ -284,7 +274,6 @@ namespace Foam Info << "q: " << H*deltaT << endl; Info << "area: " << area << endl; Info << "Q:" << H*deltaT*area << endl; - //Info << "gradT: " << TGrad << endl; } } } diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C index cf2936db..918c0266 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C @@ -88,7 +88,7 @@ void YagiWallHTImplicit::calcEnergyContribution() YagiWallHT::calcEnergyContribution(); - QWallFluidCoeff_.primitiveFieldRef() /= -QWallFluidCoeff_.mesh().V(); + QWallFluidCoeff_.primitiveFieldRef() /= QWallFluidCoeff_.mesh().V(); // QWallFluidCoeff_.correctBoundaryConditions(); diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H index 8b5cb12b..2d4403be 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H @@ -80,8 +80,6 @@ public: void addEnergyCoefficient(volScalarField&) const; void calcEnergyContribution(); - - void postFlow(); }; From 6075578f1b0948eb94b5612d2ed045909b05c85b Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 28 Feb 2020 09:59:08 +0100 Subject: [PATCH 43/47] added voidfractionMax option --- .../subModels/energyModel/YagiWallHT/YagiWallHT.C | 7 ++++++- .../subModels/energyModel/YagiWallHT/YagiWallHT.H | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 949e7493..349ed598 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -99,6 +99,7 @@ namespace Foam tempField_(sm.mesh().lookupObject (tempFieldName_)), voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + voidfractionMax_(readScalar(propsDict_.lookup("voidfractionMax"))), maxSource_(1e30), velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), U_(sm.mesh().lookupObject (velFieldName_)), @@ -244,7 +245,11 @@ namespace Foam scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; // calculate H - scalar H = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); + scalar H; + if (voidfraction_[faceCelli]<=voidfractionMax_) + H = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); + else + H = 0; // get delta T (wall-fluid) scalar Twall = wallTemp_.boundaryField()[patchi][facei]; diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H index 3d88eaaa..528e9ef0 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H @@ -69,6 +69,8 @@ protected: const volScalarField& voidfraction_; + scalar voidfractionMax_; + scalar maxSource_; // max (limited) value of src field word velFieldName_; From fe3fbe58d9242a80443555372f3607a169fdda2b Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 28 Feb 2020 10:32:29 +0100 Subject: [PATCH 44/47] Yagi rename --- src/lagrangian/cfdemParticle/Make/files | 4 +- .../energyModel/YagiWallHT/YagiWallHT.C | 60 ++-- .../YagiWallHTImplicit/YagiWallHTImplicit.C | 30 +- .../wallHeatTransferYagi.C | 329 ++++++++++++++++++ .../wallHeatTransferYagi.H} | 14 +- .../wallHeatTransferYagiImplicit.C | 116 ++++++ .../wallHeatTransferYagiImplicit.H} | 18 +- src/lagrangian/cfdemParticleComp/Make/files | 4 +- 8 files changed, 509 insertions(+), 66 deletions(-) create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.C rename src/lagrangian/cfdemParticle/subModels/energyModel/{YagiWallHT/YagiWallHT.H => wallHeatTransferYagi/wallHeatTransferYagi.H} (92%) create mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C rename src/lagrangian/cfdemParticle/subModels/energyModel/{YagiWallHTImplicit/YagiWallHTImplicit.H => wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.H} (85%) diff --git a/src/lagrangian/cfdemParticle/Make/files b/src/lagrangian/cfdemParticle/Make/files index c3ec28be..bfcc0fba 100644 --- a/src/lagrangian/cfdemParticle/Make/files +++ b/src/lagrangian/cfdemParticle/Make/files @@ -33,8 +33,8 @@ $(energyModels)/energyModel/energyModel.C $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C -$(energyModels)/YagiWallHT/YagiWallHT.C -$(energyModels)/YagiWallHTImplicit/YagiWallHTImplicit.C +$(energyModels)/wallHeatTransferYagi/wallHeatTransferYagi.C +$(energyModels)/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C index 349ed598..264ab29d 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C @@ -19,7 +19,7 @@ Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria \*---------------------------------------------------------------------------*/ #include "error.H" -#include "YagiWallHT.H" +#include "wallHeatTransferYagi.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -28,14 +28,14 @@ namespace Foam // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - defineTypeNameAndDebug(YagiWallHT, 0); + defineTypeNameAndDebug(wallHeatTransferYagi, 0); - addToRunTimeSelectionTable(energyModel, YagiWallHT, dictionary); + addToRunTimeSelectionTable(energyModel, wallHeatTransferYagi, dictionary); // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - YagiWallHT::YagiWallHT + wallHeatTransferYagi::wallHeatTransferYagi ( const dictionary& dict, cfdemCloudEnergy& sm @@ -141,13 +141,13 @@ namespace Foam // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - YagiWallHT::~YagiWallHT() + wallHeatTransferYagi::~wallHeatTransferYagi() { particleCloud_.dataExchangeM().destroy(partRe_,1); } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // - void YagiWallHT::allocateMyArrays() const + void wallHeatTransferYagi::allocateMyArrays() const { // get memory for 2d arrays double initVal=0.0; @@ -160,7 +160,7 @@ namespace Foam // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // - void YagiWallHT::calcEnergyContribution() + void wallHeatTransferYagi::calcEnergyContribution() { allocateMyArrays(); @@ -244,12 +244,12 @@ namespace Foam // calculate Urel scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; - // calculate H - scalar H; + // calculate h + scalar h; if (voidfraction_[faceCelli]<=voidfractionMax_) - H = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); + h = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); else - H = 0; + h = 0; // get delta T (wall-fluid) scalar Twall = wallTemp_.boundaryField()[patchi][facei]; @@ -260,31 +260,29 @@ namespace Foam scalar area = curPatch.magSf()[facei]; // calculate heat flux - heatFlux(faceCelli, H, area, Twall, Tfluid); - heatFluxCoeff(faceCelli, H, area); + heatFlux(faceCelli, h, area, Twall, Tfluid); + heatFluxCoeff(faceCelli, h, area); if(verbose_ && facei >=0 && facei <2) { Info << "####################" << endl; - Info << "cellID: " << faceCelli << endl; - Info << "G : " << magG << endl; - Info << "Re: " << ReField_[faceCelli] << endl; - Info << "Pr: " << PrField_[faceCelli] << endl; - Info << "Cp: " << CpField_[faceCelli] << endl; - Info << "kf: " << kfField_[faceCelli] << endl; - Info << "H : " << H << endl; - Info << "Twall: " << Twall << endl; - Info << "Tfluid: " << Tfluid << endl; - Info << "dT: " << deltaT << endl; - Info << "q: " << H*deltaT << endl; - Info << "area: " << area << endl; - Info << "Q:" << H*deltaT*area << endl; + Info << "cellID [-] : " << faceCelli << endl; + Info << "G [kg/(m2s)] : " << magG << endl; + Info << "Re [-] : " << ReField_[faceCelli] << endl; + Info << "Pr [-] : " << PrField_[faceCelli] << endl; + Info << "Cp [J/(kgK)] : " << CpField_[faceCelli] << endl; + Info << "kf [J/(msK)] : " << kfField_[faceCelli] << endl; + Info << "h [J/(m2Ks)] : " << h << endl; + Info << "Twall [K] : " << Twall << endl; + Info << "Tfluid [K] : " << Tfluid << endl; + Info << "area [m2] : " << area << endl; + Info << "Q [J/s] : " << H*deltaT*area << endl; } } } else { - FatalError << "YagiWallHT requires zeroGradient BC for temperature field" << endl; + FatalError << "wallHeatTransferYagi requires zeroGradient BC for temperature field" << endl; } } } @@ -307,17 +305,17 @@ namespace Foam } - void YagiWallHT::addEnergyContribution(volScalarField& Qsource) const + void wallHeatTransferYagi::addEnergyContribution(volScalarField& Qsource) const { Qsource += QWallFluid_; } - void YagiWallHT::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) + void wallHeatTransferYagi::heatFlux(label faceCelli, scalar h, scalar area, scalar Twall, scalar Tfluid) { - QWallFluid_[faceCelli] += H * area * (Twall - Tfluid); + QWallFluid_[faceCelli] += h * area * (Twall - Tfluid); } - void YagiWallHT::heatFluxCoeff(label faceCelli, scalar H, scalar area) + void wallHeatTransferYagi::heatFluxCoeff(label faceCelli, scalar h, scalar area) { //no heat transfer coefficient in explicit model } diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C index 918c0266..e92630e2 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C @@ -19,7 +19,7 @@ License \*---------------------------------------------------------------------------*/ #include "error.H" -#include "YagiWallHTImplicit.H" +#include "wallHeatTransferYagiImplicit.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -28,20 +28,20 @@ namespace Foam // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -defineTypeNameAndDebug(YagiWallHTImplicit, 0); +defineTypeNameAndDebug(wallHeatTransferYagiImplicit, 0); -addToRunTimeSelectionTable(energyModel, YagiWallHTImplicit, dictionary); +addToRunTimeSelectionTable(energyModel, wallHeatTransferYagiImplicit, dictionary); // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Construct from components -YagiWallHTImplicit::YagiWallHTImplicit +wallHeatTransferYagiImplicit::wallHeatTransferYagiImplicit ( const dictionary& dict, cfdemCloudEnergy& sm ) : - YagiWallHT(dict,sm), + wallHeatTransferYagi(dict,sm), QWallFluidCoeffName_(propsDict_.lookupOrDefault("QWallFluidCoeffName","QWallFluidCoeff")), QWallFluidCoeff_ ( IOobject @@ -66,27 +66,27 @@ YagiWallHTImplicit::YagiWallHTImplicit // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // -YagiWallHTImplicit::~YagiWallHTImplicit() +wallHeatTransferYagiImplicit::~wallHeatTransferYagiImplicit() { particleCloud_.dataExchangeM().destroy(partHeatFluxCoeff_,1); } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // -void YagiWallHTImplicit::allocateMyArrays() const +void wallHeatTransferYagiImplicit::allocateMyArrays() const { -// YagiWallHT::allocateMyArrays(); +// wallHeatTransferYagi::allocateMyArrays(); double initVal=0.0; particleCloud_.dataExchangeM().allocateArray(partHeatFluxCoeff_,initVal,1); } // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // -void YagiWallHTImplicit::calcEnergyContribution() +void wallHeatTransferYagiImplicit::calcEnergyContribution() { allocateMyArrays(); QWallFluidCoeff_.primitiveFieldRef() = 0.0; - YagiWallHT::calcEnergyContribution(); + wallHeatTransferYagi::calcEnergyContribution(); QWallFluidCoeff_.primitiveFieldRef() /= QWallFluidCoeff_.mesh().V(); @@ -94,19 +94,19 @@ void YagiWallHTImplicit::calcEnergyContribution() } -void YagiWallHTImplicit::addEnergyCoefficient(volScalarField& Qsource) const +void wallHeatTransferYagiImplicit::addEnergyCoefficient(volScalarField& Qsource) const { Qsource += QWallFluidCoeff_; } -void YagiWallHTImplicit::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) +void wallHeatTransferYagiImplicit::heatFlux(label faceCelli, scalar h, scalar area, scalar Twall, scalar Tfluid) { - QWallFluid_[faceCelli] += H * area * Twall; + QWallFluid_[faceCelli] += h * area * Twall; } -void YagiWallHTImplicit::heatFluxCoeff(label faceCelli, scalar H, scalar area) +void wallHeatTransferYagiImplicit::heatFluxCoeff(label faceCelli, scalar h, scalar area) { - QWallFluidCoeff_[faceCelli] -= H * area; + QWallFluidCoeff_[faceCelli] -= h * area; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.C b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.C new file mode 100644 index 00000000..b7c93ee4 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.C @@ -0,0 +1,329 @@ +/*---------------------------------------------------------------------------*\ +License + +This 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. + +This code 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 this code. If not, see . + +Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "wallHeatTransferYagi.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + + defineTypeNameAndDebug(wallHeatTransferYagi, 0); + + addToRunTimeSelectionTable(energyModel, wallHeatTransferYagi, dictionary); + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + + wallHeatTransferYagi::wallHeatTransferYagi + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ) + : + energyModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + interpolation_(propsDict_.lookupOrDefault("interpolation",false)), + verbose_(propsDict_.lookupOrDefault("verbose",false)), + QWallFluidName_(propsDict_.lookupOrDefault("QWallFluidName","QWallFluid")), + QWallFluid_ + ( IOobject + ( + QWallFluidName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ), + wallTempName_(propsDict_.lookup("wallTempName")), + wallTemp_ + ( IOobject + ( + wallTempName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0) + ), + ReField_ + ( IOobject + ( + "ReField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + PrField_ + ( IOobject + ( + "PrField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), + tempField_(sm.mesh().lookupObject (tempFieldName_)), + voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + voidfractionMax_(readScalar(propsDict_.lookup("voidfractionMax"))), + maxSource_(1e30), + velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), + U_(sm.mesh().lookupObject (velFieldName_)), + UsFieldName_(propsDict_.lookup("granVelFieldName")), + Us_(sm.mesh().lookupObject (UsFieldName_)), + densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), + rho_(sm.mesh().lookupObject (densityFieldName_)), + partRe_(NULL), + multiphase_(propsDict_.lookupOrDefault("multiphase",false)), + kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + kfField_(sm.mesh().lookupObject (kfFieldName_)), + CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase + CpField_(sm.mesh().lookupObject (CpFieldName_)) + { + allocateMyArrays(); + + if (propsDict_.found("maxSource")) + { + maxSource_=readScalar(propsDict_.lookup ("maxSource")); + Info << "limiting wall source field to: " << maxSource_ << endl; + } + + if (verbose_) + { + ReField_.writeOpt() = IOobject::AUTO_WRITE; + PrField_.writeOpt() = IOobject::AUTO_WRITE; + ReField_.write(); + PrField_.write(); + } + + // currently it is detected if field was auto generated or defined + // improvement would be changing the type here automatically + forAll(wallTemp_.boundaryField(),patchI) + if(wallTemp_.boundaryField()[patchI].type()=="calculated") + FatalError <<"Scalar field:"<< wallTemp_.name() << " must be defined.\n" << abort(FatalError); + + wallTemp_.writeOpt() = IOobject::AUTO_WRITE; + } + + // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + + wallHeatTransferYagi::~wallHeatTransferYagi() + { + particleCloud_.dataExchangeM().destroy(partRe_,1); + } + + // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // + void wallHeatTransferYagi::allocateMyArrays() const + { + // get memory for 2d arrays + double initVal=0.0; + + if(verbose_) + { + particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); + } + } + + // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + + void wallHeatTransferYagi::calcEnergyContribution() + { + allocateMyArrays(); + + // reset Scalar field + QWallFluid_.primitiveFieldRef() = 0.0; + + #ifdef compre + const volScalarField mufField = particleCloud_.turbulence().mu(); + #else + const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; + #endif + + interpolationCellPoint voidfractionInterpolator_(voidfraction_); + interpolationCellPoint UInterpolator_(U_); + interpolationCellPoint TInterpolator_(tempField_); + + // calculate Rep + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + label cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + scalar voidfraction; + vector Ufluid; + + if(interpolation_) + { + vector position = particleCloud_.position(index); + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + Ufluid = UInterpolator_.interpolate(position,cellI); + } + else + { + voidfraction = voidfraction_[cellI]; + Ufluid = U_[cellI]; + } + + if (voidfraction < 0.01) + voidfraction = 0.01; + + vector Us = particleCloud_.velocity(index); + scalar magUr = mag(Ufluid - Us); + scalar ds = 2.*particleCloud_.radius(index); + scalar muf = mufField[cellI]; + + scalar Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; + partRe_[index][0] = Rep; + } + } + + // calculate Rep field + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + ReField_, + partRe_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); + + // calculate Pr field + PrField_ = CpField_ * mufField / kfField_; + + const fvPatchList& patches = U_.mesh().boundary(); + + // calculate flux + forAll(patches, patchi) + { + const fvPatch& curPatch = patches[patchi]; + + if (wallTemp_.boundaryField().types()[patchi] == "fixedValue") + { + if(tempField_.boundaryField().types()[patchi] == "zeroGradient") + { + + forAll(curPatch, facei) + { + label faceCelli = curPatch.faceCells()[facei]; + + // calculate Urel + scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; + + // calculate H + scalar H; + if (voidfraction_[faceCelli]<=voidfractionMax_) + H = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); + else + H = 0; + + // get delta T (wall-fluid) + scalar Twall = wallTemp_.boundaryField()[patchi][facei]; + scalar Tfluid = tempField_[faceCelli]; + scalar deltaT = Twall - Tfluid; + + // get area + scalar area = curPatch.magSf()[facei]; + + // calculate heat flux + heatFlux(faceCelli, H, area, Twall, Tfluid); + heatFluxCoeff(faceCelli, H, area); + + if(verbose_ && facei >=0 && facei <2) + { + Info << "####################" << endl; + Info << "cellID: " << faceCelli << endl; + Info << "G : " << magG << endl; + Info << "Re: " << ReField_[faceCelli] << endl; + Info << "Pr: " << PrField_[faceCelli] << endl; + Info << "Cp: " << CpField_[faceCelli] << endl; + Info << "kf: " << kfField_[faceCelli] << endl; + Info << "H : " << H << endl; + Info << "Twall: " << Twall << endl; + Info << "Tfluid: " << Tfluid << endl; + Info << "dT: " << deltaT << endl; + Info << "q: " << H*deltaT << endl; + Info << "area: " << area << endl; + Info << "Q:" << H*deltaT*area << endl; + } + } + } + else + { + FatalError << "wallHeatTransferYagi requires zeroGradient BC for temperature field" << endl; + } + } + } + + QWallFluid_.primitiveFieldRef() /= QWallFluid_.mesh().V(); + + // limit source term + forAll(QWallFluid_,cellI) + { + scalar EuFieldInCell = QWallFluid_[cellI]; + + if(mag(EuFieldInCell) > maxSource_ ) + { + Pout << "limiting source term" << endl ; + QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; + } + } + + QWallFluid_.correctBoundaryConditions(); + + } + + void wallHeatTransferYagi::addEnergyContribution(volScalarField& Qsource) const + { + Qsource += QWallFluid_; + } + + void wallHeatTransferYagi::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) + { + QWallFluid_[faceCelli] += H * area * (Twall - Tfluid); + } + + void wallHeatTransferYagi::heatFluxCoeff(label faceCelli, scalar H, scalar area) + { + //no heat transfer coefficient in explicit model + } + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.H similarity index 92% rename from src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H rename to src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.H index 528e9ef0..d3ea5e13 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagi/wallHeatTransferYagi.H @@ -22,8 +22,8 @@ License \*---------------------------------------------------------------------------*/ -#ifndef YagiWallHT_H -#define YagiWallHT_H +#ifndef wallHeatTransferYagi_H +#define wallHeatTransferYagi_H #include "fvCFD.H" #include "cfdemCloudEnergy.H" @@ -34,10 +34,10 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class YagiWallHT Declaration + Class wallHeatTransferYagi Declaration \*---------------------------------------------------------------------------*/ -class YagiWallHT +class wallHeatTransferYagi : public energyModel { @@ -106,12 +106,12 @@ protected: public: //- Runtime type information - TypeName("YagiWallHT"); + TypeName("wallHeatTransferYagi"); // Constructors //- Construct from components - YagiWallHT + wallHeatTransferYagi ( const dictionary& dict, cfdemCloudEnergy& sm @@ -120,7 +120,7 @@ public: // Destructor - virtual ~YagiWallHT(); + virtual ~wallHeatTransferYagi(); // Member Functions diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C new file mode 100644 index 00000000..9499fcba --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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. + + This code 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 this code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "wallHeatTransferYagiImplicit.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(wallHeatTransferYagiImplicit, 0); + +addToRunTimeSelectionTable(energyModel, wallHeatTransferYagiImplicit, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +wallHeatTransferYagiImplicit::wallHeatTransferYagiImplicit +( + const dictionary& dict, + cfdemCloudEnergy& sm +) +: + wallHeatTransferYagi(dict,sm), + QWallFluidCoeffName_(propsDict_.lookupOrDefault("QWallFluidCoeffName","QWallFluidCoeff")), + QWallFluidCoeff_ + ( IOobject + ( + QWallFluidCoeffName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) + ), + partHeatFluxCoeff_(NULL) +{ + allocateMyArrays(); + + // no limiting necessary for implicit heat transfer + maxSource_ = 1e30; +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +wallHeatTransferYagiImplicit::~wallHeatTransferYagiImplicit() +{ + particleCloud_.dataExchangeM().destroy(partHeatFluxCoeff_,1); +} + +// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // +void wallHeatTransferYagiImplicit::allocateMyArrays() const +{ +// wallHeatTransferYagi::allocateMyArrays(); + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partHeatFluxCoeff_,initVal,1); +} +// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + +void wallHeatTransferYagiImplicit::calcEnergyContribution() +{ + allocateMyArrays(); + + QWallFluidCoeff_.primitiveFieldRef() = 0.0; + + wallHeatTransferYagi::calcEnergyContribution(); + + QWallFluidCoeff_.primitiveFieldRef() /= QWallFluidCoeff_.mesh().V(); + +// QWallFluidCoeff_.correctBoundaryConditions(); + +} + +void wallHeatTransferYagiImplicit::addEnergyCoefficient(volScalarField& Qsource) const +{ + Qsource += QWallFluidCoeff_; +} + +void wallHeatTransferYagiImplicit::heatFlux(label faceCelli, scalar H, scalar area, scalar Twall, scalar Tfluid) +{ + QWallFluid_[faceCelli] += H * area * Twall; +} + +void wallHeatTransferYagiImplicit::heatFluxCoeff(label faceCelli, scalar H, scalar area) +{ + QWallFluidCoeff_[faceCelli] -= H * area; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.H similarity index 85% rename from src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H rename to src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.H index 2d4403be..08c8cd31 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.H @@ -22,24 +22,24 @@ License \*---------------------------------------------------------------------------*/ -#ifndef YagiWallHTImplicit_H -#define YagiWallHTImplicit_H +#ifndef wallHeatTransferYagiImplicit_H +#define wallHeatTransferYagiImplicit_H #include "fvCFD.H" #include "cfdemCloudEnergy.H" -#include "YagiWallHT.H" +#include "wallHeatTransferYagi.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { /*---------------------------------------------------------------------------*\ - Class YagiWallHTImplicit Declaration + Class wallHeatTransferYagiImplicit Declaration \*---------------------------------------------------------------------------*/ -class YagiWallHTImplicit +class wallHeatTransferYagiImplicit : - public YagiWallHT + public wallHeatTransferYagi { private: @@ -58,12 +58,12 @@ private: public: //- Runtime type information - TypeName("YagiWallHTImplicit"); + TypeName("wallHeatTransferYagiImplicit"); // Constructors //- Construct from components - YagiWallHTImplicit + wallHeatTransferYagiImplicit ( const dictionary& dict, cfdemCloudEnergy& sm @@ -72,7 +72,7 @@ public: // Destructor - virtual ~YagiWallHTImplicit(); + virtual ~wallHeatTransferYagiImplicit(); // Member Functions diff --git a/src/lagrangian/cfdemParticleComp/Make/files b/src/lagrangian/cfdemParticleComp/Make/files index 17a7f1bf..44ea58f0 100644 --- a/src/lagrangian/cfdemParticleComp/Make/files +++ b/src/lagrangian/cfdemParticleComp/Make/files @@ -32,8 +32,8 @@ $(energyModels)/energyModel/energyModel.C $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C $(energyModels)/heatTransferGunnImplicit/heatTransferGunnImplicit.C -$(energyModels)/YagiWallHT/YagiWallHT.C -$(energyModels)/YagiWallHTImplicit/YagiWallHTImplicit.C +$(energyModels)/wallHeatTransferYagi/wallHeatTransferYagi.C +$(energyModels)/wallHeatTransferYagiImplicit/wallHeatTransferYagiImplicit.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C From 59afe3dc3d0f04bf14339799e084298719060e4e Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 28 Feb 2020 10:32:59 +0100 Subject: [PATCH 45/47] fix --- .../cfdemSolverMultiphase/tankDrainage/CFD/system/fvSchemes | 1 + 1 file changed, 1 insertion(+) diff --git a/tutorials/cfdemSolverMultiphase/tankDrainage/CFD/system/fvSchemes b/tutorials/cfdemSolverMultiphase/tankDrainage/CFD/system/fvSchemes index e15a3682..4a76aa77 100644 --- a/tutorials/cfdemSolverMultiphase/tankDrainage/CFD/system/fvSchemes +++ b/tutorials/cfdemSolverMultiphase/tankDrainage/CFD/system/fvSchemes @@ -38,6 +38,7 @@ divSchemes div(((dev(grad(U).T())*rho)*dev(grad(U).T()))) Gauss linear; div((((((alpha.water*rho)*nu.water)|(alpha.water*rho))*rho)*dev(grad(U).T()))) Gauss linear; div(((nu*rho)*dev(grad(U).T()))) Gauss linear; + div(((rho*(nu+nut))*dev2(grad(U).T()))) Gauss linear; } laplacianSchemes From c35ac408cc5a324b0decf8e6a62bef4fdeda2644 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 28 Feb 2020 12:19:18 +0100 Subject: [PATCH 46/47] harmonic mean for nu --- .../multiphaseMixture/multiphaseMixture.C | 9 +- .../multiphaseMixture/#multiphaseMixture.C# | 816 ------------------ .../multiphaseMixture/multiphaseMixture.C | 9 +- 3 files changed, 16 insertions(+), 818 deletions(-) delete mode 100644 applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# diff --git a/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/multiphaseMixture.C index bd969ec6..6cf6cf91 100644 --- a/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/multiphaseMixture.C +++ b/applications/solvers/cfdemSolverMultiphase/multiphaseMixture/multiphaseMixture.C @@ -55,13 +55,20 @@ Foam::multiphaseMixture::calcNu() const { PtrDictionary::const_iterator iter = phases_.begin(); + // 1/nu + tmp tnuInv = iter()/iter().nu(); + volScalarField& nuInv = tnuInv.ref(); + + // nu tmp tnu = iter()*iter().nu(); volScalarField& nu = tnu.ref(); for (++iter; iter != phases_.end(); ++iter) { - nu += iter()*iter().nu(); + nuInv += iter()/iter().nu(); } + + nu = 1/nuInv; return tnu; } diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# deleted file mode 100644 index 2b2e645f..00000000 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/#multiphaseMixture.C# +++ /dev/null @@ -1,816 +0,0 @@ -/*---------------------------------------------------------------------------*\ -License - - This 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. - - This code 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 this code. If not, see . - - Copyright (C) 2018- Mathias Vångö, JKU Linz, Austria - -\*---------------------------------------------------------------------------*/ - -#include "multiphaseMixture.H" -#include "alphaContactAngleFvPatchScalarField.H" -#include "Time.H" -#include "subCycle.H" -#include "MULES.H" -#include "surfaceInterpolate.H" -#include "fvcGrad.H" -#include "fvcSnGrad.H" -#include "fvcDiv.H" -#include "fvcFlux.H" - -// * * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * // - -const Foam::scalar Foam::multiphaseMixture::convertToRad = - Foam::constant::mathematical::pi/180.0; - - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -void Foam::multiphaseMixture::calcAlphas() -{ - scalar level = 0.0; - alphas_ == 0.0; - - forAllIter(PtrDictionary, phases_, iter) - { - alphas_ += level*iter(); - level += 1.0; - } -} - - -Foam::tmp -Foam::multiphaseMixture::calcNu() const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tnu = iter()*iter().nu(); - volScalarField& nu = tnu.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - nu += iter()*iter().nu(); - } - - return tnu; -} - -Foam::tmp -Foam::multiphaseMixture::calcStf() const -{ - tmp tstf - ( - new surfaceScalarField - ( - IOobject - ( - "stf", - mesh_.time().timeName(), - mesh_ - ), - mesh_, - dimensionedScalar - ( - "stf", - dimensionSet(1, -2, -2, 0, 0), - 0.0 - ) - ) - ); - - surfaceScalarField& stf = tstf.ref(); - - forAllConstIter(PtrDictionary, phases_, iter1) - { - const phase& alpha1 = iter1(); - - PtrDictionary::const_iterator iter2 = iter1; - ++iter2; - - for (; iter2 != phases_.end(); ++iter2) - { - const phase& alpha2 = iter2(); - - sigmaTable::const_iterator sigma = - sigmas_.find(interfacePair(alpha1, alpha2)); - - if (sigma == sigmas_.end()) - { - FatalErrorInFunction - << "Cannot find interface " << interfacePair(alpha1, alpha2) - << " in list of sigma values" - << exit(FatalError); - } - - stf += dimensionedScalar("sigma", dimSigma_, sigma()) - *fvc::interpolate(K(alpha1, alpha2))* - ( - fvc::interpolate(alpha2)*fvc::snGrad(alpha1) - - fvc::interpolate(alpha1)*fvc::snGrad(alpha2) - ); - } - } - - return tstf; -} - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::multiphaseMixture::multiphaseMixture -( - const volVectorField& U, - const surfaceScalarField& phi, - const volScalarField& voidfraction -) -: - IOdictionary - ( - IOobject - ( - "transportProperties", - U.time().constant(), - U.db(), - IOobject::MUST_READ_IF_MODIFIED, - IOobject::NO_WRITE - ) - ), - - phases_(lookup("phases"), phase::iNew(U, phi)), - - mesh_(U.mesh()), - U_(U), - phi_(phi), - voidfraction_(voidfraction), - rhoPhi_ - ( - IOobject - ( - "rhoPhi", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::NO_WRITE - ), - mesh_, - dimensionedScalar("rhoPhi", dimMass/dimTime, 0.0) - ), - surfaceTensionForce_ - ( - IOobject - ( - "surfaceTensionForce", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - mesh_, - dimensionedScalar("surfaceTensionForce", dimensionSet(1, -2, -2, 0, 0), 0.0) - ), - alphas_ - ( - IOobject - ( - "alphas", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - mesh_, - dimensionedScalar("alphas", dimless, 0.0) - ), - - nu_ - ( - IOobject - ( - "nu", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - calcNu() - ), - - sigmas_(lookup("sigmas")), - dimSigma_(1, 0, -2, 0, 0), - deltaN_ - ( - "deltaN", - 1e-8/pow(average(mesh_.V()), 1.0/3.0) - ) -{ - calcAlphas(); - alphas_.write(); - surfaceTensionForce_ = calcStf(); - -} - - -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // - -Foam::tmp -Foam::multiphaseMixture::rho() const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp trho = iter()*iter().rho(); - volScalarField& rho = trho.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - rho += iter()*iter().rho(); - } - - return trho; -} - - -Foam::tmp -Foam::multiphaseMixture::rho(const label patchi) const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp trho = iter().boundaryField()[patchi]*iter().rho().value(); - scalarField& rho = trho.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - rho += iter().boundaryField()[patchi]*iter().rho().value(); - } - - return trho; -} - - -Foam::tmp -Foam::multiphaseMixture::mu() const -{ - Info << "In multiphasemixture mu()" << endl; - return rho()*nu(); -// PtrDictionary::const_iterator iter = phases_.begin(); - -// tmp tmu = iter()*iter().rho()*iter().nu(); -// volScalarField& mu = tmu.ref(); - -// for (++iter; iter != phases_.end(); ++iter) -// { -// mu += iter()*iter().rho()*iter().nu(); -// } - -// return tmu; -} - - -Foam::tmp -Foam::multiphaseMixture::mu(const label patchi) const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tmu = - iter().boundaryField()[patchi] - *iter().rho().value() - *iter().nu(patchi); - scalarField& mu = tmu.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - mu += - iter().boundaryField()[patchi] - *iter().rho().value() - *iter().nu(patchi); - } - - return tmu; -} - - -Foam::tmp -Foam::multiphaseMixture::muf() const -{ - - return nuf()*fvc::interpolate(rho()); -// PtrDictionary::const_iterator iter = phases_.begin(); - -// tmp tmuf = -// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); -// surfaceScalarField& muf = tmuf.ref(); - -// for (++iter; iter != phases_.end(); ++iter) -// { -// muf += -// fvc::interpolate(iter())*iter().rho()*fvc::interpolate(iter().nu()); -// } - -// return tmuf; -} - - -Foam::tmp -Foam::multiphaseMixture::nu() const -{ - return nu_; -} - -Foam::tmp -Foam::multiphaseMixture::nu(const label patchi) const -{ - //return nu_.boundaryField()[patchi]; - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tnu = - iter().boundaryField()[patchi] - *iter().nu(patchi); - scalarField& nu = tnu.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - nu += - iter().boundaryField()[patchi] - *iter().nu(patchi); - } - - return tnu; -} - - -Foam::tmp -Foam::multiphaseMixture::nuf() const -{ - //return muf()/fvc::interpolate(rho()); - PtrDictionary::const_iterator iter = phases_.begin(); - - tmp tnuf = - fvc::interpolate(iter())*fvc::interpolate(iter().nu()); - surfaceScalarField& nuf = tnuf.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - nuf += - fvc::interpolate(iter())*fvc::interpolate(iter().nu()); - } - - return tnuf; -} - -Foam::tmp -Foam::multiphaseMixture::Cp() const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - // rho*Cp - tmp trhoCp = iter()*iter().Cp()*iter().rho(); - volScalarField& rhoCp = trhoCp.ref(); - - // Cp - tmp tCp = iter()*iter().Cp(); - volScalarField& Cp = tCp.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - rhoCp += iter()*iter().Cp()*iter().rho(); - } - Cp = rhoCp/rho(); - return tCp; -} - -Foam::tmp -Foam::multiphaseMixture::kf() const -{ - PtrDictionary::const_iterator iter = phases_.begin(); - - // rho*Cp/kf - tmp trhoCpkf = iter()*iter().rho()*iter().Cp()/iter().kf(); - volScalarField& rhoCpkf = trhoCpkf.ref(); - - // kf - tmp tkf = iter()*iter().kf(); - volScalarField& kf = tkf.ref(); - - for (++iter; iter != phases_.end(); ++iter) - { - rhoCpkf += iter()*iter().rho()*iter().Cp()/iter().kf(); - } - - kf = rho()*Cp()/rhoCpkf; - return tkf; -} - -void Foam::multiphaseMixture::solve() -{ - correct(); - - const Time& runTime = mesh_.time(); - - volScalarField& alpha = phases_.first(); - - const dictionary& alphaControls = mesh_.solverDict("alpha"); - label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles"))); - scalar cAlpha(readScalar(alphaControls.lookup("cAlpha"))); - - if (nAlphaSubCycles > 1) - { - surfaceScalarField rhoPhiSum - ( - IOobject - ( - "rhoPhiSum", - runTime.timeName(), - mesh_ - ), - mesh_, - dimensionedScalar("0", rhoPhi_.dimensions(), 0) - ); - - dimensionedScalar totalDeltaT = runTime.deltaT(); - - for - ( - subCycle alphaSubCycle(alpha, nAlphaSubCycles); - !(++alphaSubCycle).end(); - ) - { - FatalError << "Sub-cycling of the alpha equation not yet implemented!!" << abort(FatalError); - solveAlphas(cAlpha); - rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi_; - } - - rhoPhi_ = rhoPhiSum; - } - else - { - solveAlphas(cAlpha); - } - - // Update the mixture kinematic viscosity - nu_ = calcNu(); - - surfaceTensionForce_ = calcStf(); -} - - -void Foam::multiphaseMixture::correct() -{ - forAllIter(PtrDictionary, phases_, iter) - { - iter().correct(); - } -} - - -Foam::tmp Foam::multiphaseMixture::nHatfv -( - const volScalarField& alpha1, - const volScalarField& alpha2 -) const -{ - /* - // Cell gradient of alpha - volVectorField gradAlpha = - alpha2*fvc::grad(alpha1) - alpha1*fvc::grad(alpha2); - - // Interpolated face-gradient of alpha - surfaceVectorField gradAlphaf = fvc::interpolate(gradAlpha); - */ - - surfaceVectorField gradAlphaf - ( - fvc::interpolate(alpha2)*fvc::interpolate(fvc::grad(alpha1)) - - fvc::interpolate(alpha1)*fvc::interpolate(fvc::grad(alpha2)) - ); - - // Face unit interface normal - return gradAlphaf/(mag(gradAlphaf) + deltaN_); -} - - -Foam::tmp Foam::multiphaseMixture::nHatf -( - const volScalarField& alpha1, - const volScalarField& alpha2 -) const -{ - // Face unit interface normal flux - return nHatfv(alpha1, alpha2) & mesh_.Sf(); -} - - -// Correction for the boundary condition on the unit normal nHat on -// walls to produce the correct contact angle. - -// The dynamic contact angle is calculated from the component of the -// velocity on the direction of the interface, parallel to the wall. - -void Foam::multiphaseMixture::correctContactAngle -( - const phase& alpha1, - const phase& alpha2, - surfaceVectorField::Boundary& nHatb -) const -{ - const volScalarField::Boundary& gbf - = alpha1.boundaryField(); - - const fvBoundaryMesh& boundary = mesh_.boundary(); - - forAll(boundary, patchi) - { - if (isA(gbf[patchi])) - { - const alphaContactAngleFvPatchScalarField& acap = - refCast(gbf[patchi]); - - vectorField& nHatPatch = nHatb[patchi]; - - vectorField AfHatPatch - ( - mesh_.Sf().boundaryField()[patchi] - /mesh_.magSf().boundaryField()[patchi] - ); - - alphaContactAngleFvPatchScalarField::thetaPropsTable:: - const_iterator tp = - acap.thetaProps().find(interfacePair(alpha1, alpha2)); - - if (tp == acap.thetaProps().end()) - { - FatalErrorInFunction - << "Cannot find interface " << interfacePair(alpha1, alpha2) - << "\n in table of theta properties for patch " - << acap.patch().name() - << exit(FatalError); - } - - bool matched = (tp.key().first() == alpha1.name()); - - scalar theta0 = convertToRad*tp().theta0(matched); - scalarField theta(boundary[patchi].size(), theta0); - - scalar uTheta = tp().uTheta(); - - // Calculate the dynamic contact angle if required - if (uTheta > SMALL) - { - scalar thetaA = convertToRad*tp().thetaA(matched); - scalar thetaR = convertToRad*tp().thetaR(matched); - - // Calculated the component of the velocity parallel to the wall - vectorField Uwall - ( - U_.boundaryField()[patchi].patchInternalField() - - U_.boundaryField()[patchi] - ); - Uwall -= (AfHatPatch & Uwall)*AfHatPatch; - - // Find the direction of the interface parallel to the wall - vectorField nWall - ( - nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch - ); - - // Normalise nWall - nWall /= (mag(nWall) + SMALL); - - // Calculate Uwall resolved normal to the interface parallel to - // the interface - scalarField uwall(nWall & Uwall); - - theta += (thetaA - thetaR)*tanh(uwall/uTheta); - } - - - // Reset nHatPatch to correspond to the contact angle - - scalarField a12(nHatPatch & AfHatPatch); - - scalarField b1(cos(theta)); - - scalarField b2(nHatPatch.size()); - - forAll(b2, facei) - { - b2[facei] = cos(acos(a12[facei]) - theta[facei]); - } - - scalarField det(1.0 - a12*a12); - - scalarField a((b1 - a12*b2)/det); - scalarField b((b2 - a12*b1)/det); - - nHatPatch = a*AfHatPatch + b*nHatPatch; - - nHatPatch /= (mag(nHatPatch) + deltaN_.value()); - } - } -} - - -Foam::tmp Foam::multiphaseMixture::K -( - const phase& alpha1, - const phase& alpha2 -) const -{ - tmp tnHatfv = nHatfv(alpha1, alpha2); - - correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef()); - - // Simple expression for curvature - return -fvc::div(tnHatfv & mesh_.Sf()); -} - - -Foam::tmp -Foam::multiphaseMixture::nearInterface() const -{ - tmp tnearInt - ( - new volScalarField - ( - IOobject - ( - "nearInterface", - mesh_.time().timeName(), - mesh_ - ), - mesh_, - dimensionedScalar("nearInterface", dimless, 0.0) - ) - ); - - forAllConstIter(PtrDictionary, phases_, iter) - { - tnearInt.ref() = max(tnearInt(), pos(iter() - 0.01)*pos(0.99 - iter())); - } - - return tnearInt; -} - - -void Foam::multiphaseMixture::solveAlphas -( - const scalar cAlpha -) -{ - static label nSolves=-1; - nSolves++; - - word alphaScheme("div(phi,alpha)"); - word alpharScheme("div(phirb,alpha)"); - - surfaceScalarField phic(mag(phi_/mesh_.magSf())); - phic = min(cAlpha*phic, max(phic)); - - PtrList alphaPhiCorrs(phases_.size()); - int phasei = 0; - - forAllIter(PtrDictionary, phases_, iter) - { - phase& alpha = iter(); - - alphaPhiCorrs.set - ( - phasei, - new surfaceScalarField - ( - "phi" + alpha.name() + "Corr", - fvc::flux - ( - phi_, - alpha, - alphaScheme - ) - ) - ); - - surfaceScalarField& alphaPhiCorr = alphaPhiCorrs[phasei]; - - forAllIter(PtrDictionary, phases_, iter2) - { - phase& alpha2 = iter2(); - - if (&alpha2 == &alpha) continue; - - surfaceScalarField phir(phic*nHatf(alpha, alpha2)); - - alphaPhiCorr += fvc::flux - ( - -fvc::flux(-phir, alpha2, alpharScheme), - alpha, - alpharScheme - ); - } - - MULES::limit - ( - 1.0/mesh_.time().deltaT().value(), - voidfraction_, - alpha, - phi_, - alphaPhiCorr, - zeroField(), - zeroField(), - 1, - 0, - true - ); - - phasei++; - } - - MULES::limitSum(alphaPhiCorrs); - - rhoPhi_ = dimensionedScalar("0", dimensionSet(1, 0, -1, 0, 0), 0); - - volScalarField sumAlpha - ( - IOobject - ( - "sumAlpha", - mesh_.time().timeName(), - mesh_ - ), - mesh_, - dimensionedScalar("sumAlpha", dimless, 0) - ); - - phasei = 0; - - forAllIter(PtrDictionary, phases_, iter) - { - phase& alpha = iter(); - - surfaceScalarField& alphaPhi = alphaPhiCorrs[phasei]; - alphaPhi += upwind(mesh_, phi_).flux(alpha); - - MULES::explicitSolve - ( - voidfraction_, - alpha, - alphaPhi, - zeroField(), - zeroField() - ); - - rhoPhi_ += alphaPhi*alpha.rho(); - - Info<< alpha.name() << " volume fraction, min, max = " - << alpha.weightedAverage(mesh_.V()).value() - << ' ' << min(alpha).value() - << ' ' << max(alpha).value() - << endl; - - sumAlpha += alpha; - - phasei++; - } - - Info<< "Phase-sum volume fraction, min, max = " - << sumAlpha.weightedAverage(mesh_.V()).value() - << ' ' << min(sumAlpha).value() - << ' ' << max(sumAlpha).value() - << endl; - - calcAlphas(); -} - - -bool Foam::multiphaseMixture::read() -{ - if (transportModel::read()) - { - bool readOK = true; - - PtrList phaseData(lookup("phases")); - label phasei = 0; - - forAllIter(PtrDictionary, phases_, iter) - { - readOK &= iter().read(phaseData[phasei++].dict()); - } - - lookup("sigmas") >> sigmas_; - - return readOK; - } - else - { - return false; - } -} - - -// ************************************************************************* // diff --git a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C index 2b2e645f..faa3a1ec 100644 --- a/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C +++ b/applications/solvers/cfdemSolverMultiphaseScalar/multiphaseMixture/multiphaseMixture.C @@ -55,13 +55,20 @@ Foam::multiphaseMixture::calcNu() const { PtrDictionary::const_iterator iter = phases_.begin(); + // 1/nu + tmp tnuInv = iter()/iter().nu(); + volScalarField& nuInv = tnuInv.ref(); + + // nu tmp tnu = iter()*iter().nu(); volScalarField& nu = tnu.ref(); for (++iter; iter != phases_.end(); ++iter) { - nu += iter()*iter().nu(); + nuInv += iter()/iter().nu(); } + + nu = 1/nuInv; return tnu; } From dbcdbb101724d309923b159f4325f8b3b3df70b2 Mon Sep 17 00:00:00 2001 From: s126103 Date: Fri, 28 Feb 2020 13:49:52 +0100 Subject: [PATCH 47/47] cleanup old files --- .../energyModel/YagiWallHT/YagiWallHT.C | 327 ------------------ .../YagiWallHTImplicit/YagiWallHTImplicit.C | 116 ------- 2 files changed, 443 deletions(-) delete mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C delete mode 100644 src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C deleted file mode 100644 index 264ab29d..00000000 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHT/YagiWallHT.C +++ /dev/null @@ -1,327 +0,0 @@ -/*---------------------------------------------------------------------------*\ -License - -This 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. - -This code 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 this code. If not, see . - -Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria - -\*---------------------------------------------------------------------------*/ - -#include "error.H" -#include "wallHeatTransferYagi.H" -#include "addToRunTimeSelectionTable.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - - // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - - defineTypeNameAndDebug(wallHeatTransferYagi, 0); - - addToRunTimeSelectionTable(energyModel, wallHeatTransferYagi, dictionary); - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - - - wallHeatTransferYagi::wallHeatTransferYagi - ( - const dictionary& dict, - cfdemCloudEnergy& sm - ) - : - energyModel(dict,sm), - propsDict_(dict.subDict(typeName + "Props")), - interpolation_(propsDict_.lookupOrDefault("interpolation",false)), - verbose_(propsDict_.lookupOrDefault("verbose",false)), - QWallFluidName_(propsDict_.lookupOrDefault("QWallFluidName","QWallFluid")), - QWallFluid_ - ( IOobject - ( - QWallFluidName_, - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::READ_IF_PRESENT, - IOobject::AUTO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) - ), - wallTempName_(propsDict_.lookup("wallTempName")), - wallTemp_ - ( IOobject - ( - wallTempName_, - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::READ_IF_PRESENT, - IOobject::AUTO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0) - ), - ReField_ - ( IOobject - ( - "ReField", - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::NO_READ, - IOobject::NO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) - ), - PrField_ - ( IOobject - ( - "PrField", - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::NO_READ, - IOobject::NO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) - ), - tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), - tempField_(sm.mesh().lookupObject (tempFieldName_)), - voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), - voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), - voidfractionMax_(readScalar(propsDict_.lookup("voidfractionMax"))), - maxSource_(1e30), - velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), - U_(sm.mesh().lookupObject (velFieldName_)), - UsFieldName_(propsDict_.lookup("granVelFieldName")), - Us_(sm.mesh().lookupObject (UsFieldName_)), - densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), - rho_(sm.mesh().lookupObject (densityFieldName_)), - partRe_(NULL), - multiphase_(propsDict_.lookupOrDefault("multiphase",false)), - kfFieldName_(propsDict_.lookupOrDefault("kfFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase - kfField_(sm.mesh().lookupObject (kfFieldName_)), - CpFieldName_(propsDict_.lookupOrDefault("CpFieldName",voidfractionFieldName_)), // use voidfractionField as dummy to prevent lookup error when not using multiphase - CpField_(sm.mesh().lookupObject (CpFieldName_)) - { - allocateMyArrays(); - - if (propsDict_.found("maxSource")) - { - maxSource_=readScalar(propsDict_.lookup ("maxSource")); - Info << "limiting wall source field to: " << maxSource_ << endl; - } - - if (verbose_) - { - ReField_.writeOpt() = IOobject::AUTO_WRITE; - PrField_.writeOpt() = IOobject::AUTO_WRITE; - ReField_.write(); - PrField_.write(); - } - - // currently it is detected if field was auto generated or defined - // improvement would be changing the type here automatically - forAll(wallTemp_.boundaryField(),patchI) - if(wallTemp_.boundaryField()[patchI].type()=="calculated") - FatalError <<"Scalar field:"<< wallTemp_.name() << " must be defined.\n" << abort(FatalError); - - wallTemp_.writeOpt() = IOobject::AUTO_WRITE; - } - - // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - - wallHeatTransferYagi::~wallHeatTransferYagi() - { - particleCloud_.dataExchangeM().destroy(partRe_,1); - } - - // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // - void wallHeatTransferYagi::allocateMyArrays() const - { - // get memory for 2d arrays - double initVal=0.0; - - if(verbose_) - { - particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); - } - } - - // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // - - void wallHeatTransferYagi::calcEnergyContribution() - { - allocateMyArrays(); - - // reset Scalar field - QWallFluid_.primitiveFieldRef() = 0.0; - - #ifdef compre - const volScalarField mufField = particleCloud_.turbulence().mu(); - #else - const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; - #endif - - interpolationCellPoint voidfractionInterpolator_(voidfraction_); - interpolationCellPoint UInterpolator_(U_); - interpolationCellPoint TInterpolator_(tempField_); - - // calculate Rep - for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) - { - label cellI = particleCloud_.cellIDs()[index][0]; - if(cellI >= 0) - { - scalar voidfraction; - vector Ufluid; - - if(interpolation_) - { - vector position = particleCloud_.position(index); - voidfraction = voidfractionInterpolator_.interpolate(position,cellI); - Ufluid = UInterpolator_.interpolate(position,cellI); - } - else - { - voidfraction = voidfraction_[cellI]; - Ufluid = U_[cellI]; - } - - if (voidfraction < 0.01) - voidfraction = 0.01; - - vector Us = particleCloud_.velocity(index); - scalar magUr = mag(Ufluid - Us); - scalar ds = 2.*particleCloud_.radius(index); - scalar muf = mufField[cellI]; - - scalar Rep = ds * magUr * voidfraction * rho_[cellI]/ muf; - partRe_[index][0] = Rep; - } - } - - // calculate Rep field - particleCloud_.averagingM().resetWeightFields(); - particleCloud_.averagingM().setScalarAverage - ( - ReField_, - partRe_, - particleCloud_.particleWeights(), - particleCloud_.averagingM().UsWeightField(), - NULL - ); - - // calculate Pr field - PrField_ = CpField_ * mufField / kfField_; - - const fvPatchList& patches = U_.mesh().boundary(); - - // calculate flux - forAll(patches, patchi) - { - const fvPatch& curPatch = patches[patchi]; - - if (wallTemp_.boundaryField().types()[patchi] == "fixedValue") - { - if(tempField_.boundaryField().types()[patchi] == "zeroGradient") - { - - forAll(curPatch, facei) - { - label faceCelli = curPatch.faceCells()[facei]; - - // calculate Urel - scalar magG = mag(U_[faceCelli]-Us_[faceCelli])*voidfraction_[faceCelli]*rho_[faceCelli]; - - // calculate h - scalar h; - if (voidfraction_[faceCelli]<=voidfractionMax_) - h = 0.2087 * (pow(ReField_[faceCelli]+SMALL,-0.20)) * CpField_[faceCelli] * magG / (pow(PrField_[faceCelli],2/3) + SMALL); - else - h = 0; - - // get delta T (wall-fluid) - scalar Twall = wallTemp_.boundaryField()[patchi][facei]; - scalar Tfluid = tempField_[faceCelli]; - scalar deltaT = Twall - Tfluid; - - // get area - scalar area = curPatch.magSf()[facei]; - - // calculate heat flux - heatFlux(faceCelli, h, area, Twall, Tfluid); - heatFluxCoeff(faceCelli, h, area); - - if(verbose_ && facei >=0 && facei <2) - { - Info << "####################" << endl; - Info << "cellID [-] : " << faceCelli << endl; - Info << "G [kg/(m2s)] : " << magG << endl; - Info << "Re [-] : " << ReField_[faceCelli] << endl; - Info << "Pr [-] : " << PrField_[faceCelli] << endl; - Info << "Cp [J/(kgK)] : " << CpField_[faceCelli] << endl; - Info << "kf [J/(msK)] : " << kfField_[faceCelli] << endl; - Info << "h [J/(m2Ks)] : " << h << endl; - Info << "Twall [K] : " << Twall << endl; - Info << "Tfluid [K] : " << Tfluid << endl; - Info << "area [m2] : " << area << endl; - Info << "Q [J/s] : " << H*deltaT*area << endl; - } - } - } - else - { - FatalError << "wallHeatTransferYagi requires zeroGradient BC for temperature field" << endl; - } - } - } - - QWallFluid_.primitiveFieldRef() /= QWallFluid_.mesh().V(); - - // limit source term - forAll(QWallFluid_,cellI) - { - scalar EuFieldInCell = QWallFluid_[cellI]; - - if(mag(EuFieldInCell) > maxSource_ ) - { - Pout << "limiting source term" << endl ; - QWallFluid_[cellI] = sign(EuFieldInCell) * maxSource_; - } - } - - QWallFluid_.correctBoundaryConditions(); - - } - - void wallHeatTransferYagi::addEnergyContribution(volScalarField& Qsource) const - { - Qsource += QWallFluid_; - } - - void wallHeatTransferYagi::heatFlux(label faceCelli, scalar h, scalar area, scalar Twall, scalar Tfluid) - { - QWallFluid_[faceCelli] += h * area * (Twall - Tfluid); - } - - void wallHeatTransferYagi::heatFluxCoeff(label faceCelli, scalar h, scalar area) - { - //no heat transfer coefficient in explicit model - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C b/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C deleted file mode 100644 index e92630e2..00000000 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/YagiWallHTImplicit/YagiWallHTImplicit.C +++ /dev/null @@ -1,116 +0,0 @@ -/*---------------------------------------------------------------------------*\ -License - - This 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. - - This code 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 this code. If not, see . - - Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria - -\*---------------------------------------------------------------------------*/ - -#include "error.H" -#include "wallHeatTransferYagiImplicit.H" -#include "addToRunTimeSelectionTable.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -defineTypeNameAndDebug(wallHeatTransferYagiImplicit, 0); - -addToRunTimeSelectionTable(energyModel, wallHeatTransferYagiImplicit, dictionary); - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -// Construct from components -wallHeatTransferYagiImplicit::wallHeatTransferYagiImplicit -( - const dictionary& dict, - cfdemCloudEnergy& sm -) -: - wallHeatTransferYagi(dict,sm), - QWallFluidCoeffName_(propsDict_.lookupOrDefault("QWallFluidCoeffName","QWallFluidCoeff")), - QWallFluidCoeff_ - ( IOobject - ( - QWallFluidCoeffName_, - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::READ_IF_PRESENT, - IOobject::AUTO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) - ), - partHeatFluxCoeff_(NULL) -{ - allocateMyArrays(); - - // no limiting necessary for implicit heat transfer - maxSource_ = 1e30; -} - - -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -wallHeatTransferYagiImplicit::~wallHeatTransferYagiImplicit() -{ - particleCloud_.dataExchangeM().destroy(partHeatFluxCoeff_,1); -} - -// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // -void wallHeatTransferYagiImplicit::allocateMyArrays() const -{ -// wallHeatTransferYagi::allocateMyArrays(); - double initVal=0.0; - particleCloud_.dataExchangeM().allocateArray(partHeatFluxCoeff_,initVal,1); -} -// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // - -void wallHeatTransferYagiImplicit::calcEnergyContribution() -{ - allocateMyArrays(); - - QWallFluidCoeff_.primitiveFieldRef() = 0.0; - - wallHeatTransferYagi::calcEnergyContribution(); - - QWallFluidCoeff_.primitiveFieldRef() /= QWallFluidCoeff_.mesh().V(); - -// QWallFluidCoeff_.correctBoundaryConditions(); - -} - -void wallHeatTransferYagiImplicit::addEnergyCoefficient(volScalarField& Qsource) const -{ - Qsource += QWallFluidCoeff_; -} - -void wallHeatTransferYagiImplicit::heatFlux(label faceCelli, scalar h, scalar area, scalar Twall, scalar Tfluid) -{ - QWallFluid_[faceCelli] += h * area * Twall; -} - -void wallHeatTransferYagiImplicit::heatFluxCoeff(label faceCelli, scalar h, scalar area) -{ - QWallFluidCoeff_[faceCelli] -= h * area; -} - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// ************************************************************************* //