MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
LPTSpherical< nDim > Class Template Reference

#include <lptspherical.h>

Inheritance diagram for LPTSpherical< nDim >:
[legend]
Collaboration diagram for LPTSpherical< nDim >:
[legend]

Public Member Functions

 LPTSpherical ()
 constructor of spherical particles, used to invalidate values when debugging! More...
 
 ~LPTSpherical () override=default
 
 LPTSpherical (const LPTSpherical &)=default
 
LPTSphericaloperator= (const LPTSpherical &)=default
 
void motionEquation () override
 
void energyEquation () override
 
void coupling () override
 single particle coupling terms More...
 
void advanceParticle () override
 advance to new timeStep More...
 
void resetWeights () override
 
MFloat dragFactor (const MFloat partRe)
 Calculate drag factor of the current particle for the given particle Reynolds number. in the literature this is referred to as: C_d * Re_p / 24. More...
 
MFloat sphericalVolume () const
 Calculate the current volume. More...
 
MFloat sphericalMass () const
 Calculate the current mass. More...
 
MFloat magRelVel (const MFloat *const velocity1, const MFloat *const velocity2) const
 Calculate the magnitude of the relative velocity of the two given velocity vectors. More...
 
MFloat magVel () const
 Calculate the magnitude of the relative velocity of the two given velocity vectors. More...
 
MFloat particleRe (const MFloat velocity, const MFloat density, const MFloat dynamicViscosity)
 Calculate the particle reynoldsnumber. More...
 
MFloat fParticleRelTime (const MFloat dynamicViscosity)
 Calculate the reciprocal of the particle relaxation time. More...
 
MFloat WeberNumber (const MFloat density, const MFloat velocity, const MFloat temperature)
 Calculate the particle Weber-number (radius based) More...
 
MFloat effectiveWallCollisionRadius () const override
 Returns the relevant particle radius for the wall collision. More...
 
void initVelocityAndDensity ()
 
- Public Member Functions inherited from LPTBase< nDim >
virtual ~LPTBase ()=default
 
BitsetType::reference hasProperty (const LptBaseProperty p)
 Accessor for properties. More...
 
MBool hasProperty (const LptBaseProperty p) const
 Accessor for properties (const version). More...
 
BitsetType::reference isWindow ()
 
MBool isWindow () const
 
BitsetType::reference reqSend ()
 
MBool reqSend () const
 
BitsetType::reference reqBroadcast ()
 
MBool reqBroadcast () const
 
BitsetType::reference isInvalid ()
 
MBool isInvalid () const
 
BitsetType::reference hasCollided ()
 
MBool hasCollided () const
 
BitsetType::reference hadWallColl ()
 
MBool hadWallColl () const
 
BitsetType::reference firstStep ()
 
MBool firstStep () const
 
BitsetType::reference toBeDeleted ()
 
MBool toBeDeleted () const
 
BitsetType::reference wasSend ()
 
MBool wasSend () const
 
BitsetType::reference toBeRespawn ()
 
MBool toBeRespawn () const
 
BitsetType::reference fullyEvaporated ()
 
MBool fullyEvaporated () const
 
void getNghbrList (std::vector< MInt > &, const MInt)
 
template<MInt a, MInt b>
void interpolateAndCalcWeights (const MInt cellId, const MFloat *const x, MFloat *const result, std::vector< MFloat > &weight, MFloat *const gradientResult=nullptr)
 
virtual void energyEquation ()=0
 
virtual void coupling ()=0
 
virtual void motionEquation ()=0
 
virtual void advanceParticle ()=0
 
virtual void resetWeights ()=0
 
virtual void particleWallCollision ()
 particle-wall collision step More...
 
virtual void wallParticleCollision ()
 wall-particle collision step More...
 
void initProperties ()
 
void checkCellChange (const MFloat *oldPosition, const MBool allowHaloNonLeaf=false)
 Checks whether position is within cell with number cellId if not, cellId is updated. More...
 
void updateProperties (const MBool init=true)
 Update particle properties. More...
 
virtual MFloat effectiveWallCollisionRadius () const
 

Public Attributes

std::array< MFloat, nDim > m_fluidVel {}
 fluid velocity More...
 
MFloat m_fluidDensity = std::numeric_limits<MFloat>::quiet_NaN()
 fluid density More...
 
std::array< MFloat, nDim > m_oldAccel {}
 particle acceleration of the last time step More...
 
std::array< MFloat, nDim > m_oldFluidVel {}
 fluid velocity of the last time step More...
 
MFloat m_oldFluidDensity = std::numeric_limits<MFloat>::quiet_NaN()
 old fluid density More...
 
MFloat m_diameter = std::numeric_limits<MFloat>::quiet_NaN()
 particle diameter More...
 
MFloat m_temperature = std::numeric_limits<MFloat>::quiet_NaN()
 temperature More...
 
MFloat m_breakUpTime = std::numeric_limits<MFloat>::quiet_NaN()
 time since last breakUp More...
 
MFloat m_shedDiam = std::numeric_limits<MFloat>::quiet_NaN()
 shedding diameter More...
 
MInt m_noParticles = -1
 parceled particles More...
 
MFloat m_dM = std::numeric_limits<MFloat>::quiet_NaN()
 mass evaporation rate More...
 
MFloat m_fluidVelMag = std::numeric_limits<MFloat>::quiet_NaN()
 fluid velocity magnitude More...
 
MFloat m_heatFlux = std::numeric_limits<MFloat>::quiet_NaN()
 heat flux to cell More...
 
std::vector< MFloatm_redistWeight {}
 
- Public Attributes inherited from LPTBase< nDim >
std::array< MFloat, nDim > m_position {}
 
std::array< MFloat, nDim > m_velocity {}
 
std::array< MFloat, nDim > m_accel {}
 
std::array< MFloat, nDim > m_oldPos {}
 particle position of the last time step More...
 
std::array< MFloat, nDim > m_oldVel {}
 particle velocity of the last time step More...
 
MFloat m_densityRatio = -2
 
MLong m_partId = -2
 
MInt m_cellId = -2
 
MInt m_oldCellId = -2
 
MFloat m_creationTime = std::numeric_limits<MFloat>::quiet_NaN()
 creation time modifier More...
 
BitsetType m_properties
 
std::vector< MIntm_neighborList
 

Static Public Attributes

static constexpr MInt s_floatElements = 9 + 4 * nDim
 
static constexpr MInt s_intElements = 1
 
static MFloat s_lengthFactor = 1.0
 
static MFloat s_Re = 1.0
 
static MFloat s_Pr = 1.0
 
static MFloat s_Sc = 1.0
 
static MFloat s_We = 1.0
 
static std::array< MFloat, nDim > s_Frm {}
 
- Static Public Attributes inherited from LPTBase< nDim >
static MInt s_interpolationOrder = 0
 
static MInt s_interpolationMethod = 0
 
static MFloat s_distFactorImp = 0.0
 
static LPT< nDim > * s_backPtr = nullptr
 
static constexpr MInt s_floatElements = 3 * nDim + 1
 
static constexpr MInt s_intElements = 5
 

Private Member Functions

void interpolateVelocityAndDensity (const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, std::vector< MFloat > &weights)
 
void interpolateAllFluidVariables (const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, MFloat &pressure, MFloat &temperature, MFloat &species, std::vector< MFloat > &weights)
 
void interpolateAllFluidVariables (const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, MFloat &pressure, MFloat &temperature, std::vector< MFloat > &weights)
 
void momentumCoupling ()
 add the momentum flux from the particle to the cell/all surrounding cells More...
 
void heatCoupling ()
 add the heat flux from the particle to the cell/all surrounding cells More...
 
void massCoupling ()
 add the mass flux from the particle to the cell/all surrounding cells More...
 

Friends

template<MInt >
std::ostream & operator<< (std::ostream &os, const LPTSpherical &m)
 

Additional Inherited Members

- Public Types inherited from LPTBase< nDim >
using BitsetType = maia::lpt::baseProperty::BitsetType
 

Detailed Description

template<MInt nDim>
class LPTSpherical< nDim >

Definition at line 21 of file lptspherical.h.

Constructor & Destructor Documentation

◆ LPTSpherical() [1/2]

template<MInt nDim>
LPTSpherical< nDim >::LPTSpherical
Author
Sven Berger, Tim Wegmann

Definition at line 42 of file lptspherical.cpp.

