FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

LISA.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
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 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00040 
00041 defineTypeNameAndDebug(LISA, 0);
00042 
00043 addToRunTimeSelectionTable
00044 (
00045     atomizationModel,
00046     LISA,
00047     dictionary
00048 );
00049 
00050 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00051 
00052 // Construct from components
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 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00070 
00071 LISA::~LISA()
00072 {}
00073 
00074 
00075 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
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     // ideal gas law to evaluate density
00104     scalar rhoAverage = pressure/R/Taverage;
00105     //scalar nuAverage = muAverage/rhoAverage;
00106     scalar sigma = fuels.sigma(pressure, p.T(), p.X());
00107 
00108     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00109     //     The We and Re numbers are to be evaluated using the 1/3 rule.
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     TL
00128     It might be the relative velocity between Liquid and Gas, but I use the
00129     absolute velocity of the parcel as suggested by the authors
00130 */
00131 
00132 //    scalar U = mag(p.Urel(vel));
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 //  Updating liquid sheet tickness... that is the droplet diameter
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 //  modifications to take account of the flash boiling on primary breakUp
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 //          The fuel is boiling.....
00305 //          Calculation of the boiling temperature
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     //  bounding chi
00335 
00336     chi = max(chi, 0.0);
00337     chi = min(chi, 1.0);
00338 
00339     //  modifing dD to take account of flash boiling
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 //      calculate the new diameter with a Rosin Rammler distribution
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 //  New droplet diameter
00390 
00391         p.d() = x;
00392         p.ct() = 0.0;
00393 
00394     }
00395 
00396 
00397 }
00398 
00399 
00400 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00401 
00402 } // End namespace Foam
00403 
00404 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines