00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <OpenFOAM/error.H>
00027
00028 #include "LISA.H"
00029 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00030 #include <reactionThermophysicalModels/basicMultiComponentMixture.H>
00031
00032 #include <pdf/RosinRammler.H>
00033
00034
00035
00036 namespace Foam
00037 {
00038
00039
00040
00041 defineTypeNameAndDebug(LISA, 0);
00042
00043 addToRunTimeSelectionTable
00044 (
00045 atomizationModel,
00046 LISA,
00047 dictionary
00048 );
00049
00050
00051
00052
00053 LISA::LISA
00054 (
00055 const dictionary& dict,
00056 spray& sm
00057 )
00058 :
00059 atomizationModel(dict, sm),
00060 coeffsDict_(dict.subDict(typeName+"Coeffs")),
00061 rndGen_(sm.rndGen()),
00062 Cl_(readScalar(coeffsDict_.lookup("Cl"))),
00063 cTau_(readScalar(coeffsDict_.lookup("cTau"))),
00064 Q_(readScalar(coeffsDict_.lookup("Q"))),
00065 J_(readScalar(coeffsDict_.lookup("J")))
00066 {}
00067
00068
00069
00070
00071 LISA::~LISA()
00072 {}
00073
00074
00075
00076
00077 void LISA::atomizeParcel
00078 (
00079 parcel& p,
00080 const scalar deltaT,
00081 const vector& vel,
00082 const liquidMixture& fuels
00083 ) const
00084 {
00085
00086
00087 const PtrList<volScalarField>& Y = spray_.composition().Y();
00088
00089 label Ns = Y.size();
00090 label cellI = p.cell();
00091 scalar pressure = spray_.p()[cellI];
00092 scalar temperature = spray_.T()[cellI];
00093 scalar Taverage = p.T() + (temperature - p.T())/3.0;
00094 scalar Winv = 0.0;
00095
00096 for(label i=0; i<Ns; i++)
00097 {
00098 Winv += Y[i][cellI]/spray_.gasProperties()[i].W();
00099 }
00100
00101 scalar R = specie::RR*Winv;
00102
00103
00104 scalar rhoAverage = pressure/R/Taverage;
00105
00106 scalar sigma = fuels.sigma(pressure, p.T(), p.X());
00107
00108
00109
00110
00111
00112 scalar WeberNumber = p.We(vel, rhoAverage, sigma);
00113
00114 scalar tau = 0.0;
00115 scalar dL = 0.0;
00116 scalar k = 0.0;
00117 scalar muFuel = fuels.mu(pressure, p.T(), p.X());
00118 scalar rhoFuel = fuels.rho(1.0e+5, p.T(), p.X());
00119 scalar nuFuel = muFuel/rhoFuel;
00120
00121 vector uDir = p.U()/mag(p.U());
00122
00123 scalar uGas = mag(vel & uDir);
00124 vector Ug = uGas*uDir;
00125
00126
00127
00128
00129
00130
00131
00132
00133 scalar U = mag(p.U());
00134
00135 p.ct() += deltaT;
00136
00137 scalar Q = rhoAverage/rhoFuel;
00138
00139 const injectorType& it =
00140 spray_.injectors()[label(p.injector())].properties();
00141
00142 if (it.nHoles() > 1)
00143 {
00144 Info << "Warning: This atomization model is not suitable for multihole injector." << endl
00145 << "Only the first hole will be used." << endl;
00146 }
00147
00148 const vector itPosition = it.position(0);
00149 scalar pWalk = mag(p.position() - itPosition);
00150
00151
00152
00153 const vector direction = it.direction(0, spray_.runTime().value());
00154
00155 scalar h = (p.position() - itPosition) & direction;
00156
00157 scalar d = sqrt(sqr(pWalk)-sqr(h));
00158
00159 scalar time = pWalk/mag(p.U());
00160
00161 scalar elapsedTime = spray_.runTime().value();
00162
00163 scalar massFlow = it.massFlowRate(max(0.0,elapsedTime-time));
00164
00165 scalar hSheet = massFlow/(mathematicalConstant::pi*d*rhoFuel*mag(p.U()));
00166
00167 p.d() = min(hSheet,p.d());
00168
00169 if(WeberNumber > 27.0/16.0)
00170 {
00171
00172 scalar kPos = 0.0;
00173 scalar kNeg = Q*pow(U, 2.0)*rhoFuel/sigma;
00174
00175 scalar derivativePos = sqrt
00176 (
00177 Q*pow(U,2.0)
00178 );
00179
00180 scalar derivativeNeg =
00181 (
00182 8.0*pow(nuFuel, 2.0)*pow(kNeg, 3.0)
00183 + Q*pow(U, 2.0)*kNeg
00184 - 3.0*sigma/2.0/rhoFuel*pow(kNeg, 2.0)
00185 )
00186 /
00187 sqrt
00188 (
00189 4.0*pow(nuFuel, 2.0)*pow(kNeg, 4.0)
00190 + Q*pow(U, 2.0)*pow(kNeg, 2.0)
00191 - sigma*pow(kNeg, 3.0)/rhoFuel
00192 )
00193 -
00194 4.0*nuFuel*kNeg;
00195
00196 scalar kOld = 0.0;
00197
00198
00199 for(label i=0; i<40; i++)
00200 {
00201
00202 k = kPos - (derivativePos/((derivativeNeg-derivativePos)/(kNeg-kPos)));
00203
00204 scalar derivativek =
00205 (
00206 8.0*pow(nuFuel, 2.0)*pow(k, 3.0)
00207 + Q*pow(U, 2.0)*k
00208 - 3.0*sigma/2.0/rhoFuel*pow(k, 2.0)
00209 )
00210 /
00211 sqrt
00212 (
00213 4.0*pow(nuFuel, 2.0)*pow(k, 4.0)
00214 + Q*pow(U, 2.0)*pow(k, 2.0)
00215 - sigma*pow(k, 3.0)/rhoFuel
00216 )
00217 -
00218 4.0*nuFuel*k;
00219
00220 if(derivativek > 0)
00221 {
00222 derivativePos = derivativek;
00223 kPos = k;
00224 }
00225 else
00226 {
00227 derivativeNeg = derivativek;
00228 kNeg = k;
00229 }
00230
00231 if(mag(k-kOld)/k < 1e-4)
00232 {
00233 break;
00234 }
00235
00236 kOld = k;
00237
00238 }
00239
00240 scalar omegaS =
00241 - 2.0 * nuFuel * pow(k, 2.0)
00242 + sqrt
00243 (
00244 4.0*pow(nuFuel, 2.0)*pow(k, 4.0)
00245 + Q*pow(U, 2.0)*pow(k, 2.0)
00246 - sigma*pow(k, 3.0)/rhoFuel
00247 );
00248
00249 tau = cTau_/omegaS;
00250
00251 dL = sqrt(8.0*p.d()/k);
00252
00253 }
00254 else
00255 {
00256
00257 k =
00258 rhoAverage*pow(U, 2.0)
00259 /
00260 2.0*sigma;
00261
00262 scalar J = pWalk*p.d()/2.0;
00263
00264 tau = pow(3.0*cTau_,2.0/3.0)*cbrt(J*sigma/(sqr(Q)*pow(U,4.0)*rhoFuel));
00265
00266 dL = sqrt(4.0*p.d()/k);
00267 }
00268
00269
00270
00271 scalar kL =
00272 1.0
00273 /
00274 (
00275 dL *
00276 pow(0.5 + 1.5 * muFuel/pow((rhoFuel*sigma*dL), 0.5), 0.5)
00277 );
00278
00279 scalar dD = cbrt(3.0*mathematicalConstant::pi*pow(dL, 2.0)/kL);
00280
00281 scalar lisaExp = 0.27;
00282 scalar ambientPressure = 1.0e+5;
00283
00284 scalar pRatio = spray_.ambientPressure()/ambientPressure;
00285
00286 dD = dD*pow(pRatio,lisaExp);
00287
00288
00289
00290 scalar pExp = 0.135;
00291
00292 scalar chi = 0.0;
00293
00294 label Nf = fuels.components().size();
00295
00296 scalar Td = p.T();
00297
00298 for(label i = 0; i < Nf ; i++)
00299 {
00300
00301 if(fuels.properties()[i].pv(spray_.ambientPressure(), Td) >= 0.999*spray_.ambientPressure())
00302 {
00303
00304
00305
00306
00307 scalar tBoilingSurface = Td;
00308
00309 label Niter = 200;
00310
00311 for(label k=0; k< Niter ; k++)
00312 {
00313 scalar pBoil = fuels.properties()[i].pv(pressure, tBoilingSurface);
00314
00315 if(pBoil > pressure)
00316 {
00317 tBoilingSurface = tBoilingSurface - (Td-temperature)/Niter;
00318 }
00319 else
00320 {
00321 break;
00322 }
00323 }
00324
00325 scalar hl = fuels.properties()[i].hl(spray_.ambientPressure(), tBoilingSurface);
00326 scalar iTp = fuels.properties()[i].h(spray_.ambientPressure(), Td) - spray_.ambientPressure()/fuels.properties()[i].rho(spray_.ambientPressure(), Td);
00327 scalar iTb = fuels.properties()[i].h(spray_.ambientPressure(), tBoilingSurface) - spray_.ambientPressure()/fuels.properties()[i].rho(spray_.ambientPressure(), tBoilingSurface);
00328
00329 chi += p.X()[i]*(iTp-iTb)/hl;
00330
00331 }
00332 }
00333
00334
00335
00336 chi = max(chi, 0.0);
00337 chi = min(chi, 1.0);
00338
00339
00340
00341 dD = dD*(1.0 - chi*pow(pRatio, -pExp));
00342
00343 scalar lBU = Cl_ * mag(p.U())*tau;
00344
00345 if(pWalk > lBU)
00346 {
00347
00348 p.liquidCore() = 0.0;
00349
00350
00351
00352 scalar minValue = min(p.d(),dD/10.0);
00353
00354 scalar maxValue = dD;
00355
00356 if(maxValue - minValue < SMALL)
00357 {
00358 minValue = p.d()/10.0;
00359 }
00360
00361 scalar range = maxValue - minValue;
00362
00363 scalar y = 0;
00364 scalar x = 0;
00365
00366 bool success = false;
00367
00368 while(!success)
00369 {
00370
00371 x = minValue + range*rndGen_.scalar01();
00372 y = rndGen_.scalar01();
00373
00374 scalar p = 0.0;
00375
00376 scalar nExp = 1;
00377
00378 scalar xx = pow(x/dD, nExp);
00379
00380 p = xx*exp(-xx);
00381
00382 if (y<p)
00383 {
00384 success = true;
00385 }
00386
00387 }
00388
00389
00390
00391 p.d() = x;
00392 p.ct() = 0.0;
00393
00394 }
00395
00396
00397 }
00398
00399
00400
00401
00402 }
00403
00404