42 {
43 //#ifdef LPT_DEBUG
44 const auto nan = std::numeric_limits<MFloat>::quiet_NaN();
45
46 for(MInt i = 0; i < nDim; i++) {
47 m_fluidVel[i] = nan;
48 m_oldFluidVel[i] = nan;
49 m_velocity[i] = nan;
50 m_oldVel[i] = nan;
51 m_position[i] = nan;
52 m_oldPos[i] = nan;
53 m_accel[i] = nan;
54 m_oldAccel[i] = nan;
55 }
56 //#endif
57}
std::array< MFloat, nDim > m_position
Definition: lptbase.h:34
std::array< MFloat, nDim > m_velocity
Definition: lptbase.h:35
std::array< MFloat, nDim > m_oldPos
particle position of the last time step
Definition: lptbase.h:39
std::array< MFloat, nDim > m_oldVel
particle velocity of the last time step
Definition: lptbase.h:41
std::array< MFloat, nDim > m_accel
Definition: lptbase.h:36
std::array< MFloat, nDim > m_oldFluidVel
fluid velocity of the last time step
Definition: lptspherical.h:70
std::array< MFloat, nDim > m_oldAccel
particle acceleration of the last time step
Definition: lptspherical.h:68
std::array< MFloat, nDim > m_fluidVel
fluid velocity
Definition: lptspherical.h:63
int32_t MInt
Definition: maiatypes.h:62

◆ ~LPTSpherical()

template<MInt nDim>
LPTSpherical< nDim >::~LPTSpherical ( )
overridedefault

◆ LPTSpherical() [2/2]

template<MInt nDim>
LPTSpherical< nDim >::LPTSpherical ( const LPTSpherical< nDim > &  )
default

Member Function Documentation

◆ advanceParticle()

template<MInt nDim>
void LPTSpherical< nDim >::advanceParticle
overridevirtual
Author
Tim Wegmann

Implements LPTBase< nDim >.

Definition at line 65 of file lptspherical.cpp.

65 {
66 firstStep() = false;
67 hasCollided() = false;
68 hadWallColl() = false;
69 // m_creationTime = 0.0;
70 for(MInt i = 0; i < nDim; i++) {
71 ASSERT(!isnan(m_fluidVel[i]), "");
73 }
74 ASSERT(m_fluidDensity > 0, "");
76}
BitsetType::reference firstStep()
Definition: lptbase.h:179
BitsetType::reference hadWallColl()
Definition: lptbase.h:169
BitsetType::reference hasCollided()
Definition: lptbase.h:160
MFloat m_oldFluidDensity
old fluid density
Definition: lptspherical.h:73
MFloat m_fluidDensity
fluid density
Definition: lptspherical.h:65

◆ coupling()

template<MInt nDim>
void LPTSpherical< nDim >::coupling
overridevirtual
Author
Tim Wegmann

Implements LPTBase< nDim >.

Definition at line 84 of file lptspherical.cpp.

84 {
85 if(m_cellId < 0) {
86 mTerm(1, AT_, "coupling of invalid particle?");
87 }
88
89 if(!s_backPtr->m_heatCoupling && !s_backPtr->m_evaporation) {
90 // NOTE: set weights for later source term redistribution if not done for the evaporation yet!
91 m_redistWeight.clear();
93 }
94
95 // check that all variables have been exchanged/set correctly
96 for(MInt i = 0; i < nDim; i++) {
97 ASSERT(!isnan(m_oldFluidVel[i]), "");
98 }
99 ASSERT(m_oldFluidDensity > 0, "");
100
101 // check all source terms
102 // TODO: add debug-flags!
103 if((s_backPtr->m_heatCoupling && std::isnan(m_heatFlux)) || (s_backPtr->m_massCoupling && std::isnan(m_dM))) {
104 cerr << "Invalid energy equation!" << m_partId << " " << m_position[0] << " " << m_position[1] << " "
105 << m_position[2] << endl;
106 }
107 for(MInt i = 0; i < nDim; i++) {
108 if(std::isnan(m_accel[i])) {
109 cerr << "Invalid motion equation!" << m_partId << " " << m_position[0] << " " << m_position[1] << " "
110 << m_position[2] << endl;
111 isInvalid() = true;
112 return;
113 }
114 if(std::isnan(m_velocity[i])) {
115 cerr << "Invalid motion equation2!" << m_partId << " " << m_position[0] << " " << m_position[1] << " "
116 << m_position[2] << " " << m_densityRatio << " " << hadWallColl() << endl;
117 isInvalid() = true;
118 return;
119 }
120 }
121
122 if(s_backPtr->m_momentumCoupling) momentumCoupling();
123 if(s_backPtr->m_heatCoupling) heatCoupling();
124 if(s_backPtr->m_massCoupling) massCoupling();
125}
static LPT< nDim > * s_backPtr
Definition: lptbase.h:29
MLong m_partId
Definition: lptbase.h:45
MFloat m_densityRatio
Definition: lptbase.h:44
MInt m_cellId
Definition: lptbase.h:46
BitsetType::reference isInvalid()
Definition: lptbase.h:151
std::vector< MFloat > m_redistWeight
Definition: lptspherical.h:105
MFloat m_dM
mass evaporation rate
Definition: lptspherical.h:86
MFloat m_heatFlux
heat flux to cell
Definition: lptspherical.h:90
void momentumCoupling()
add the momentum flux from the particle to the cell/all surrounding cells
void heatCoupling()
add the heat flux from the particle to the cell/all surrounding cells
void interpolateVelocityAndDensity(const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, std::vector< MFloat > &weights)
Definition: lptspherical.h:179
void massCoupling()
add the mass flux from the particle to the cell/all surrounding cells
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ dragFactor()

template<MInt nDim>
MFloat LPTSpherical< nDim >::dragFactor ( const MFloat  partRe)
Author
Sven Berger
Date
August 2015
Parameters
[in]partReParticle Reynolds number.

Definition at line 435 of file lptspherical.cpp.

435 {
436 MFloat result = NAN;
437 switch(s_backPtr->m_dragModelType) {
438 case 0: { // drag force switched off
439 result = 0.0;
440 break;
441 }
442 case 1: { // linear Stokes drag
443 result = 1.0;
444 break;
445 }
446 case 2: { // nonlinear drag according to Schiller & Naumann
447 result = 1.0 + 0.15 * pow(partRe, 0.687);
448 break;
449 }
450 case 3: { // nonlinear drag according to Pinsky & Khain, J. Aerosol Sci. 28(7), 1177-1214 (1997).
451 result = 1.0 + 0.17 * pow(partRe, 0.632) + 1.0e-6 * pow(partRe, 2.25);
452 break;
453 }
454 case 4: {
455 // drag according to Carsten Baumgarten
456 // Mixture Formation in Internal Combustion Engines, 2005
457 // originates from Putnam 1961
458 // (C_d * Re_p / 24 )
459 if(partRe > 1000) {
460 // Newton flow regime Re from 1k to 250k
461 result = 0.424 * partRe / 24.0;
462 } else if(partRe <= 0.1) {
463 // Stokes flow
464 result = 1.0;
465 } else {
466 // transition regime
467 result = 1.0 + pow(partRe, 2.0 / 3.0) / 6.0;
468 }
469 break;
470 }
471 case 5: {
472 // drag according to Rowe for interphase momentum exchange, 1961
473 if(partRe >= 1000) {
474 result = 0.44 * partRe / 24.0;
475 } else {
476 result = 1.0 + 0.15 * pow(partRe, 0.687);
477 }
478 // limited drag to 10% fluid fraction
479 const MFloat fluidFractionUnlimited = 1 - s_backPtr->a_volumeFraction(m_cellId);
480 const MFloat fluidFraction = fluidFractionUnlimited < 0.1 ? 0.1 : fluidFractionUnlimited;
481 result *= pow(fluidFraction, -2.65) * (fluidFraction - POW2(fluidFraction));
482 break;
483 }
484 case 6: {
485 // drag corrected for fluid fraction
486 // limited drag to 10% fluid fraction
487 const MFloat fluidFractionUnlimited = 1 - s_backPtr->a_volumeFraction(m_cellId);
488 const MFloat fluidFraction = fluidFractionUnlimited < 0.1 ? 0.1 : fluidFractionUnlimited;
489 result = pow(fluidFraction, -2.65) + 1.0 / 6.0 * pow(partRe, 2.0 / 3.0) * pow(fluidFraction, -1.78);
490 break;
491 }
492 case 7: {
493 /* for testing const c_d of 1.83, according to Maier in Multisclae Simulation with a Two-Way
494 Coupled Lattice Boltzmann Methoc and Discrete Element Method (DOI: 10.1002/ceat.201600547) */
495 result = std::max(1.83 * partRe / 24, 0.1);
496 break;
497 }
498 default: {
499 mTerm(1, AT_, "Unknown particle drag method");
500 }
501 }
502 return result;
503}
constexpr Real POW2(const Real x)
Definition: functions.h:119
double MFloat
Definition: maiatypes.h:52

