bool Foam::solidParticle::move ( solidParticleCloud& cloud, trackingData& td, const scalar trackTime ) { td.switchProcessor = false; td.keepParticle = true; while (td.keepParticle && !td.switchProcessor && stepFraction() < 1) { if (debug) { Info<< "Time = " << mesh().time().timeName() << " trackTime = " << trackTime << " steptFraction() = " << stepFraction() << endl; } const scalar sfrac = stepFraction(); const scalar f = 1 - stepFraction(); trackToAndHitFace(f*trackTime*U_, f, cloud, td); const scalar dt = (stepFraction() - sfrac)*trackTime; const tetIndices tetIs = this->currentTetIndices(); scalar rhoc = td.rhoInterp().interpolate(this->coordinates(), tetIs); vector Uc = td.UInterp().interpolate(this->coordinates(), tetIs); scalar nuc = td.nuInterp().interpolate(this->coordinates(), tetIs); scalar rhop = cloud.rhop(); scalar magUr = mag(Uc - U_); scalar ReFunc = 1.0; scalar Re = magUr*d_/nuc; if (Re > 0.01) { ReFunc += 0.15*pow(Re, 0.687); } scalar Dc = (24.0*nuc/d_)*ReFunc*(3.0/4.0)*(rhoc/(d_*rhop)); U_ = (U_ + dt*(Dc*Uc + (1.0 - rhoc/rhop)*td.g()))/(1.0 + dt*Dc); } return td.keepParticle; }
//- Move a softParticle from one position to another. bool Foam::softParticle::move ( trackingData& td, const scalar trackTime ) { td.switchProcessor = false; td.keepParticle = true; const polyBoundaryMesh& pbMesh = mesh_.boundaryMesh(); scalar tEnd = (1.0 - stepFraction())*trackTime; scalar dtMax = tEnd; while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL) { if (debug) { Pout<< "Time = " << mesh_.time().timeName() << " trackTime = " << trackTime << " steptFraction() = " << stepFraction() << endl; Pout<< "Before trackToFace, particle tag is: " << ptag() << ". Particle position is: " << position() << endl; } scalar dt = min(dtMax, tEnd); dt *= trackToFace(position() + dt*moveU_, td); tEnd -= dt; stepFraction() = 1.0 - tEnd/trackTime; if (debug) { Pout<< "After trackToFace, particle tag is: " << ptag() << ". Particle position is: " << position() << endl; } if (onBoundary() && td.keepParticle) { if (isA<processorPolyPatch>(pbMesh[patch(face())])) { td.switchProcessor = true; // Pout<< "Cross the processor boundary.." << endl; } } } return td.keepParticle; }
bool Foam::molecule::move ( moleculeCloud& cloud, trackingData& td, const scalar trackTime ) { td.switchProcessor = false; td.keepParticle = true; const constantProperties& constProps(cloud.constProps(id_)); if (td.part() == 0) { // First leapfrog velocity adjust part, required before tracking+force // part v_ += 0.5*trackTime*a_; pi_ += 0.5*trackTime*tau_; } else if (td.part() == 1) { // Leapfrog tracking part while (td.keepParticle && !td.switchProcessor && stepFraction() < 1) { const scalar f = 1 - stepFraction(); trackToAndHitFace(f*trackTime*v_, f, cloud, td); } } else if (td.part() == 2) { // Leapfrog orientation adjustment, carried out before force calculation // but after tracking stage, i.e. rotation carried once linear motion // complete. if (!constProps.pointMolecule()) { const diagTensor& momentOfInertia(constProps.momentOfInertia()); tensor R; if (!constProps.linearMolecule()) { R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx()); pi_ = pi_ & R; Q_ = Q_ & R; } R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy()); pi_ = pi_ & R; Q_ = Q_ & R; R = rotationTensorZ(trackTime*pi_.z()/momentOfInertia.zz()); pi_ = pi_ & R; Q_ = Q_ & R; R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy()); pi_ = pi_ & R; Q_ = Q_ & R; if (!constProps.linearMolecule()) { R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx()); pi_ = pi_ & R; Q_ = Q_ & R; } } setSitePositions(constProps); } else if (td.part() == 3) { // Second leapfrog velocity adjust part, required after tracking+force // part scalar m = constProps.mass(); a_ = Zero; tau_ = Zero; forAll(siteForces_, s) { const vector& f = siteForces_[s]; a_ += f/m; tau_ += (constProps.siteReferencePositions()[s] ^ (Q_.T() & f)); } v_ += 0.5*trackTime*a_; pi_ += 0.5*trackTime*tau_; if (constProps.pointMolecule()) { tau_ = Zero; pi_ = Zero; } if (constProps.linearMolecule()) { tau_.x() = 0.0; pi_.x() = 0.0; } }
bool Foam::molecule::move(molecule::trackingData& td, const scalar trackTime) { td.switchProcessor = false; td.keepParticle = true; const constantProperties& constProps(td.cloud().constProps(id_)); if (td.part() == 0) { // First leapfrog velocity adjust part, required before tracking+force // part v_ += 0.5*trackTime*a_; pi_ += 0.5*trackTime*tau_; } else if (td.part() == 1) { // Leapfrog tracking part scalar tEnd = (1.0 - stepFraction())*trackTime; scalar dtMax = tEnd; while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL) { // set the lagrangian time-step scalar dt = min(dtMax, tEnd); dt *= trackToFace(position() + dt*v_, td); tEnd -= dt; stepFraction() = 1.0 - tEnd/trackTime; } } else if (td.part() == 2) { // Leapfrog orientation adjustment, carried out before force calculation // but after tracking stage, i.e. rotation carried once linear motion // complete. if (!constProps.pointMolecule()) { const diagTensor& momentOfInertia(constProps.momentOfInertia()); tensor R; if (!constProps.linearMolecule()) { R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx()); pi_ = pi_ & R; Q_ = Q_ & R; } R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy()); pi_ = pi_ & R; Q_ = Q_ & R; R = rotationTensorZ(trackTime*pi_.z()/momentOfInertia.zz()); pi_ = pi_ & R; Q_ = Q_ & R; R = rotationTensorY(0.5*trackTime*pi_.y()/momentOfInertia.yy()); pi_ = pi_ & R; Q_ = Q_ & R; if (!constProps.linearMolecule()) { R = rotationTensorX(0.5*trackTime*pi_.x()/momentOfInertia.xx()); pi_ = pi_ & R; Q_ = Q_ & R; } } setSitePositions(constProps); } else if (td.part() == 3) { // Second leapfrog velocity adjust part, required after tracking+force // part scalar m = constProps.mass(); a_ = vector::zero; tau_ = vector::zero; forAll(siteForces_, s) { const vector& f = siteForces_[s]; a_ += f/m; tau_ += (constProps.siteReferencePositions()[s] ^ (Q_.T() & f)); } v_ += 0.5*trackTime*a_; pi_ += 0.5*trackTime*tau_; if (constProps.pointMolecule()) { tau_ = vector::zero; pi_ = vector::zero; } if (constProps.linearMolecule()) { tau_.x() = 0.0; pi_.x() = 0.0; } }
bool Foam::parcel::move(spray& sDB) { const polyMesh& mesh = cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); const liquidMixture& fuels = sDB.fuels(); scalar deltaT = sDB.runTime().deltaT().value(); label Nf = fuels.components().size(); label Ns = sDB.composition().Y().size(); // Calculate the interpolated gas properties at the position of the parcel vector Up = sDB.UInterpolator().interpolate(position(), cell()) + Uturb(); scalar rhog = sDB.rhoInterpolator().interpolate(position(), cell()); scalar pg = sDB.pInterpolator().interpolate(position(), cell()); scalar Tg = sDB.TInterpolator().interpolate(position(), cell()); scalarField Yfg(Nf, 0.0); scalar cpMixture = 0.0; for(label i=0; i<Ns; i++) { const volScalarField& Yi = sDB.composition().Y()[i]; if (sDB.isLiquidFuel()[i]) { label j = sDB.gasToLiquidIndex()[i]; scalar Yicelli = Yi[cell()]; Yfg[j] = Yicelli; } cpMixture += Yi[cell()]*sDB.gasProperties()[i].Cp(Tg); } // Correct the gaseous temperature for evaporated fuel scalar cellV = sDB.mesh().V()[cell()]; scalar cellMass = rhog*cellV; Tg += sDB.shs()[cell()]/(cpMixture*cellMass); // Changed cut-off temperature for evaporation. HJ, 27/Apr/2011 Tg = max(273, Tg); scalar tauMomentum = GREAT; scalar tauHeatTransfer = GREAT; scalarField tauEvaporation(Nf, GREAT); scalarField tauBoiling(Nf, GREAT); bool keepParcel = true; setRelaxationTimes ( cell(), tauMomentum, tauEvaporation, tauHeatTransfer, tauBoiling, sDB, rhog, Up, Tg, pg, Yfg, m()*fuels.Y(X()), deltaT ); // set the end-time for the track scalar tEnd = (1.0 - stepFraction())*deltaT; // Set the maximum time step for this parcel // FPK changes: avoid temperature-out-of-range errors // in spray tracking. HJ, 13/Oct/2007 // tauEvaporation no longer multiplied by 1e20, // to account for the evaporation timescale // FPK, 13/Oct/2007 scalar dtMax = min ( tEnd, min ( tauMomentum, min ( mag(min(tauEvaporation)), min ( mag(tauHeatTransfer), mag(min(tauBoiling)) ) ) ) )/sDB.subCycles(); // prevent the number of subcycles from being too many // (10 000 seems high enough) dtMax = max(dtMax, 1.0e-4*tEnd); bool switchProcessor = false; vector planeNormal = vector::zero; if (sDB.twoD()) { planeNormal = n() ^ sDB.axisOfSymmetry(); planeNormal /= mag(planeNormal); } // move the parcel until there is no 'timeLeft' while (keepParcel && tEnd > SMALL && !switchProcessor) { // set the lagrangian time-step scalar dt = min(dtMax, tEnd); // remember which cell the parcel is in // since this will change if a face is hit label celli = cell(); scalar p = sDB.p()[celli]; // track parcel to face, or end of trajectory if (keepParcel) { // Track and adjust the time step if the trajectory // is not completed dt *= trackToFace(position() + dt*U_, sDB); // Decrement the end-time acording to how much time the track took tEnd -= dt; // Set the current time-step fraction. stepFraction() = 1.0 - tEnd/deltaT; if (onBoundary()) // hit face { # include "boundaryTreatment.H" } } if (keepParcel && sDB.twoD()) { scalar z = position() & sDB.axisOfSymmetry(); vector r = position() - z*sDB.axisOfSymmetry(); if (mag(r) > SMALL) { correctNormal(sDB.axisOfSymmetry()); } } // **** calculate the lagrangian source terms **** // First we get the 'old' properties. // and then 'update' them to get the 'new' // properties. // The difference is then added to the source terms. scalar oRho = fuels.rho(p, T(), X()); scalarField oMass(Nf, 0.0); scalar oHg = 0.0; scalar oTotMass = m(); scalarField oYf(fuels.Y(X())); forAll(oMass, i) { oMass[i] = m()*oYf[i]; label j = sDB.liquidToGasIndex()[i]; oHg += oYf[i]*sDB.gasProperties()[j].Hs(T()); } vector oMom = m()*U(); scalar oHv = fuels.hl(p, T(), X()); scalar oH = oHg - oHv; scalar oPE = (p - fuels.pv(p, T(), X()))/oRho; // update the parcel properties (U, T, D) updateParcelProperties ( dt, sDB, celli, face() ); scalar nRho = fuels.rho(p, T(), X()); scalar nHg = 0.0; scalarField nMass(Nf, 0.0); scalarField nYf(fuels.Y(X())); forAll(nMass, i) { nMass[i] = m()*nYf[i]; label j = sDB.liquidToGasIndex()[i]; nHg += nYf[i]*sDB.gasProperties()[j].Hs(T()); }
bool Foam::solidParticle::move(solidParticle::trackData& td) { td.switchProcessor = false; td.keepParticle = true; const polyMesh& mesh = cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); scalar deltaT = mesh.time().deltaT().value(); scalar tEnd = (1.0 - stepFraction())*deltaT; scalar dtMax = tEnd; while (td.keepParticle && !td.switchProcessor && tEnd > SMALL) { if (debug) { Info<< "Time = " << mesh.time().timeName() << " deltaT = " << deltaT << " tEnd = " << tEnd << " steptFraction() = " << stepFraction() << endl; } // set the lagrangian time-step scalar dt = min(dtMax, tEnd); // remember which cell the parcel is in // since this will change if a face is hit label celli = cell(); dt *= trackToFace(position() + dt*U_, td); tEnd -= dt; stepFraction() = 1.0 - tEnd/deltaT; cellPointWeight cpw(mesh, position(), celli, face()); scalar rhoc = td.rhoInterp().interpolate(cpw); vector Uc = td.UInterp().interpolate(cpw); scalar nuc = td.nuInterp().interpolate(cpw); scalar rhop = td.spc().rhop(); scalar magUr = mag(Uc - U_); scalar ReFunc = 1.0; scalar Re = magUr*d_/nuc; if (Re > 0.01) { ReFunc += 0.15*pow(Re, 0.687); } scalar Dc = (24.0*nuc/d_)*ReFunc*(3.0/4.0)*(rhoc/(d_*rhop)); U_ = (U_ + dt*(Dc*Uc + (1.0 - rhoc/rhop)*td.g()))/(1.0 + dt*Dc); if (onBoundary() && td.keepParticle) { // Bug fix. HJ, 25/Aug/2010 if (face() > -1) { if (isType<processorPolyPatch>(pbMesh[patch(face())])) { td.switchProcessor = true; } } } } return td.keepParticle; }