void Foam::SHF::breakupParcel ( parcel& p, const scalar deltaT, const vector& vel, const liquidMixtureProperties& fuels ) const { label cellI = p.cell(); scalar T = p.T(); scalar pc = spray_.p()[cellI]; scalar sigma = fuels.sigma(pc, T, p.X()); scalar rhoLiquid = fuels.rho(pc, T, p.X()); scalar muLiquid = fuels.mu(pc, T, p.X()); scalar rhoGas = spray_.rho()[cellI]; scalar weGas = p.We(vel, rhoGas, sigma); scalar weLiquid = p.We(vel, rhoLiquid, sigma); // correct the Reynolds number. Reitz is using radius instead of diameter scalar reLiquid = p.Re(rhoLiquid, vel, muLiquid); scalar ohnesorge = sqrt(weLiquid)/(reLiquid + VSMALL); vector vRel = p.Urel(vel); scalar weGasCorr = weGas/(1.0 + weCorrCoeff_*ohnesorge); // droplet deformation characteristic time scalar tChar = p.d()/mag(vRel)*sqrt(rhoLiquid/rhoGas); scalar tFirst = cInit_*tChar; scalar tSecond = 0; scalar tCharSecond = 0; // updating the droplet characteristic time p.ct() += deltaT; if (weGas > weConst_) { if (weGas < weCrit1_) { tCharSecond = c1_*pow((weGas - weConst_),cExp1_); } else if (weGas >= weCrit1_ && weGas <= weCrit2_) { tCharSecond = c2_*pow((weGas - weConst_),cExp2_); } else { tCharSecond = c3_*pow((weGas - weConst_),cExp3_); } } scalar weC = weBuCrit_*(1.0+ohnCoeffCrit_*pow(ohnesorge, ohnExpCrit_)); scalar weB = weBuBag_*(1.0+ohnCoeffBag_*pow(ohnesorge, ohnExpBag_)); scalar weMM = weBuMM_*(1.0+ohnCoeffMM_*pow(ohnesorge, ohnExpMM_)); bool bag = (weGas > weC && weGas < weB); bool multimode = (weGas >= weB && weGas <= weMM); bool shear = (weGas > weMM); tSecond = tCharSecond*tChar; scalar tBreakUP = tFirst + tSecond; if (p.ct() > tBreakUP) { scalar d32 = coeffD_*p.d()*pow(ohnesorge, onExpD_)*pow(weGasCorr, weExpD_); if (bag || multimode) { scalar d05 = d32Coeff_*d32; scalar x = 0.0; scalar y = 0.0; scalar d = 0.0; scalar px = 0.0; do { x = cDmaxBM_*rndGen_.sample01<scalar>(); d = sqr(x)*d05; y = rndGen_.sample01<scalar>(); px = x /(2.0*sqrt(constant::mathematical::twoPi)*sigma_) *exp(-0.5*sqr((x-mu_)/sigma_)); } while (y >= px); p.d() = d; p.ct() = 0.0; } if (shear) { scalar dC = weConst_*sigma/(rhoGas*sqr(mag(vRel))); scalar d32Red = 4.0*(d32*dC)/(5.0*dC - d32); scalar initMass = p.m(); scalar d05 = d32Coeff_*d32Red; scalar x = 0.0; scalar y = 0.0; scalar d = 0.0; scalar px = 0.0; do { x = cDmaxS_*rndGen_.sample01<scalar>(); d = sqr(x)*d05; y = rndGen_.sample01<scalar>(); px = x /(2.0*sqrt(constant::mathematical::twoPi)*sigma_) *exp(-0.5*sqr((x-mu_)/sigma_)); } while (y >= px); p.d() = dC; p.m() = corePerc_*initMass; spray_.addParticle ( new parcel ( p.mesh(), p.position(), p.cell(), p.tetFace(), p.tetPt(), p.n(), d, p.T(), (1.0 - corePerc_)*initMass, 0.0, 0.0, 0.0, -GREAT, p.tTurb(), 0.0, scalar(p.injector()), p.U(), p.Uturb(), p.X(), p.fuelNames() ) ); p.ct() = 0.0; } } }
// Return 'keepParcel' bool reflectParcel::wallTreatment ( parcel& p, const label globalFacei ) const { label patchi = p.patch(globalFacei); label facei = p.patchFace(patchi, globalFacei); const polyMesh& mesh = spray_.mesh(); if (mesh_.boundaryMesh()[patchi].isWall()) { // wallNormal defined to point outwards of domain vector Sf = mesh_.Sf().boundaryField()[patchi][facei]; Sf /= mag(Sf); if (!mesh.moving()) { // static mesh scalar Un = p.U() & Sf; if (Un > 0) { p.U() -= (1.0 + elasticity_)*Un*Sf; } } else { // moving mesh vector Ub1 = U_.boundaryField()[patchi][facei]; vector Ub0 = U_.oldTime().boundaryField()[patchi][facei]; scalar dt = spray_.runTime().deltaT().value(); const vectorField& oldPoints = mesh.oldPoints(); const vector& Cf1 = mesh.faceCentres()[globalFacei]; vector Cf0 = mesh.faces()[globalFacei].centre(oldPoints); vector Cf = Cf0 + p.stepFraction()*(Cf1 - Cf0); vector Sf0 = mesh.faces()[globalFacei].normal(oldPoints); // for layer addition Sf0 = vector::zero and we use Sf if (mag(Sf0) > SMALL) { Sf0 /= mag(Sf0); } else { Sf0 = Sf; } scalar magSfDiff = mag(Sf - Sf0); vector Ub = Ub0 + p.stepFraction()*(Ub1 - Ub0); if (magSfDiff > SMALL) { // rotation + translation vector Sfp = Sf0 + p.stepFraction()*(Sf - Sf0); vector omega = Sf0 ^ Sf; scalar magOmega = mag(omega); omega /= magOmega+SMALL; scalar phiVel = ::asin(magOmega)/dt; scalar dist = (p.position() - Cf) & Sfp; vector pos = p.position() - dist*Sfp; vector vrot = phiVel*(omega ^ (pos - Cf)); vector v = Ub + vrot; scalar Un = ((p.U() - v) & Sfp); if (Un > 0.0) { p.U() -= (1.0 + elasticity_)*Un*Sfp; } } else { // translation vector Ur = p.U() - Ub; scalar Urn = Ur & Sf; /* if (mag(Ub-v) > SMALL) { Info << "reflectParcel:: v = " << v << ", Ub = " << Ub << ", facei = " << facei << ", patchi = " << patchi << ", globalFacei = " << globalFacei << ", name = " << mesh_.boundaryMesh()[patchi].name() << endl; } */ if (Urn > 0.0) { p.U() -= (1.0 + elasticity_)*Urn*Sf; } } } } else { FatalError << "bool reflectParcel::wallTreatment(parcel& parcel) const " << " parcel has hit a boundary " << mesh_.boundary()[patchi].type() << " which not yet has been implemented." << abort(FatalError); } return true; }
void myLISA_3_InjPos::atomizeParcel ( parcel& p, const scalar deltaT, const vector& vel, const liquidMixture& fuels ) const { const PtrList<volScalarField>& Y = spray_.composition().Y(); label Ns = Y.size(); label cellI = p.cell(); scalar pressure = spray_.p()[cellI]; scalar temperature = spray_.T()[cellI]; //--------------------------------------AL____101015--------------------------------// // scalar Taverage = p.T() + (temperature - p.T())/3.0; scalar Taverage = temperature; //-----------------------------------------END--------------------------------------// scalar Winv = 0.0; for(label i=0; i<Ns; i++) { Winv += Y[i][cellI]/spray_.gasProperties()[i].W(); } scalar R = specie::RR*Winv; // ideal gas law to evaluate density scalar rhoAverage = pressure/R/Taverage; //scalar nuAverage = muAverage/rhoAverage; scalar sigma = fuels.sigma(pressure, p.T(), p.X()); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // The We and Re numbers are to be evaluated using the 1/3 rule. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // scalar WeberNumber = p.We(vel, rhoAverage, sigma); scalar tau = 0.0; scalar dL = 0.0; scalar k = 0.0; scalar muFuel = fuels.mu(pressure, p.T(), p.X()); scalar rhoFuel = fuels.rho(1.0e+5, p.T(), p.X()); scalar nuFuel = muFuel/rhoFuel; vector uDir = p.U()/mag(p.U()); scalar uGas = mag(vel & uDir); vector Ug = uGas*uDir; /* TL It might be the relative velocity between Liquid and Gas, but I use the absolute velocity of the parcel as suggested by the authors */ // scalar U = mag(p.Urel(vel)); scalar U = mag(p.U()); p.ct() += deltaT; scalar Q = rhoAverage/rhoFuel; const injectorType& it = spray_.injectors()[label(p.injector())].properties(); if (it.nHoles() > 1) { Info << "Warning: This atomization model is not suitable for multihole injector." << endl << "Only the first hole will be used." << endl; } const vector direction = it.direction(0, spray_.runTime().value()); //--------------------------------CH 101108--------------------------------------------------// // const vector itPosition = it.position(0); const injectorModel& im = spray_.injection(); const vector itPosition = it.position(0) + im.injDist(0)*direction/mag(direction); //------------------------------------END----------------------------------------------------// scalar pWalk = mag(p.position() - itPosition); // Updating liquid sheet tickness... that is the droplet diameter // const vector direction = it.direction(0, spray_.runTime().value()); scalar h = (p.position() - itPosition) & direction; scalar d = sqrt(sqr(pWalk)-sqr(h)); scalar time = pWalk/mag(p.U()); scalar elapsedTime = spray_.runTime().value(); scalar massFlow = it.massFlowRate(max(0.0,elapsedTime-time)); scalar hSheet = massFlow/(mathematicalConstant::pi*d*rhoFuel*mag(p.U())); p.d() = min(hSheet,p.d()); if(WeberNumber > 27.0/16.0) { scalar kPos = 0.0; scalar kNeg = Q*pow(U, 2.0)*rhoFuel/sigma; scalar derivativePos = sqrt ( Q*pow(U,2.0) ); scalar derivativeNeg = ( 8.0*pow(nuFuel, 2.0)*pow(kNeg, 3.0) + Q*pow(U, 2.0)*kNeg - 3.0*sigma/2.0/rhoFuel*pow(kNeg, 2.0) ) / sqrt ( 4.0*pow(nuFuel, 2.0)*pow(kNeg, 4.0) + Q*pow(U, 2.0)*pow(kNeg, 2.0) - sigma*pow(kNeg, 3.0)/rhoFuel ) - 4.0*nuFuel*kNeg; scalar kOld = 0.0; for(label i=0; i<40; i++) { k = kPos - (derivativePos/((derivativeNeg-derivativePos)/(kNeg-kPos))); scalar derivativek = ( 8.0*pow(nuFuel, 2.0)*pow(k, 3.0) + Q*pow(U, 2.0)*k - 3.0*sigma/2.0/rhoFuel*pow(k, 2.0) ) / sqrt ( 4.0*pow(nuFuel, 2.0)*pow(k, 4.0) + Q*pow(U, 2.0)*pow(k, 2.0) - sigma*pow(k, 3.0)/rhoFuel ) - 4.0*nuFuel*k; if(derivativek > 0) { derivativePos = derivativek; kPos = k; } else { derivativeNeg = derivativek; kNeg = k; } if(mag(k-kOld)/k < 1e-4) { break; } kOld = k; } scalar omegaS = - 2.0 * nuFuel * pow(k, 2.0) + sqrt ( 4.0*pow(nuFuel, 2.0)*pow(k, 4.0) + Q*pow(U, 2.0)*pow(k, 2.0) - sigma*pow(k, 3.0)/rhoFuel ); tau = cTau_/omegaS; dL = sqrt(8.0*p.d()/k); } else { k = rhoAverage*pow(U, 2.0) / 2.0*sigma; //--------------------------------------AL____101011--------------------------------// // scalar J = pWalk*p.d()/2.0; scalar J = time*hSheet/2.0; //-----------------------------------------END--------------------------------------// tau = pow(3.0*cTau_,2.0/3.0)*cbrt(J*sigma/(sqr(Q)*pow(U,4.0)*rhoFuel)); dL = sqrt(4.0*p.d()/k); } scalar kL = 1.0 / ( dL * pow(0.5 + 1.5 * muFuel/pow((rhoFuel*sigma*dL), 0.5), 0.5) ); scalar dD = cbrt(3.0*mathematicalConstant::pi*pow(dL, 2.0)/kL); // lisaExp is included in coeffsDict // scalar lisaExp = 0.27; scalar ambientPressure = 1.0e+5; scalar pRatio = spray_.ambientPressure()/ambientPressure; dD = dD*pow(pRatio,lisaExp_); // modifications to take account of the flash boiling on primary breakUp scalar pExp = 0.135; scalar chi = 0.0; label Nf = fuels.components().size(); scalar Td = p.T(); for(label i = 0; i < Nf ; i++) { if(fuels.properties()[i].pv(spray_.ambientPressure(), Td) >= 0.999*spray_.ambientPressure()) { // The fuel is boiling..... // Calculation of the boiling temperature scalar tBoilingSurface = Td; label Niter = 200; for(label k=0; k< Niter ; k++) { scalar pBoil = fuels.properties()[i].pv(pressure, tBoilingSurface); if(pBoil > pressure) { tBoilingSurface = tBoilingSurface - (Td-temperature)/Niter; } else { break; } } scalar hl = fuels.properties()[i].hl(spray_.ambientPressure(), tBoilingSurface); scalar iTp = fuels.properties()[i].h(spray_.ambientPressure(), Td) - spray_.ambientPressure()/fuels.properties()[i].rho(spray_.ambientPressure(), Td); scalar iTb = fuels.properties()[i].h(spray_.ambientPressure(), tBoilingSurface) - spray_.ambientPressure()/fuels.properties()[i].rho(spray_.ambientPressure(), tBoilingSurface); chi += p.X()[i]*(iTp-iTb)/hl; } } // bounding chi chi = max(chi, 0.0); chi = min(chi, 1.0); // modifing dD to take account of flash boiling dD = dD*(1.0 - chi*pow(pRatio, -pExp)); scalar lBU = Cl_ * mag(p.U())*tau; if(pWalk > lBU) { p.liquidCore() = 0.0; // calculate the new diameter with the standard 1D Rosin Rammler distribution //--------------------------------AL_____101012------------------------------// // Calculation of the mean radius based on SMR rs. Coefficient factorGamma depends on nExp. // Note that Reitz either used (Schmidt et al., 1999-01-0496) or skipped (Senecal et al.) this factor!!! // scalar factorGamma = 0.75*sqrt(mathematicalConstant::pi); //nExp=2 scalar factorGamma = 1.; scalar delta = dD/factorGamma; /* dD is the SMD, and the delta is calculated using gama function. Here we assume nExp = 2. */ // scalar delta = dD/(0.75*sqrt(mathematicalConstant::pi)); // scalar minValue = min(p.d()/20.0,dD/20.0); scalar minValue = dD/10.0; // delta is divided by 20 instead of 10 in order to make sure of small minValue // scalar minValue = min(p.d(),dD/20.0); // scalar maxValue = p.d(); scalar maxValue = dD; // The pdf value for 4.0*delta is already very small. // scalar maxValue = delta*4.0; if(maxValue - minValue < SMALL) { // minValue = p.d()/20.0; minValue = maxValue/20.0; //-----------------------------------END-------------------------------------// } scalar range = maxValue - minValue; scalar nExp = 3; scalar rrd_[500]; //--------------------------------AL_____101012------------------------------// scalar probFactorMin = exp(-pow(minValue/delta,nExp)); scalar probFactorMax = exp(-pow(maxValue/delta,nExp)); scalar probFactor = 1./(probFactorMin - probFactorMax); //-----------------------------------END-------------------------------------// for(label n=0; n<500; n++) { scalar xx = minValue + range*n/500; //-------------------------------AL_____101012-------------------------------// // rrd_[n] = 1 - exp(-pow(xx/delta,nExp)); rrd_[n] = (probFactorMin - exp(-pow(xx/delta,nExp)))*probFactor; //-----------------------------------END-------------------------------------// } bool success = false; scalar x = 0; scalar y = rndGen_.scalar01(); label k = 0; while(!success && (k<500)) { if (rrd_[k]>y) { success = true; } k++; } //--------------------------------AL_____101012------------------------------// // x = minValue + range*n/500; x = minValue + range*(k-0.5)/500.0; //------------------------------------END------------------------------------// // New droplet diameter p.d() = x; p.ct() = 0.0; } }
void reitzKHRT::breakupParcel ( parcel& p, const scalar deltaT, const vector& vel, const liquidMixture& fuels ) const { label celli = p.cell(); scalar T = p.T(); scalar r = 0.5*p.d(); scalar pc = spray_.p()[celli]; scalar sigma = fuels.sigma(pc, T, p.X()); scalar rhoLiquid = fuels.rho(pc, T, p.X()); scalar muLiquid = fuels.mu(pc, T, p.X()); scalar rhoGas = spray_.rho()[celli]; scalar Np = p.N(rhoLiquid); scalar semiMass = Np*pow(p.d(), 3.0); scalar weGas = p.We(vel, rhoGas, sigma); scalar weLiquid = p.We(vel, rhoLiquid, sigma); // correct the Reynolds number. Reitz is using radius instead of diameter scalar reLiquid = 0.5*p.Re(rhoLiquid, vel, muLiquid); scalar ohnesorge = sqrt(weLiquid)/(reLiquid + VSMALL); scalar taylor = ohnesorge*sqrt(weGas); vector acceleration = p.Urel(vel)/p.tMom(); vector trajectory = p.U()/mag(p.U()); scalar gt = (g_ + acceleration) & trajectory; // frequency of the fastest growing KH-wave scalar omegaKH = (0.34 + 0.38*pow(weGas, 1.5)) /((1 + ohnesorge)*(1 + 1.4*pow(taylor, 0.6))) *sqrt(sigma/(rhoLiquid*pow(r, 3))); // corresponding KH wave-length. scalar lambdaKH = 9.02 *r *(1.0 + 0.45*sqrt(ohnesorge)) *(1.0 + 0.4*pow(taylor, 0.7)) /pow(1.0 + 0.865*pow(weGas, 1.67), 0.6); // characteristic Kelvin-Helmholtz breakup time scalar tauKH = 3.726*b1_*r/(omegaKH*lambdaKH); // stable KH diameter scalar dc = 2.0*b0_*lambdaKH; // the frequency of the fastest growing RT wavelength. scalar helpVariable = mag(gt*(rhoLiquid - rhoGas)); scalar omegaRT = sqrt ( 2.0*pow(helpVariable, 1.5) /(3.0*sqrt(3.0*sigma)*(rhoGas + rhoLiquid)) ); // RT wave number scalar KRT = sqrt(helpVariable/(3.0*sigma + VSMALL)); // wavelength of the fastest growing RT frequency scalar lambdaRT = 2.0*mathematicalConstant::pi*cRT_/(KRT + VSMALL); // if lambdaRT < diameter, then RT waves are growing on the surface // and we start to keep track of how long they have been growing if ((p.ct() > 0) || (lambdaRT < p.d())) { p.ct() += deltaT; } // characteristic RT breakup time scalar tauRT = cTau_/(omegaRT + VSMALL); // check if we have RT breakup if ((p.ct() > tauRT) && (lambdaRT < p.d())) { // the RT breakup creates diameter/lambdaRT new droplets p.ct() = -GREAT; scalar multiplier = p.d()/lambdaRT; scalar nDrops = multiplier*Np; p.d() = cbrt(semiMass/nDrops); } // otherwise check for KH breakup else if (dc < p.d()) { // no breakup below Weber = 12 if (weGas > weberLimit_) { label injector = label(p.injector()); scalar fraction = deltaT/tauKH; // reduce the diameter according to the rate-equation p.d() = (fraction*dc + p.d())/(1.0 + fraction); scalar ms = rhoLiquid*Np*pow3(dc)*mathematicalConstant::pi/6.0; p.ms() += ms; // Total number of parcels for the whole injection event label nParcels = spray_.injectors()[injector].properties()->nParcelsToInject ( spray_.injectors()[injector].properties()->tsoi(), spray_.injectors()[injector].properties()->teoi() ); scalar averageParcelMass = spray_.injectors()[injector].properties()->mass()/nParcels; if (p.ms()/averageParcelMass > msLimit_) { // set the initial ms value to -GREAT. This prevents // new droplets from being formed from the child droplet // from the KH instability // mass of stripped child parcel scalar mc = p.ms(); // Prevent child parcel from taking too much mass if (mc > 0.5*p.m()) { mc = 0.5*p.m(); } spray_.addParticle ( new parcel ( spray_, p.position(), p.cell(), p.n(), dc, p.T(), mc, 0.0, 0.0, 0.0, -GREAT, p.tTurb(), 0.0, p.injector(), p.U(), p.Uturb(), p.X(), p.fuelNames() ) ); p.m() -= mc; p.ms() = 0.0; } } } }