◆ effectiveWallCollisionRadius()

template<MInt nDim>
MFloat LPTSpherical< nDim >::effectiveWallCollisionRadius ( ) const
inlineoverridevirtual

Reimplemented from LPTBase< nDim >.

Definition at line 164 of file lptspherical.h.

164{ return F1B2 * m_diameter; }
MFloat m_diameter
particle diameter
Definition: lptspherical.h:76

◆ energyEquation()

template<MInt nDim>
void LPTSpherical< nDim >::energyEquation
overridevirtual

This is the analytical solution of the following differential equation: Spalding equation (1953) gives the mass evaporation rate dm/dt = - pi * d * density * D_AB * Sh * ln(1 + BM) as also in "A compararive study of numerical models for Eulerian-Lagrangian simulations of turbulent evaporating sprays" D.I. Kolaitis, M.A. Founti J. Heat and Fluid Flow (2006) This is the same equation as used by Miller/Bellan in: "Direct numerical simulation of a confined three-dimensional gar mixing layer with one evaporating hydrocarbon-droplet-laden stream" J. Fluid Mech. (1999) but they have rearranged it in the form of: dm/dt = - Sh / (3 * Sc) * m / tau * ln(1+BM) using particle-relaxation time tau. For detais of the analytical solution contact t.weg.nosp@m.mann.nosp@m.@aia..nosp@m.rwth.nosp@m.-aach.nosp@m.en.d.nosp@m.e

The heat balance equation for a droplet was given by Faeth 1983 to be (tp1-tp0)/dt = (pi * dp1 * Nu * km * (T_f - tp1) + dm1 * LH_ev)/(mp1 * cp) again this is the same equation as used by Miller/Bellan in: "Direct numerical simulation of a confined three-dimensional gar mixing layer with one evaporating hydrocarbon-droplet-laden stream" J. Fluid Mech. (1999) but they have rearranged it in the form of: dT/dt = Nu / (3 * Pr) * cp_F/cp_L * 1/tau_p * (T_f - T_p) + dm/m * L_ev/cp_L For detais of the analytical solution contact t.weg.nosp@m.mann.nosp@m.@aia..nosp@m.rwth.nosp@m.-aach.nosp@m.en.d.nosp@m.e

NOTE: the type of differential equation changes for Nu -> 0 and is merely: dT/dt = dm/m * L_ev/cp_L

Implements LPTBase< nDim >.

Definition at line 507 of file lptspherical.cpp.

