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 "ReactingMultiphaseParcel.H"
00027 #include <OpenFOAM/mathematicalConstants.H>
00028
00029
00030
00031 template<class ParcelType>
00032 const Foam::label Foam::ReactingMultiphaseParcel<ParcelType>::GAS(0);
00033
00034 template<class ParcelType>
00035 const Foam::label Foam::ReactingMultiphaseParcel<ParcelType>::LIQ(1);
00036
00037 template<class ParcelType>
00038 const Foam::label Foam::ReactingMultiphaseParcel<ParcelType>::SLD(2);
00039
00040
00041
00042
00043 template<class ParcelType>
00044 template<class TrackData>
00045 Foam::scalar Foam::ReactingMultiphaseParcel<ParcelType>::cpEff
00046 (
00047 TrackData& td,
00048 const scalar p,
00049 const scalar T,
00050 const label idG,
00051 const label idL,
00052 const label idS
00053 ) const
00054 {
00055 return
00056 this->Y_[GAS]*td.cloud().composition().cp(idG, YGas_, p, T)
00057 + this->Y_[LIQ]*td.cloud().composition().cp(idL, YLiquid_, p, T)
00058 + this->Y_[SLD]*td.cloud().composition().cp(idS, YSolid_, p, T);
00059 }
00060
00061
00062 template<class ParcelType>
00063 template<class TrackData>
00064 Foam::scalar Foam::ReactingMultiphaseParcel<ParcelType>::HEff
00065 (
00066 TrackData& td,
00067 const scalar p,
00068 const scalar T,
00069 const label idG,
00070 const label idL,
00071 const label idS
00072 ) const
00073 {
00074 return
00075 this->Y_[GAS]*td.cloud().composition().H(idG, YGas_, p, T)
00076 + this->Y_[LIQ]*td.cloud().composition().H(idL, YLiquid_, p, T)
00077 + this->Y_[SLD]*td.cloud().composition().H(idS, YSolid_, p, T);
00078 }
00079
00080
00081 template<class ParcelType>
00082 template<class TrackData>
00083 Foam::scalar Foam::ReactingMultiphaseParcel<ParcelType>::LEff
00084 (
00085 TrackData& td,
00086 const scalar p,
00087 const scalar T,
00088 const label idG,
00089 const label idL,
00090 const label idS
00091 ) const
00092 {
00093 return
00094 this->Y_[GAS]*td.cloud().composition().L(idG, YGas_, p, T)
00095 + this->Y_[LIQ]*td.cloud().composition().L(idL, YLiquid_, p, T)
00096 + this->Y_[SLD]*td.cloud().composition().L(idS, YSolid_, p, T);
00097 }
00098
00099
00100 template<class ParcelType>
00101 Foam::scalar Foam::ReactingMultiphaseParcel<ParcelType>::updateMassFractions
00102 (
00103 const scalar mass0,
00104 const scalarField& dMassGas,
00105 const scalarField& dMassLiquid,
00106 const scalarField& dMassSolid
00107 )
00108 {
00109 scalarField& YMix = this->Y_;
00110
00111 scalar massGas =
00112 this->updateMassFraction(mass0*YMix[GAS], dMassGas, YGas_);
00113 scalar massLiquid =
00114 this->updateMassFraction(mass0*YMix[LIQ], dMassLiquid, YLiquid_);
00115 scalar massSolid =
00116 this->updateMassFraction(mass0*YMix[SLD], dMassSolid, YSolid_);
00117
00118 scalar massNew = max(massGas + massLiquid + massSolid, ROOTVSMALL);
00119
00120 YMix[GAS] = massGas/massNew;
00121 YMix[LIQ] = massLiquid/massNew;
00122 YMix[SLD] = 1.0 - YMix[GAS] - YMix[LIQ];
00123
00124 return massNew;
00125 }
00126
00127
00128
00129
00130 template<class ParcelType>
00131 template<class TrackData>
00132 void Foam::ReactingMultiphaseParcel<ParcelType>::setCellValues
00133 (
00134 TrackData& td,
00135 const scalar dt,
00136 const label cellI
00137 )
00138 {
00139 ReactingParcel<ParcelType>::setCellValues(td, dt, cellI);
00140 }
00141
00142
00143 template<class ParcelType>
00144 template<class TrackData>
00145 void Foam::ReactingMultiphaseParcel<ParcelType>::cellValueSourceCorrection
00146 (
00147 TrackData& td,
00148 const scalar dt,
00149 const label cellI
00150 )
00151 {
00152 scalar massCell = this->massCell(cellI);
00153
00154 scalar addedMass = 0.0;
00155 forAll(td.cloud().rhoTrans(), i)
00156 {
00157 addedMass += td.cloud().rhoTrans(i)[cellI];
00158 }
00159
00160 this->rhoc_ += addedMass/td.cloud().pMesh().cellVolumes()[cellI];
00161
00162 scalar massCellNew = massCell + addedMass;
00163 this->Uc_ += td.cloud().UTrans()[cellI]/massCellNew;
00164
00165 scalar cpEff = 0;
00166 if (addedMass > ROOTVSMALL)
00167 {
00168 forAll(td.cloud().rhoTrans(), i)
00169 {
00170 scalar Y = td.cloud().rhoTrans(i)[cellI]/addedMass;
00171 cpEff +=
00172 Y*td.cloud().mcCarrierThermo().speciesData()[i].Cp(this->Tc_);
00173 }
00174 }
00175 const scalar cpc = td.cpInterp().psi()[cellI];
00176 this->cpc_ = (massCell*cpc + addedMass*cpEff)/massCellNew;
00177
00178 this->Tc_ += td.cloud().hsTrans()[cellI]/(this->cpc_*massCellNew);
00179 }
00180
00181
00182 template<class ParcelType>
00183 template<class TrackData>
00184 void Foam::ReactingMultiphaseParcel<ParcelType>::calc
00185 (
00186 TrackData& td,
00187 const scalar dt,
00188 const label cellI
00189 )
00190 {
00191
00192
00193 const scalar np0 = this->nParticle_;
00194 const scalar d0 = this->d_;
00195 const vector& U0 = this->U_;
00196 const scalar rho0 = this->rho_;
00197 const scalar T0 = this->T_;
00198 const scalar cp0 = this->cp_;
00199 const scalar mass0 = this->mass();
00200
00201 const scalar pc = this->pc_;
00202
00203 const scalarField& YMix = this->Y_;
00204 const label idG = td.cloud().composition().idGas();
00205 const label idL = td.cloud().composition().idLiquid();
00206 const label idS = td.cloud().composition().idSolid();
00207
00208
00209
00210
00211 scalar Ts, rhos, mus, Pr, kappa;
00212 ThermoParcel<ParcelType>::
00213 calcSurfaceValues(td, cellI, T0, Ts, rhos, mus, Pr, kappa);
00214
00215
00216 scalar Re = this->Re(U0, d0, rhos, mus);
00217
00218
00219
00220
00221
00222
00223 vector Su = vector::zero;
00224
00225
00226 vector dUTrans = vector::zero;
00227
00228
00229 scalar Sh = 0.0;
00230
00231
00232 scalar dhsTrans = 0.0;
00233
00234
00235
00236
00237
00238
00239 scalarField dMassPC(YLiquid_.size(), 0.0);
00240
00241
00242 scalar Ne = 0.0;
00243
00244
00245 scalar NCpW = 0.0;
00246
00247
00248 scalarField Cs(td.cloud().mcCarrierThermo().species().size(), 0.0);
00249
00250
00251 this->calcPhaseChange
00252 (
00253 td,
00254 dt,
00255 cellI,
00256 Re,
00257 Ts,
00258 mus/rhos,
00259 d0,
00260 T0,
00261 mass0,
00262 idL,
00263 YMix[LIQ],
00264 YLiquid_,
00265 dMassPC,
00266 Sh,
00267 Ne,
00268 NCpW,
00269 Cs
00270 );
00271
00272
00273
00274
00275
00276
00277 scalarField dMassDV(YGas_.size(), 0.0);
00278
00279
00280 calcDevolatilisation
00281 (
00282 td,
00283 dt,
00284 Ts,
00285 d0,
00286 T0,
00287 mass0,
00288 this->mass0_,
00289 idG,
00290 YMix[GAS],
00291 YGas_,
00292 canCombust_,
00293 dMassDV,
00294 Sh,
00295 Ne,
00296 NCpW,
00297 Cs
00298 );
00299
00300
00301 this->correctSurfaceValues(td, cellI, Ts, Cs, rhos, mus, Pr, kappa);
00302
00303
00304
00305
00306
00307
00308 scalarField dMassSRGas(YGas_.size(), 0.0);
00309 scalarField dMassSRLiquid(YLiquid_.size(), 0.0);
00310 scalarField dMassSRSolid(YSolid_.size(), 0.0);
00311 scalarField
00312 dMassSRCarrier
00313 (
00314 td.cloud().mcCarrierThermo().species().size(),
00315 0.0
00316 );
00317
00318
00319 calcSurfaceReactions
00320 (
00321 td,
00322 dt,
00323 cellI,
00324 d0,
00325 T0,
00326 mass0,
00327 canCombust_,
00328 Ne,
00329 YMix,
00330 YGas_,
00331 YLiquid_,
00332 YSolid_,
00333 dMassSRGas,
00334 dMassSRLiquid,
00335 dMassSRSolid,
00336 dMassSRCarrier,
00337 Sh,
00338 dhsTrans
00339 );
00340
00341
00342
00343
00344
00345 scalarField dMassGas = dMassDV + dMassSRGas;
00346 scalarField dMassLiquid = dMassPC + dMassSRLiquid;
00347 scalarField dMassSolid = dMassSRSolid;
00348
00349 scalar mass1 =
00350 updateMassFractions(mass0, dMassGas, dMassLiquid, dMassSolid);
00351
00352
00353
00354
00355
00356
00357 scalar T1 =
00358 this->calcHeatTransfer
00359 (
00360 td,
00361 dt,
00362 cellI,
00363 Re,
00364 Pr,
00365 kappa,
00366 d0,
00367 rho0,
00368 T0,
00369 cp0,
00370 NCpW,
00371 Sh,
00372 dhsTrans
00373 );
00374
00375
00376
00377
00378
00379
00380 vector U1 =
00381 this->calcVelocity
00382 (
00383 td,
00384 dt,
00385 cellI,
00386 Re,
00387 mus,
00388 d0,
00389 U0,
00390 rho0,
00391 mass0,
00392 Su,
00393 dUTrans
00394 );
00395
00396 dUTrans += 0.5*(mass0 - mass1)*(U0 + U1);
00397
00398
00399
00400
00401
00402 if (td.cloud().coupled())
00403 {
00404
00405 forAll(YGas_, i)
00406 {
00407 label gid = td.cloud().composition().localToGlobalCarrierId(GAS, i);
00408 td.cloud().rhoTrans(gid)[cellI] += np0*dMassGas[i];
00409 }
00410 forAll(YLiquid_, i)
00411 {
00412 label gid = td.cloud().composition().localToGlobalCarrierId(LIQ, i);
00413 td.cloud().rhoTrans(gid)[cellI] += np0*dMassLiquid[i];
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423 forAll(dMassSRCarrier, i)
00424 {
00425 td.cloud().rhoTrans(i)[cellI] += np0*dMassSRCarrier[i];
00426 }
00427
00428
00429 td.cloud().UTrans()[cellI] += np0*dUTrans;
00430
00431
00432 td.cloud().hsTrans()[cellI] += np0*dhsTrans;
00433 }
00434
00435
00436
00437
00438
00439 if (mass1 < td.constProps().minParticleMass())
00440 {
00441 td.keepParticle = false;
00442
00443 if (td.cloud().coupled())
00444 {
00445
00446 forAll(YGas_, i)
00447 {
00448 label gid =
00449 td.cloud().composition().localToGlobalCarrierId(GAS, i);
00450 td.cloud().rhoTrans(gid)[cellI] += np0*mass1*YMix[GAS]*YGas_[i];
00451 }
00452 forAll(YLiquid_, i)
00453 {
00454 label gid =
00455 td.cloud().composition().localToGlobalCarrierId(LIQ, i);
00456 td.cloud().rhoTrans(gid)[cellI] +=
00457 np0*mass1*YMix[LIQ]*YLiquid_[i];
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 td.cloud().UTrans()[cellI] += np0*mass1*U1;
00470 td.cloud().hsTrans()[cellI] +=
00471 np0*mass1*HEff(td, pc, T1, idG, idL, idS);
00472 }
00473 }
00474
00475
00476
00477
00478
00479 else
00480 {
00481 this->cp_ = cpEff(td, pc, T1, idG, idL, idS);
00482 this->T_ = T1;
00483 this->U_ = U1;
00484
00485
00486 if (td.constProps().constantVolume())
00487 {
00488 this->rho_ = mass1/this->volume();
00489 }
00490 else
00491 {
00492 this->d_ = cbrt(mass1/this->rho_*6.0/mathematicalConstant::pi);
00493 }
00494 }
00495 }
00496
00497
00498 template<class ParcelType>
00499 template<class TrackData>
00500 void Foam::ReactingMultiphaseParcel<ParcelType>::calcDevolatilisation
00501 (
00502 TrackData& td,
00503 const scalar dt,
00504 const scalar Ts,
00505 const scalar d,
00506 const scalar T,
00507 const scalar mass,
00508 const scalar mass0,
00509 const label idVolatile,
00510 const scalar YVolatileTot,
00511 const scalarField& YVolatile,
00512 bool& canCombust,
00513 scalarField& dMassDV,
00514 scalar& Sh,
00515 scalar& N,
00516 scalar& NCpW,
00517 scalarField& Cs
00518 ) const
00519 {
00520
00521
00522 if
00523 (
00524 !td.cloud().devolatilisation().active()
00525 || T < td.constProps().Tvap()
00526 )
00527 {
00528 return;
00529 }
00530
00531
00532 const scalar dMassTot = td.cloud().devolatilisation().calculate
00533 (
00534 dt,
00535 mass0,
00536 mass,
00537 T,
00538 td.cloud().composition().YMixture0()[idVolatile],
00539 YVolatileTot,
00540 canCombust
00541 );
00542
00543
00544 dMassDV = YVolatile*dMassTot;
00545
00546 td.cloud().addToMassDevolatilisation(this->nParticle_*dMassTot);
00547
00548 Sh -= dMassTot*td.constProps().LDevol()/dt;
00549
00550
00551 const scalar Wc = this->rhoc_*specie::RR*this->Tc_/this->pc_;
00552
00553
00554 forAll(dMassDV, i)
00555 {
00556
00557
00558 const scalar beta = sqr(cbrt(15.0) + cbrt(15.0));
00559 const label id =
00560 td.cloud().composition().localToGlobalCarrierId(GAS, i);
00561 const scalar Cp = td.cloud().mcCarrierThermo().speciesData()[id].Cp(Ts);
00562 const scalar W = td.cloud().mcCarrierThermo().speciesData()[id].W();
00563 const scalar Ni = dMassDV[i]/(this->areaS(d)*dt*W);
00564
00565
00566 const scalar Dab =
00567 3.6059e-3*(pow(1.8*Ts, 1.75))*sqrt(1.0/W + 1.0/Wc)/(this->pc_*beta);
00568
00569 N += Ni;
00570 NCpW += Ni*Cp*W;
00571 Cs[id] += Ni*d/(2.0*Dab);
00572 }
00573 }
00574
00575
00576 template<class ParcelType>
00577 template<class TrackData>
00578 void Foam::ReactingMultiphaseParcel<ParcelType>::calcSurfaceReactions
00579 (
00580 TrackData& td,
00581 const scalar dt,
00582 const label cellI,
00583 const scalar d,
00584 const scalar T,
00585 const scalar mass,
00586 const bool canCombust,
00587 const scalar N,
00588 const scalarField& YMix,
00589 const scalarField& YGas,
00590 const scalarField& YLiquid,
00591 const scalarField& YSolid,
00592 scalarField& dMassSRGas,
00593 scalarField& dMassSRLiquid,
00594 scalarField& dMassSRSolid,
00595 scalarField& dMassSRCarrier,
00596 scalar& Sh,
00597 scalar& dhsTrans
00598 ) const
00599 {
00600
00601 if (!td.cloud().surfaceReaction().active() || !canCombust)
00602 {
00603 return;
00604 }
00605
00606
00607 const scalar hReaction = td.cloud().surfaceReaction().calculate
00608 (
00609 dt,
00610 cellI,
00611 d,
00612 T,
00613 this->Tc_,
00614 this->pc_,
00615 this->rhoc_,
00616 mass,
00617 YGas,
00618 YLiquid,
00619 YSolid,
00620 YMix,
00621 N,
00622 dMassSRGas,
00623 dMassSRLiquid,
00624 dMassSRSolid,
00625 dMassSRCarrier
00626 );
00627
00628 td.cloud().addToMassSurfaceReaction
00629 (
00630 this->nParticle_
00631 *(sum(dMassSRGas) + sum(dMassSRLiquid) + sum(dMassSRSolid))
00632 );
00633
00634 const scalar xsi = min(T/5000.0, 1.0);
00635 const scalar hRetentionCoeffMod =
00636 (1.0 - xsi*xsi)*td.constProps().hRetentionCoeff();
00637
00638 Sh += hRetentionCoeffMod*hReaction/dt;
00639
00640 dhsTrans += (1.0 - hRetentionCoeffMod)*hReaction;
00641 }
00642
00643
00644
00645
00646 template <class ParcelType>
00647 Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel
00648 (
00649 const ReactingMultiphaseParcel<ParcelType>& p
00650 )
00651 :
00652 ReactingParcel<ParcelType>(p),
00653 YGas_(p.YGas_),
00654 YLiquid_(p.YLiquid_),
00655 YSolid_(p.YSolid_)
00656 {}
00657
00658
00659
00660
00661 #include "ReactingMultiphaseParcelIO.C"
00662
00663