507 {
508 // on first time step for this particle:
509 // determine special timestep size which is used to get continuous particle generation
510 // i.e. the particle has not lived for the entire timeStep!
511 const MFloat dt = s_backPtr->m_timeStep - m_creationTime;
512 ASSERT(dt > 0, "Timestep < 0");
513
514 //#ifdef LPT_DEBUG
515 if(isnan(m_dM) || isnan(m_diameter) || isnan(m_temperature)) {
516 cerr << globalTimeStep << " " << m_dM << " " << m_diameter << " " << m_temperature << endl;
517 mTerm(1, AT_, "Nan input values for evaporation!");
518 }
519 //#endif
520
521 // sub-scripts:
522 // fluid : (continous) fluid phase
523 // liquid: (disperse, particle) liquid phase
524 // vap : vapour phase of the originally liquid particle
525 // mix : mixture of vapour and fluid phase at the bndry-state
526
527 // surf : surface state at the droplet interface
528 // bndry : (reference) boundray layer state (including fluid and vapour)
529
530
531 // NOTE: interpolate all fluid variables for evaporation to the particle position and
532 // already set weights for later source term redistribution!
533 // As in "Direct numerical simulation of a confined three-dimensional gas mixing layer
534 // with one evaporating hydrocarbon-droplet-laden stream", R.S. Miller and J. Bellan
535 m_redistWeight.clear();
536 MFloat p_fluid = -1;
537 MFloat T_fluid = -1;
538 MFloat Y_fluid = 0;
539 if(!s_backPtr->m_massCoupling) {
542 } else {
544 Y_fluid, m_redistWeight);
545 }
546
547 // particles with small diameters are evaporating fully
548 if(m_diameter <= s_backPtr->m_sizeLimit) {
549 m_dM = sphericalMass() / dt;
550 m_diameter = 0.0;
551 isInvalid() = true;
552 fullyEvaporated() = true;
553 m_heatFlux = 0.0;
554 return;
555 }
556
557 if(hadWallColl()) {
558 // special post-wall collision treatment:
559 m_dM = 0;
560 m_heatFlux = 0.0;
561 return;
562 }
563
564 const MFloat volume = sphericalVolume();
565 ASSERT(volume > 0, "Invalid volume!");
566
567 static constexpr MFloat convEvap = 1E-10;
568 const MFloat oldDiameter = m_diameter;
569
570 MFloat previousTemp = m_temperature;
571 MInt heatStep = 0;
572
573 const MFloat oldMass = sphericalMass();
574 const MFloat oldTemperature = m_temperature;
575 const MFloat oldSheddedMass = 1.0 / 6.0 * PI * s_backPtr->m_material->density(m_temperature) * POW3(m_shedDiam);
576
577 // heat capacity of the liquid phase
578 const MFloat cp_liquid = s_backPtr->m_material->cp(m_temperature);
579
580 static constexpr MBool belanHarstad = true;
581 if(belanHarstad) {
582 // 0) get material properties:
583
584 // boiling point of the disperse phase
585 const MFloat T_Boil = s_backPtr->m_material->boilingPoint();
586 // referenece pressure for the boiling point of the disperse phase
587 const MFloat p_Boil = s_backPtr->m_material->bpRefPressure();
588
589 // specific gas constant of the vapour of the originally disperse phase
590 // NOTE: in the non-dimensional formulation: 1/gamma * M_ref / M_p
591 const MFloat gasConstant_vap = s_backPtr->m_material->gasConstant();
592
593 // molar weight ration (disperse/continuous) M_p / M_ref
594 const MFloat molWeightRatio = s_backPtr->m_material->molWeightRatio();
595
596 // NOTE: for the dimensional case this is just 1
597 const MFloat gammaMinusOne = s_backPtr->m_material->gammaMinusOne();
598
599 do {
600 previousTemp = m_temperature;
601
602 // particles with small diameters are evaporating fully
603 if(m_diameter <= s_backPtr->m_sizeLimit) {
604 m_dM = oldMass / dt;
605 m_diameter = 0.0;
606 m_temperature = oldTemperature;
607 isInvalid() = true;
608 fullyEvaporated() = true;
609 m_heatFlux = 0.0;
610 break;
611 }
612
613 // 1) use the 1/3-rule to interpolate boundary layer temperature:
614 const MFloat T_bndry = 2.0 / 3.0 * m_temperature + 1.0 / 3.0 * T_fluid;
615
616 // 2) use this reference temperture to calculate all material properties:
617
618 // viscosity of the continous phase
619 MFloat viscosity_fluid = s_backPtr->m_material->dynViscosityFun(T_bndry);
620 if(viscosity_fluid < 0) {
621 viscosity_fluid = numeric_limits<MFloat>::epsilon();
622 }
623
624 // diffusion coefficient
625 MFloat diffusionC = s_backPtr->m_material->diffusionCoefficient(T_bndry);
626 ASSERT(diffusionC > 0, "ERROR: Invalid diffusion coefficient.");
627
628 // latent heat of Evaporation of the liquid/disperse phase
629 // MFloat lH_ev = s_backPtr->m_material->latentHeatEvap(T_bndry);
630 MFloat lH_ev = s_backPtr->m_material->latentHeatEvap(m_temperature);
631
632 // thermal conductivity of the fluid/continous/gas phase
633 MFloat lamda_fluid = s_backPtr->m_material->airThermalConductivity(T_bndry);
634 if(lamda_fluid < 0) {
635 lamda_fluid = numeric_limits<MFloat>::epsilon();
636 }
637
638 // thermal condictivity of the liquid/disperse phase
639 const MFloat lamda_vap = s_backPtr->m_material->thermalConductivity(T_bndry);
640
641 // dynamic viscosity of the vapour phase
642 const MFloat viscosity_vap = s_backPtr->m_material->dynamicViscosity(T_bndry);
643
644 // density of the vapour from the originally liquid/disperse phase
645 const MFloat density_vap = p_fluid / (gasConstant_vap * T_bndry);
646
647 // Schmidt-number Sc: viscous diffusion rate / molecular diffusion rate
648 // NOTE: in dimensional form for Ranz-Marshall correlation!
649 const MFloat Sc = viscosity_fluid / (m_fluidDensity * diffusionC) * s_Sc;
650
651 // Prandtl-number of the fluid/continous/gas phase
652 const MFloat Pr = s_backPtr->m_material->airPrandtl(T_bndry) * s_Pr;
653
654 // 3) surface equilibrium mole fraction
655
656 // surface mole fraction is obtained from equilibrium assumption
657 // (partial pressure of disperse-material vapour is equal to the equilibrium vapour temperature
658 // at the drop temperature) which is used to solve the Clausius-Clapeyron
659 // equation for X_F,s (X_surf)
660 MFloat X_surf = p_Boil / p_fluid * exp(lH_ev / gasConstant_vap * (1.0 / T_Boil - 1.0 / m_temperature));
661
662 static constexpr MFloat X_surfLimit = 0.99999;
663 if(X_surf > X_surfLimit) {
664 X_surf = X_surfLimit;
665 } else if(X_surf < 0) {
666 X_surf = 1.0 - X_surfLimit;
667 }
668
669 // 4) non-equilibrium corrections to the surface mole-fraction
670 static constexpr MBool nonEquilibrium = true;
671 MFloat beta = NAN;
672 if(nonEquilibrium) {
673 /*
674 // 4.1) the beta-factor
675 // NOTE: in dimensional system
676 if(heatStep == 0) {
677 beta = (cp_fluid * oldDM) / (2.0 * PI * lamda_fluid * m_diameter) * s_Pr * s_Re;
678 } else {
679 beta = (cp_fluid * m_dM) / (2.0 * PI * lamda_fluid * m_diameter) * s_Pr * s_Re;
680 }
681 */
682
683 // blowing Re-number
684 const MFloat Re_b = m_dM / (PI * viscosity_fluid * m_diameter) * s_Re;
685 beta = 0.5 * Pr * Re_b;
686
687 // 4.2) the Langmuir-Knudsen law
688 // dimensionless Knudsen-layer parameter ( Lk / diameter)
689 const MFloat Lk_d =
690 viscosity_fluid * sqrt(2.0 * PI * m_temperature * gasConstant_vap) / (Sc * p_fluid * m_diameter * s_Re);
691
692 // non-equilibrium correction:
693 X_surf = X_surf - (2.0 * beta * Lk_d);
694
695 // limiting...
696 if(X_surf < 0) {
697 X_surf = 1.0 - X_surfLimit;
698 }
699 }
700
701 ASSERT(X_surf <= 1.0, "ERROR: Invalid corrected fuel surface mole concentration (>100%): " + to_string(X_surf));
702 ASSERT(X_surf >= 0.0, "ERROR: Invalid corrected fuel surface mole concentration (<0%): " + to_string(X_surf));
703
704 // 5) surface fuel mass fraction
705 MFloat Y_surf = X_surf * molWeightRatio / (X_surf * molWeightRatio + (1.0 - X_surf));
706
707 ASSERT(Y_surf <= 1.0, "ERROR: Invalid fuel surface mass concentration (>100%): " + to_string(Y_surf));
708 if(std::isnan(Y_surf)) {
709 cerr << "X_surf " << X_surf << " m_temperature " << m_temperature << " " << p_fluid << m_partId << " "
710 << m_position[0] << " " << m_position[1] << " " << m_position[2] << endl;
711 }
712
713 // 6) Spalding mass transfer number BM
714 // BM = (Y_F,s - Y_F,infty)/(1-Y_F,s)
715 // where Y is the fuel mass fraction at the surface (s) and
716 // Y_F,infty is the fuel mass fraction at the the far-field conditions
717 // for the droplet particle
718 MFloat BM = (Y_surf - Y_fluid) / (1.0 - Y_surf);
719 if(BM < MFloatEps) {
720 // cerr << "BM " << BM << " Y_surf " << Y_surf << " Y_inf " << Y_fluid << " "
721 // << oldDiameter << " " << beta << " " << X_surf << endl;
722 BM = 0;
723 }
724
725 // 7) Compute Mixture of disperse material-vapour and continous phase in the boundary layer
726 // based on Yuen and Chen, 1976 i.e. the 1/3-rule / the Wilke Rule (Edwards et al., 1979)
727
728 // boundary layer disperse-material vapour mass fraction values chosen as proposed by
729 MFloat Y_bndry = 2.0 / 3.0 * Y_surf + 1.0 / 3.0 * Y_fluid;
730
731 ASSERT(Y_bndry <= 1.0, "ERROR: Invalid fuel boundary layer mass concentration (>100%): " + to_string(Y_bndry));
732
733 if(std::isnan(Y_bndry)) {
734 cerr << "Y_surf " << Y_surf << " Y_f " << Y_fluid << endl;
735 }
736
737 // boundary layer disperse vapour mole fraction
738 MFloat X_bndry = -Y_bndry / (Y_bndry * molWeightRatio - Y_bndry - molWeightRatio);
739
740
741 // thermal conductivity of vapour+fluid mixture
742 MFloat lamda_vapFluid = POW2(1.0 + sqrt(lamda_vap / lamda_fluid) * pow(1 / molWeightRatio, 0.25))
743 / sqrt(8.0 * (1.0 + molWeightRatio));
744 if(isnan(lamda_vapFluid)) {
745 cerr << "lamda_vap " << lamda_vap << " lamda_fluid " << lamda_fluid << " lamda_vapFluid " << lamda_vapFluid
746 << endl;
747 }
748
749 MFloat lamda_fluidVap = POW2(1.0 + sqrt(lamda_fluid / lamda_vap) * pow(molWeightRatio, 0.25))
750 / sqrt(8.0 * (1.0 + 1 / molWeightRatio));
751
752 MFloat lamda_mix = X_bndry * lamda_vap / (X_bndry + (1.0 - X_bndry) * lamda_vapFluid)
753 + (1.0 - X_bndry) * lamda_fluid / (X_bndry * lamda_fluidVap + (1.0 - X_bndry));
754 if(isnan(lamda_mix)) {
755 cerr << "X_bndry " << X_bndry << " lamda_vap " << lamda_vap << " lamda_vapFluid " << lamda_vapFluid << endl;
756 }
757 ASSERT(!std::isnan(lamda_mix), "ERROR: lamda_mix is NaN!");
758
759 // mixture of dynamic viscosity
760 MFloat viscosity_vapFluid = POW2(1.0 + sqrt(viscosity_vap / viscosity_fluid) * pow(1 / molWeightRatio, 0.25))
761 / sqrt(8.0 * (1.0 + molWeightRatio));
762
763 MFloat viscosity_fluidVap = POW2(1.0 + sqrt(viscosity_fluid / viscosity_vap) * pow(molWeightRatio, 0.25))
764 / sqrt(8.0 * (1.0 + 1 / molWeightRatio));
765
766 MFloat viscosity_mix = X_bndry * viscosity_vap / (X_bndry + (1.0 - X_bndry) * viscosity_vapFluid)
767 + (1.0 - X_bndry) * viscosity_fluid / (X_bndry * viscosity_fluidVap + (1.0 - X_bndry));
768
769 ASSERT(!std::isnan(viscosity_mix),
770 "ERROR: viscosity_mix is NaN!" + to_string(X_bndry) + " " + to_string(viscosity_vapFluid));
771
772
773 // const MFloat density_mix = 1.0 / (Y_bndry / density_vap + (1.0 - Y_bndry) / m_fluidDensity);
774 // ASSERT(density_mix > 0, "ERROR: Invalid mixture density (<0).");
775 // debug!
776 // const MFloat density_mix = s_backPtr->m_material->density(m_temperature);
777 // const MFloat density_mix = m_fluidDensity;
778 const MFloat density_mix = Y_bndry * density_vap + (1.0 - Y_bndry) * m_fluidDensity;
779
780 // heat capacity of the mixture
781 // const MFloat cp_mix = Y_bndry * cp_liquid + (1-Y_bndry) * cp_fluid;
782
783 // 8) Compute Nu and Sh-number based on emperical correlations
784
785 // particle Reynolds-Number with slip-velocity
786 // NOTE: in dimensional formulation, following:
787 //"A comparative study of numerical models for Eulerian-Lagrangian simulations
788 // of turbulent evaporating sprays" D.I. Kolaitis, M.A. Founti
789 // Int. J. of Heat and Fluid Flow 27 (2006) 424-435
790 // is using the surface/film viscosity over the gas/fluid viscosity
791 MFloat Re = particleRe(m_fluidDensity, magRelVel(m_fluidVel.data(), &m_velocity[0]), viscosity_mix) * s_Re;
792
793 // Sherwood number (Sh) is calculated using the Ranz-Marshall correlation (1952)
794 // Sh = Convective Mass transfer / Diffusion rate
795 // Limitations of the Ranz-Marshall correlation Re < 200, Pr < 250, Sc < 250
796 // NOTE: using dimensional Re/Sc-numbers for the correlation!
797 const MFloat Sh = 2.0 + 0.552 * sqrt(Re) * pow(Sc, 1.0 / 3.0);
798
799 //#ifdef LPT_DEBUG
800 ASSERT(!isnan(Sh), "Sh is nan!" + to_string(Re) + " " + to_string(Sc));
801 //#endif
802
803 // Nusselt number Nu : Convective heat transfer / Conductive heat transfer
804 // NOTE: using dimensional Re/Pr-numbers for the correlation!
805 MFloat Nu = 2.0 + 0.552 * sqrt(Re) * pow(Pr, 1.0 / 3.0);
806
807 //#ifdef LPT_DEBUG
808 if(isnan(Nu)) cerr << " Re " << Re << " Pr " << Pr << endl;
809 //#endif
810
811 // non-equilibrium correction of Nusselt-number
812 if(nonEquilibrium) {
813 if(beta > MFloatEps) {
814 Nu = Nu * (beta / (exp(beta) - 1));
815 }
816#ifdef LPT_DEBUG
817 if(isnan(Nu)) cerr << "beta " << beta << endl;
818#endif
819 }
820
821 MFloat mass = oldMass;
822
823 // 9) solve evaporation equation (dm/dt)
824 if(s_backPtr->m_evaporation) {
825 MFloat A = 0;
840 if(BM < MFloatEps) {
841 mass = oldMass;
842 } else {
843 A = -2.0 / 3.0 * density_mix * PI * diffusionC * Sh * log(1 + BM)
844 * pow(6.0 / (PI * s_backPtr->m_material->density(m_temperature)), 1.0 / 3.0) * dt / (s_Sc * s_Re);
845
846 const MFloat B = pow(oldMass, 2.0 / 3.0);
847
848 //#ifdef LPT_DEBUG
849 if(isnan(B)) {
850 cerr << "oldMass " << oldMass << endl;
851 }
852 if(isnan(A)) {
853 cerr << "A " << A << " density_mix " << density_mix << " diffusion Coefficient " << diffusionC << " SH "
854 << Sh << " BM " << BM << endl;
855 }
856 //#endif
857
858 // limit mass to be > 0
859 if(fabs(A) > B) {
860 mass = 0.0;
861 } else {
862 mass = pow(B + A, 3.0 / 2.0);
863 }
864 }
865
866 ASSERT(!std::isnan(mass), "ERROR: Mass is NaN!");
867
868 // NOTE: the direction from m_dM is switched, instead of beeing negtive for evaporation
869 // the sign is changed here!
870 // TODO-timw labels:LPT switch m_dM around to match the description in the literature!
871 // use below and switch signs everywhere!
872 // m_dM = (mass - oldMass) / dt;
873 m_dM = (oldMass - mass) / dt;
874
875 constexpr static MBool limitCondensation = true;
876 if(limitCondensation && m_dM < 0) {
877 m_dM = 0;
878 mass = oldMass;
879 }
880
881 ASSERT(!std::isnan(m_dM), "ERROR: Evaporation rate is NaN!");
882 ASSERT(mass - oldMass <= 0 || abs(mass) < numeric_limits<MFloat>::epsilon(),
883 "ERROR: droplets are increasing in size due to condensation! m_dM " + to_string(m_dM) + " oldMass "
884 + to_string(oldMass) + " mass " + to_string(mass));
885
886
887 if(mass > 0) {
888 m_diameter = pow(mass / s_backPtr->m_material->density(m_temperature) * 6.0 / PI, 1.0 / 3.0);
889 // reduce shedded diameter consistently based on evaporated mass m_dM * dt
890 // relevant for KH-secondary break-up
891 const MFloat reducedSheddedMass = oldSheddedMass - m_dM * dt;
892 m_shedDiam = pow(reducedSheddedMass / s_backPtr->m_material->density(m_temperature) * 6.0 / PI, 1.0 / 3.0);
893
894 } else { // catch case in which particle evaporates completely
895 m_dM = oldMass / dt;
896 m_diameter = 0.0;
897 mass = 0.0;
898 isInvalid() = true;
899 fullyEvaporated() = true;
900 m_temperature = oldTemperature;
901 m_heatFlux = 0;
902 // cerr << "Evap. Completly " << mass << " " << oldMass << " " << BM
903 // << " " << oldTemperature << " " << m_temperature << " " << density_mix << " " <<
904 // A << " " << Sh << " " << Re << " " << Sc << " " << dt << endl;
905 // cerr << m_temperature << " " << oldTemperature << " " << T_bndry
906 // << " " << T_fluid
907 // << endl;
908 // cerr << "Fully evaporating particle with mass " << oldMass * m_noParticles << endl;
909 break;
910 }
911 }
912
913 // 10) solve temperature equation (dT/dt)
914
925 if(Nu > 100 * MFloatEps) {
926 const MFloat c1 =
927 PI * 0.5 * (m_diameter + oldDiameter) * Nu * lamda_mix * dt / (mass * cp_liquid) / (s_Pr * s_Re);
928 MFloat c2 =
929 T_fluid
930 - m_dM * lH_ev / (Nu * lamda_mix * PI * 0.5 * (m_diameter + oldDiameter)) * (s_Re * s_Pr * gammaMinusOne);
931 m_temperature = c2 + (oldTemperature - c2) * exp(-c1);
932 } else {
937 // negative sign due to changed sign of evaporation rate!
938 m_temperature = oldTemperature - m_dM / (mass * cp_liquid) * lH_ev * dt * gammaMinusOne;
939 }
940
941#ifdef LPT_DEBUG
942 if(std::isnan(m_temperature)) {
943 cerr << "m_diam " << m_diameter << " Nu " << Nu << " thCond " << lamda_mix << endl;
944 cerr << "m_t " << m_temperature << " oldT " << oldTemperature << endl;
945 cerr << " Re " << Re << " Pr " << Pr << " " << T_bndry << " " << magRelVel(m_fluidVel.data(), &m_velocity[0])
946 << " " << viscosity_mix << " " << m_fluidDensity << " " << 2.0 + 0.552 * sqrt(Re) * pow(Pr, 1.0 / 3.0)
947 << endl;
948 TERM(-1);
949 }
950#endif
951
952 if(m_temperature < 0) {
953 m_temperature = MFloatEps;
954 }
955
956 heatStep++;
957
958 } while(abs(m_temperature - previousTemp) > convEvap && heatStep < 100);
959
960 } else {
961 // constant evaporation rate used for reference/validation cases
962 static MFloat dm_dt = (oldMass / dt) / 100000.0;
963 m_dM = dm_dt;
964 if(m_dM * dt > oldMass) {
965 m_dM = oldMass / dt;
966 }
967 m_diameter = pow((oldMass - m_dM * dt) / s_backPtr->m_material->density(m_temperature) * 6.0 / PI, 1.0 / 3.0);
968 }
969
970
971 if(m_temperature < 0) {
972 TERMM(-1, "Invalid temperature!");
973 }
974
975 // store particle energy change in heat-flux
976 if(s_backPtr->m_heatCoupling) {
977 const MFloat mass = sphericalMass();
978 // see "Direct numerical simulation of a confined three-dimensional gas mixing layer with one
979 // evaporating hydrocarbon-droplet-laden stream" by R.S. Miller and J. Bellan
980 // in J. Fluid Mech. (1999) for reference!
981 m_heatFlux = mass * cp_liquid * (m_temperature - oldTemperature) / dt * 1 / s_backPtr->m_material->gammaMinusOne();
982
983
984 ASSERT(!std::isnan(m_heatFlux) && !std::isinf(m_heatFlux),
985 "ERROR: m_heatFlux is NaN or inf! " + to_string(m_temperature) + " " + to_string(oldTemperature) + " "
986 + to_string(volume));
987
988 if(s_backPtr->m_evaporation) {
989 m_heatFlux -= (m_dM * cp_liquid * m_temperature * 1 / s_backPtr->m_material->gammaMinusOne());
990 }
991
992
993 ASSERT(!std::isnan(m_heatFlux) && !std::isinf(m_heatFlux), "ERROR: m_heatFlux is NaN or inf!");
994 }
995}
MFloat m_creationTime
creation time modifier
Definition: lptbase.h:50
BitsetType::reference fullyEvaporated()
Definition: lptbase.h:218
MFloat m_shedDiam
shedding diameter
Definition: lptspherical.h:82
static MFloat s_Pr
Definition: lptspherical.h:97
MFloat sphericalVolume() const
Calculate the current volume.
Definition: lptspherical.h:123
MFloat m_temperature
temperature
Definition: lptspherical.h:78
static MFloat s_Sc
Definition: lptspherical.h:98
MFloat sphericalMass() const
Calculate the current mass.
Definition: lptspherical.h:126
MFloat magRelVel(const MFloat *const velocity1, const MFloat *const velocity2) const
Calculate the magnitude of the relative velocity of the two given velocity vectors.
Definition: lptspherical.h:131
MFloat particleRe(const MFloat velocity, const MFloat density, const MFloat dynamicViscosity)
Calculate the particle reynoldsnumber.
Definition: lptspherical.h:149
void interpolateAllFluidVariables(const MInt cellId, const MFloat *const position, MFloat *const velocity, MFloat &density, MFloat &pressure, MFloat &temperature, MFloat &species, std::vector< MFloat > &weights)
Definition: lptspherical.h:189
static MFloat s_Re
Definition: lptspherical.h:96
constexpr Real POW3(const Real x)
Definition: functions.h:123
MInt globalTimeStep
bool MBool
Definition: maiatypes.h:58

◆ fParticleRelTime()

template<MInt nDim>
MFloat LPTSpherical< nDim >::fParticleRelTime ( const MFloat  dynamicViscosity)
inline

Definition at line 154 of file lptspherical.h.

154 {
155 return 18.0 * dynamicViscosity / (m_diameter * m_diameter * s_backPtr->m_material->density(m_temperature));
156 }

◆ heatCoupling()

template<MInt nDim>
void LPTSpherical< nDim >::heatCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 215 of file lptspherical.cpp.

215 {
216 const MFloat relT = (s_backPtr->m_timeStep - m_creationTime) / s_backPtr->m_timeStep;
217
218 // kin. energy change due to evaporation
219 MFloat velMagSquared = 0;
220 for(MInt i = 0; i < nDim; i++) {
221 velMagSquared += POW2(m_oldVel[i]);
222 }
223
224 // NOTE: must be negative if going trom the disperse/liquid(LPT) to the continous/fluid (FV)
225 const MFloat energySource = m_noParticles * (m_heatFlux - 0.5 * m_dM * velMagSquared);
226
227 if(s_backPtr->m_couplingRedist) {
228 for(MInt n = 0; n < (signed)m_neighborList.size(); n++) {
229 // a weight is used to distribute the source term to multiple cells
230 s_backPtr->a_heatFlux(m_neighborList[n]) += m_redistWeight.at(n) * energySource * relT;
231 }
232 } else {
233 s_backPtr->a_heatFlux(m_cellId) += energySource * relT;
234 }
235}
std::vector< MInt > m_neighborList
Definition: lptbase.h:82
MInt m_noParticles
parceled particles
Definition: lptspherical.h:84

◆ initVelocityAndDensity()

template<MInt nDim>
void LPTSpherical< nDim >::initVelocityAndDensity ( )
inline

Definition at line 166 of file lptspherical.h.

166 {
167 std::array<MFloat, nDim + 1> result{};
168 std::vector<MFloat> weights;
169 this->template interpolateAndCalcWeights<0, nDim + 1>(m_cellId, m_position.data(), result.data(), weights);
170 for(MInt i = 0; i < nDim; i++) {
171 m_oldFluidVel[i] = result[i];
172 m_fluidVel[i] = result[i];
173 }
174 m_oldFluidDensity = result[nDim];
175 m_fluidDensity = result[nDim];
176 }

◆ interpolateAllFluidVariables() [1/2]

template<MInt nDim>
void LPTSpherical< nDim >::interpolateAllFluidVariables ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  velocity,
MFloat density,
MFloat pressure,
MFloat temperature,
MFloat species,
std::vector< MFloat > &  weights 
)
inlineprivate

Definition at line 189 of file lptspherical.h.

191 {
192 std::array<MFloat, nDim + 4> result{};
193 this->template interpolateAndCalcWeights<0, nDim + 4>(cellId, position, result.data(), weights);
194 for(MInt n = 0; n < nDim; n++) {
195 velocity[n] = result[n];
196 }
197 density = result[nDim];
198 pressure = result[nDim + 1];
199 temperature = result[nDim + 2];
200 species = result[nDim + 3];
201 }

◆ interpolateAllFluidVariables() [2/2]

template<MInt nDim>
void LPTSpherical< nDim >::interpolateAllFluidVariables ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  velocity,
MFloat density,
MFloat pressure,
MFloat temperature,
std::vector< MFloat > &  weights 
)
inlineprivate

Definition at line 202 of file lptspherical.h.

204 {
205 std::array<MFloat, nDim + 3> result{};
206 this->template interpolateAndCalcWeights<0, nDim + 3>(cellId, position, result.data(), weights);
207 for(MInt n = 0; n < nDim; n++) {
208 velocity[n] = result[n];
209 }
210 density = result[nDim];
211 pressure = result[nDim + 1];
212 temperature = result[nDim + 2];
213 }

◆ interpolateVelocityAndDensity()

template<MInt nDim>
void LPTSpherical< nDim >::interpolateVelocityAndDensity ( const MInt  cellId,
const MFloat *const  position,
MFloat *const  velocity,
MFloat density,
std::vector< MFloat > &  weights 
)
inlineprivate

Definition at line 179 of file lptspherical.h.

180 {
181 std::array<MFloat, nDim + 1> result{};
182 this->template interpolateAndCalcWeights<0, nDim + 1>(cellId, position, result.data(), weights);
183 for(MInt n = 0; n < nDim; n++) {
184 velocity[n] = result[n];
185 }
186 density = result[nDim];
187 }

◆ magRelVel()

template<MInt nDim>
MFloat LPTSpherical< nDim >::magRelVel ( const MFloat *const  velocity1,
const MFloat *const  velocity2 
) const
inline

Definition at line 131 of file lptspherical.h.

131 {
132 MFloat magnitude = 0.0;
133 for(MInt i = 0; i < nDim; i++) {
134 magnitude += POW2(velocity1[i] - velocity2[i]);
135 }
136 return sqrt(magnitude);
137 }

◆ magVel()

template<MInt nDim>
MFloat LPTSpherical< nDim >::magVel ( ) const
inline

Definition at line 140 of file lptspherical.h.

140 {
141 MFloat magnitude = 0.0;
142 for(MInt i = 0; i < nDim; i++) {
143 magnitude += POW2(m_velocity[i]);
144 }
145 return sqrt(magnitude);
146 }

◆ massCoupling()

template<MInt nDim>
void LPTSpherical< nDim >::massCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 131 of file lptspherical.cpp.

131 {
132 if(m_creationTime > s_backPtr->m_timeStep) {
133 cerr << "Limiting creation time from " << m_creationTime << " to " << s_backPtr->m_timeStep - MFloatEps << endl;
134 m_creationTime = s_backPtr->m_timeStep - MFloatEps;
135 }
136
137 const MFloat relT = (s_backPtr->m_timeStep - m_creationTime) / s_backPtr->m_timeStep;
138
139 if(m_dM < 0 || relT < 0 || relT > 1) {
140 cerr << m_creationTime << " " << m_partId << " " << m_dM << " " << relT << " " << s_backPtr->m_timeStep << endl;
141 mTerm(1, AT_ "Invalid mass flux");
142 }
143
144 // NOTE: negative massFlux means going from liquid/disperse(LPT) to fluid/continous(FV)
145 const MFloat massFlux = -m_noParticles * m_dM * relT;
146
147 s_backPtr->m_sumEvapMass -= (massFlux * s_backPtr->m_timeStep);
148
149 if(!s_backPtr->m_couplingRedist) {
150 s_backPtr->a_massFlux(m_cellId) += massFlux;
151 } else {
152 for(MInt n = 0; n < (signed)m_neighborList.size(); n++) {
153 s_backPtr->a_massFlux(m_neighborList[n]) += m_redistWeight.at(n) * massFlux;
154 }
155 }
156}

◆ momentumCoupling()

template<MInt nDim>
void LPTSpherical< nDim >::momentumCoupling
private
Author
Sven Berger, Tim Wegmann

Definition at line 164 of file lptspherical.cpp.

164 {
165 const MFloat relT = (s_backPtr->m_timeStep - m_creationTime) / s_backPtr->m_timeStep;
166
167 // NOTE: as the momentum coupling is applied after the evaporation, the original mass needs
168 // to be used for the force coupling!
169 const MFloat mass =
170 (s_backPtr->m_evaporation) ? m_dM * relT * s_backPtr->m_timeStep + sphericalMass() : sphericalMass();
171
172 array<MFloat, nDim> force{};
173 array<MFloat, 3> evapMom{F0, F0, F0};
174
175 for(MInt i = 0; i < nDim; i++) {
176 // momentum flux due to drag force
177 const MFloat invDensityRatio = (abs(m_densityRatio) <= MFloatEps) ? 1.0 : 1.0 / m_densityRatio;
178 force[i] = m_noParticles * mass * (m_accel[i] - ((1.0 - invDensityRatio) * s_Frm[i])) * relT;
179
180 // momentum flux due to mass change going into the continous/fluid(FV)
181 // its energy is considered in the heat-coupling
182 if(s_backPtr->m_evaporation) evapMom[i] = -m_noParticles * m_dM * m_velocity[i] * relT;
183 }
184
185 // work done by the momentum
186 // const MFloat work = std::inner_product(force.begin(), force.end(), m_velocity.begin(), 0.0);
187 const MFloat work = std::inner_product(force.begin(), force.end(), m_oldVel.begin(), 0.0);
188
189
190 if(!s_backPtr->m_couplingRedist) {
191 for(MInt i = 0; i < nDim; i++) {
192 s_backPtr->a_momentumFlux(m_cellId, i) += (force[i] + evapMom[i]);
193 }
194 s_backPtr->a_workFlux(m_cellId) += work;
195
196 } else {
197 ASSERT(m_redistWeight.size() == m_neighborList.size(),
198 "Invalid " + to_string(m_redistWeight.size()) + "!=" + to_string(m_neighborList.size()));
199 for(MInt n = 0; n < (signed)m_neighborList.size(); n++) {
200 // a weightHeat is used to distribute the source term to multiple cells...
201 for(MInt i = 0; i < nDim; i++) {
202 s_backPtr->a_momentumFlux(m_neighborList[n], i) += m_redistWeight.at(n) * (force[i] + evapMom[i]);
203 }
204 s_backPtr->a_workFlux(m_neighborList[n]) += m_redistWeight.at(n) * work;
205 }
206 }
207}
static std::array< MFloat, nDim > s_Frm
Definition: lptspherical.h:100

◆ motionEquation()

template<MInt nDim>
void LPTSpherical< nDim >::motionEquation
overridevirtual
  1. Predictor step
  2. get velocity, density and velocity magnitude at the predicted position
  1. corrector step

Implements LPTBase< nDim >.

Definition at line 239 of file lptspherical.cpp.

239 {
240 const MFloat dt = s_backPtr->m_timeStep - m_creationTime;
241 ASSERT(dt > 0, "Timestep < 0");
242
243 // NOTE: at this point old means 1 time-Step ago and the current values will be updated below!
248
249#ifdef LPT_DEBUG
250 MLong debugPartId = -1;
251 if(m_partId == debugPartId) {
252 cerr << "BT " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << endl;
253 }
254#endif
255
256 if(firstStep()) {
257 for(MInt i = 0; i < nDim; i++) {
258 m_accel[i] = s_Frm[i];
259 m_oldAccel[i] = s_Frm[i];
260 }
261 } /*else {
262 m_creationTime = 0;
263 } */
264
265 for(MInt i = 0; i < nDim; i++) {
266 ASSERT(!isnan(m_oldFluidVel[i]), "");
267 }
268 ASSERT(m_oldFluidDensity > 0, "");
269
270 // reduce variance between runs (round to 9 decimal places)
271 // TODO-timw labels:LPT,totest check if rounding is still necessary?
272 const MFloat invDensityRatio =
273 1.0 / (static_cast<MFloat>(ceil(s_backPtr->m_material->density(m_temperature) / m_oldFluidDensity * 1E9)) / 1E9);
274
275 m_densityRatio = 1 / invDensityRatio;
276
278 array<MFloat, nDim> predictedPos{};
279 array<MFloat, nDim> predictedVel{};
280
281 // predict position and veloctity
282 for(MInt i = 0; i < nDim; i++) {
283 predictedVel[i] = m_oldVel[i] + dt * m_oldAccel[i];
284 predictedPos[i] = m_oldPos[i] + dt * m_oldVel[i] * s_lengthFactor + 0.5 * dt * dt * m_oldAccel[i] * s_lengthFactor;
285 }
286
287#ifdef LPT_DEBUG
288 if(m_partId == debugPartId) {
289 cerr << "PT " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << endl;
290 }
291#endif
292
294 // find the predicted CellId at the predicted position around the previous cellId
295 const MInt predictedCellId = s_backPtr->grid().findContainingLeafCell(&predictedPos[0], m_cellId);
296
297 if(predictedCellId < 0 || m_cellId < 0) {
298 // particle has left the LPT bounding-box completely
299 //->to-be removed!
300 isInvalid() = true;
301 return;
302 }
303
304 ASSERT(m_cellId > -1, "Invalid cell!");
305 ASSERT(predictedCellId > -1, "Invalid predicetd cell!");
306 ASSERT(s_backPtr->c_isLeafCell(predictedCellId), "Invalid cell!");
307 ASSERT(predictedCellId > -1, "Invalid cell!");
308
309 array<MFloat, nDim> fluidVel{};
310 MFloat fluidDensity{};
311 vector<MFloat> predictedWeights(0);
312 interpolateVelocityAndDensity(predictedCellId, predictedPos.data(), fluidVel.data(), fluidDensity, predictedWeights);
313
314 const MFloat T = s_backPtr->a_fluidTemperature(m_cellId);
315
316 MFloat fluidViscosity = s_backPtr->m_material->dynViscosityFun(T);
317
319 if(s_backPtr->m_dragModelType == 0) {
320 for(MInt i = 0; i < nDim; i++) {
321 m_velocity[i] = predictedVel[i];
322 m_position[i] = predictedPos[i];
323 m_accel[i] = m_oldAccel[i];
324 }
325 } else {
326 switch(s_backPtr->m_motionEquationType) {
327 case 3:
328 case 0: {
329 // see also Crowe et al "Multiphase Flows with Droplets and Particles" 1998
330 // motion equation based on analytical solution of the simplified motion equation
331 // contained when assuming constant old-drag count!
332 // in this case the newton equation takes the form of:
333 // du/dt = a + b * u
334 // for which an exponential analytical solution can be found and
335 // defined by using the old-position at relative time t_old = 0.
336 // for further details contact t.wegmann@aia.rwth-aachen
337 const MFloat relVel_old = magRelVel(&m_oldFluidVel[0], &m_oldVel[0]);
338 const MFloat relVel = magRelVel(&fluidVel[0], &predictedVel[0]);
339
340 //#ifdef LPT_DEBUG
341 if(isnan(relVel)) {
342 cerr << "relVel " << fluidVel[0] << " " << fluidVel[1] << " " << fluidVel[2] << " " << predictedVel[0] << " "
343 << predictedVel[1] << " " << predictedVel[2] << " " << predictedCellId << endl;
344 mTerm(1, AT_, "Invalid relative velocity!");
345 }
346 //#endif
347
348 // get the particle drag based on velocities and density of the old position!
349 const MFloat DC_old = dragFactor(particleRe(relVel_old, m_oldFluidDensity, fluidViscosity) * s_Re) / s_Re
350 * fParticleRelTime(fluidViscosity);
351 // get the particle drag based on velocities and density of the predicted position
352 const MFloat DC = dragFactor(particleRe(relVel, fluidDensity, fluidViscosity) * s_Re) / s_Re
353 * fParticleRelTime(fluidViscosity);
354
355 // average the fluid velocity of old and predicted position
356 // increases stability for flow fields with high velocity gradients!
357 array<MFloat, nDim> avgFlowVel{};
358 for(MInt i = 0; i < nDim; i++) {
359 avgFlowVel[i] = 0.5 * (m_oldFluidVel[i] + fluidVel[i]);
360 }
361 const MFloat avgDC = s_backPtr->m_motionEquationType == 0 ? DC_old : 0.5 * (DC_old + DC);
362
363 // analytical solution assuming constant DC
364 for(MInt i = 0; i < nDim; i++) {
365 m_velocity[i] =
366 avgFlowVel[i] + (1.0 - invDensityRatio) * s_Frm[i] / avgDC
367 + exp(-avgDC * dt) * (m_oldVel[i] - avgFlowVel[i] + (invDensityRatio - 1.0) * s_Frm[i] / avgDC);
368
369 m_accel[i] = (m_velocity[i] - m_oldVel[i]) / dt;
370
371 m_position[i] = m_oldPos[i] + 0.5 * (m_oldVel[i] + m_velocity[i]) * dt * s_lengthFactor;
372 }
373 break;
374 }
375 case 1: {
376 // non-dimensional version based on:
377 // Baumgarten, "Mixture Formation in Internal Combustion Engines", 2005
378 const MFloat relVel = magRelVel(&fluidVel[0], &predictedVel[0]);
379
380 const MFloat Rep = particleRe(relVel, m_oldFluidDensity, fluidViscosity) * s_Re;
381
382 const MFloat CD = dragFactor(Rep) / s_Re * fParticleRelTime(fluidViscosity);
383
384 for(MInt i = 0; i < nDim; i++) {
385 m_accel[i] = CD * (fluidVel[i] - predictedVel[i]) + (1.0 - invDensityRatio) * s_Frm[i];
386 m_velocity[i] = m_oldVel[i] + dt * F1B2 * (m_accel[i] + m_oldAccel[i]);
387 m_position[i] = m_oldPos[i] + dt * F1B2 * (m_velocity[i] + m_oldVel[i]) * s_lengthFactor;
388 }
389 break;
390 }
391 case 2: {
392 // particle moves with fluid velocity
393 for(MInt i = 0; i < nDim; i++) {
394 m_position[i] = m_oldPos[i] + 0.5 * dt * (fluidVel[i] + m_oldVel[i]) * s_lengthFactor;
395 m_velocity[i] = fluidVel[i];
396 m_accel[i] = (m_velocity[i] - m_oldVel[i]) / dt;
397 }
398 break;
399 }
400 default: {
401 mTerm(1, AT_, "Unknown particle corrector equation type!");
402 }
403 }
404 }
405
406#ifdef LPT_DEBUG
407 if(m_partId == debugPartId) {
408 cerr << "AT " << m_velocity[0] << " " << m_velocity[1] << " " << m_velocity[2] << endl;
409 }
410#endif
411
412 // 3. update cellId based on the corrected position and set the new status!
414
415#ifdef LPT_DEBUG
416 for(MInt i = 0; i < nDim; i++) {
417 if(std::isnan(m_accel[i])) {
418 cerr << "Nan acc. for " << s_backPtr->domainId() << " " << m_partId << " " << m_position[0] << " "
419 << m_position[1] << " " << m_position[nDim - 1] << " " << s_backPtr->a_isValidCell(m_cellId) << " "
420 << m_oldPos[0] << " " << m_oldPos[1] << " " << m_oldPos[nDim - 1] << " " << m_creationTime << " "
421 << fluidVel[0] << " " << fluidVel[1] << " " << fluidVel[nDim - 1] << fluidDensity << " " << T << " "
422 << fluidViscosity << " " << m_oldVel[0] << " " << m_oldVel[1] << " " << m_oldVel[nDim - 1] << endl;
423 }
424 }
425#endif
426}
MInt m_oldCellId
Definition: lptbase.h:47
void checkCellChange(const MFloat *oldPosition, const MBool allowHaloNonLeaf=false)
Checks whether position is within cell with number cellId if not, cellId is updated.
Definition: lptbase.cpp:233
MFloat fParticleRelTime(const MFloat dynamicViscosity)
Calculate the reciprocal of the particle relaxation time.
Definition: lptspherical.h:154
static MFloat s_lengthFactor
Definition: lptspherical.h:95
MFloat dragFactor(const MFloat partRe)
Calculate drag factor of the current particle for the given particle Reynolds number....
int64_t MLong
Definition: maiatypes.h:64

◆ operator=()

template<MInt nDim>
LPTSpherical & LPTSpherical< nDim >::operator= ( const LPTSpherical< nDim > &  )
default

◆ particleRe()

template<MInt nDim>
MFloat LPTSpherical< nDim >::particleRe ( const MFloat  velocity,
const MFloat  density,
const MFloat  dynamicViscosity 
)
inline

Definition at line 149 of file lptspherical.h.

149 {
150 return density * velocity * m_diameter / dynamicViscosity;
151 }

◆ resetWeights()

template<MInt nDim>
void LPTSpherical< nDim >::resetWeights ( )
inlineoverridevirtual

Implements LPTBase< nDim >.

Definition at line 111 of file lptspherical.h.

111 {
112 m_neighborList.clear();
113 this->template interpolateAndCalcWeights<0, 0>(m_cellId, m_position.data(), nullptr, m_redistWeight);
114 };

◆ sphericalMass()

template<MInt nDim>
MFloat LPTSpherical< nDim >::sphericalMass ( ) const
inline

Definition at line 126 of file lptspherical.h.

126 {
127 return 1.0 / 6.0 * PI * POW3(m_diameter) * s_backPtr->m_material->density(m_temperature);
128 }

◆ sphericalVolume()

template<MInt nDim>
MFloat LPTSpherical< nDim >::sphericalVolume ( ) const
inline

Definition at line 123 of file lptspherical.h.

123{ return 1.0 / 6.0 * PI * POW3(m_diameter); }

◆ WeberNumber()

template<MInt nDim>
MFloat LPTSpherical< nDim >::WeberNumber ( const MFloat  density,
const MFloat  velocity,
const MFloat  temperature 
)
inline

Definition at line 159 of file lptspherical.h.

159 {
160 return density * velocity * 0.5 * m_diameter / s_backPtr->m_material->spraySurfaceTension(temperature);
161 }

Friends And Related Function Documentation

◆ operator<<

template<MInt nDim>
template<MInt >
std::ostream & operator<< ( std::ostream &  os,
const LPTSpherical< nDim > &  m 
)
friend

Definition at line 221 of file lptspherical.h.

221 {
222 return os << m.m_partId;
223}

Member Data Documentation

◆ m_breakUpTime

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_breakUpTime = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 80 of file lptspherical.h.

◆ m_diameter

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_diameter = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 76 of file lptspherical.h.

◆ m_dM

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_dM = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 86 of file lptspherical.h.

◆ m_fluidDensity

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_fluidDensity = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 65 of file lptspherical.h.

◆ m_fluidVel

template<MInt nDim>
std::array<MFloat, nDim> LPTSpherical< nDim >::m_fluidVel {}

Definition at line 63 of file lptspherical.h.

◆ m_fluidVelMag

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_fluidVelMag = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 88 of file lptspherical.h.

◆ m_heatFlux

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_heatFlux = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 90 of file lptspherical.h.

◆ m_noParticles

template<MInt nDim>
MInt LPTSpherical< nDim >::m_noParticles = -1

Definition at line 84 of file lptspherical.h.

◆ m_oldAccel

template<MInt nDim>
std::array<MFloat, nDim> LPTSpherical< nDim >::m_oldAccel {}

Definition at line 68 of file lptspherical.h.

◆ m_oldFluidDensity

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_oldFluidDensity = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 73 of file lptspherical.h.

◆ m_oldFluidVel

template<MInt nDim>
std::array<MFloat, nDim> LPTSpherical< nDim >::m_oldFluidVel {}

Definition at line 70 of file lptspherical.h.

◆ m_redistWeight

template<MInt nDim>
std::vector<MFloat> LPTSpherical< nDim >::m_redistWeight {}

Definition at line 105 of file lptspherical.h.

◆ m_shedDiam

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_shedDiam = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 82 of file lptspherical.h.

◆ m_temperature

template<MInt nDim>
MFloat LPTSpherical< nDim >::m_temperature = std::numeric_limits<MFloat>::quiet_NaN()

Definition at line 78 of file lptspherical.h.

◆ s_floatElements

template<MInt nDim>
constexpr MInt LPTSpherical< nDim >::s_floatElements = 9 + 4 * nDim
staticconstexpr

Definition at line 92 of file lptspherical.h.

◆ s_Frm

template<MInt nDim>
std::array< MFloat, nDim > LPTSpherical< nDim >::s_Frm {}
static

Definition at line 100 of file lptspherical.h.

◆ s_intElements

template<MInt nDim>
constexpr MInt LPTSpherical< nDim >::s_intElements = 1
staticconstexpr

Definition at line 93 of file lptspherical.h.

◆ s_lengthFactor

template<MInt nDim>
MFloat LPTSpherical< nDim >::s_lengthFactor = 1.0
static

Definition at line 95 of file lptspherical.h.

◆ s_Pr

template<MInt nDim>
MFloat LPTSpherical< nDim >::s_Pr = 1.0
static

Definition at line 97 of file lptspherical.h.

◆ s_Re

template<MInt nDim>
MFloat LPTSpherical< nDim >::s_Re = 1.0
static

Definition at line 96 of file lptspherical.h.

◆ s_Sc

template<MInt nDim>
MFloat LPTSpherical< nDim >::s_Sc = 1.0
static

Definition at line 98 of file lptspherical.h.

◆ s_We

template<MInt nDim>
MFloat LPTSpherical< nDim >::s_We = 1.0
static

Definition at line 99 of file lptspherical.h.


The documentation for this class was generated from the following files: