bool Foam::CollidingParcel<ParcelType>::move ( TrackData& td, const scalar trackTime ) { typename TrackData::cloudType::parcelType& p = static_cast<typename TrackData::cloudType::parcelType&>(*this); switch (td.part()) { case TrackData::tpVelocityHalfStep: { // First and last leapfrog velocity adjust part, required // before and after tracking and force calculation p.U() += 0.5*trackTime*p.f()/p.mass(); p.angularMomentum() += 0.5*trackTime*p.torque(); td.keepParticle = true; td.switchProcessor = false; break; } case TrackData::tpLinearTrack: { ParcelType::move(td, trackTime); break; } case TrackData::tpRotationalTrack: { NotImplemented; break; } default: { FatalErrorInFunction << td.part() << " is an invalid part of the tracking method." << abort(FatalError); } } return td.keepParticle; }
void Foam::KinematicCloud<CloudType>::motion(TrackData& td) { td.part() = TrackData::tpLinearTrack; CloudType::move(td, solution_.trackTime()); updateCellOccupancy(); }
void Foam::CollidingCloud<CloudType>::moveCollide ( TrackData& td, const scalar deltaT ) { td.part() = TrackData::tpVelocityHalfStep; CloudType::move(td, deltaT); td.part() = TrackData::tpLinearTrack; CloudType::move(td, deltaT); // td.part() = TrackData::tpRotationalTrack; // CloudType::move(td); this->updateCellOccupancy(); this->collision().collide(); td.part() = TrackData::tpVelocityHalfStep; CloudType::move(td, deltaT); }
void Foam::KinematicCloud<CloudType>::evolveCloud(TrackData& td) { if (solution_.coupled()) { td.cloud().resetSourceTerms(); } if (solution_.transient()) { label preInjectionSize = this->size(); this->surfaceFilm().inject(td); // Update the cellOccupancy if the size of the cloud has changed // during the injection. if (preInjectionSize != this->size()) { updateCellOccupancy(); preInjectionSize = this->size(); } injectors_.inject(td); // Assume that motion will update the cellOccupancy as necessary // before it is required. td.cloud().motion(td); stochasticCollision().update(solution_.trackTime()); } else { // this->surfaceFilm().injectSteadyState(td); injectors_.injectSteadyState(td, solution_.trackTime()); td.part() = TrackData::tpLinearTrack; CloudType::move(td, solution_.trackTime()); } }
bool Foam::CollidingParcel<ParcelType>::move ( TrackData& td, const scalar trackTime ) { typename TrackData::cloudType::parcelType& p = static_cast<typename TrackData::cloudType::parcelType&>(*this); td.switchProcessor = false; td.keepParticle = true; const polyMesh& mesh = td.cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); const scalarField& V = mesh.cellVolumes(); switch (td.part()) { case TrackData::tpVelocityHalfStep: { // First and last leapfrog velocity adjust part, required // before and after tracking and force calculation p.U() += 0.5*trackTime*p.f()/p.mass(); p.angularMomentum() += 0.5*trackTime*p.torque(); break; } case TrackData::tpLinearTrack: { scalar tEnd = (1.0 - p.stepFraction())*trackTime; const scalar dtMax = tEnd; while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL) { // Apply correction to position for reduced-D cases meshTools::constrainToMeshCentre(mesh, p.position()); // 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 const label cellI = p.cell(); const scalar magU = mag(p.U()); if (p.active() && magU > ROOTVSMALL) { const scalar d = dt*magU; const scalar maxCo = td.cloud().solution().maxCo(); const scalar dCorr = min(d, maxCo*cbrt(V[cellI])); dt *= dCorr/d *p.trackToFace(p.position() + dCorr*p.U()/magU, td); } tEnd -= dt; p.stepFraction() = 1.0 - tEnd/trackTime; // Avoid problems with extremely small timesteps if (dt > ROOTVSMALL) { // Update cell based properties p.setCellValues(td, dt, cellI); if (td.cloud().solution().cellValueSourceCorrection()) { p.cellValueSourceCorrection(td, dt, cellI); } p.calc(td, dt, cellI); } if (p.onBoundary() && td.keepParticle) { if (isA<processorPolyPatch>(pbMesh[p.patch(p.face())])) { td.switchProcessor = true; } } p.age() += dt; } break; } case TrackData::tpRotationalTrack: { notImplemented("TrackData::tpRotationalTrack"); break; } default: { FatalErrorIn ( "CollidingParcel<ParcelType>::move(TrackData&, const scalar)" ) << td.part() << " is an invalid part of the tracking method." << abort(FatalError); } } return td.keepParticle; }
void Foam::SprayCloud<CloudType>::motion(TrackData& td) { const scalar dt = this->solution().trackTime(); td.part() = TrackData::tpLinearTrack; CloudType::move(td, dt); this->updateCellOccupancy(); if (stochasticCollision().active()) { const liquidMixtureProperties& liqMix = this->composition().liquids(); label i = 0; forAllIter(typename SprayCloud<CloudType>, *this, iter) { label j = 0; forAllIter(typename SprayCloud<CloudType>, *this, jter) { if (j > i) { parcelType& p = iter(); scalar Vi = this->mesh().V()[p.cell()]; scalarField X1(liqMix.X(p.Y())); scalar sigma1 = liqMix.sigma(p.pc(), p.T(), X1); scalar mp = p.mass()*p.nParticle(); parcelType& q = jter(); scalar Vj = this->mesh().V()[q.cell()]; scalarField X2(liqMix.X(q.Y())); scalar sigma2 = liqMix.sigma(q.pc(), q.T(), X2); scalar mq = q.mass()*q.nParticle(); bool updateProperties = stochasticCollision().update ( dt, this->rndGen(), p.position(), mp, p.d(), p.nParticle(), p.U(), p.rho(), p.T(), p.Y(), sigma1, p.cell(), Vi, q.position(), mq, q.d(), q.nParticle(), q.U(), q.rho(), q.T(), q.Y(), sigma2, q.cell(), Vj ); // for coalescence we need to update the density and // the diameter cause of the temp/conc/mass-change if (updateProperties) { if (mp > VSMALL) { scalarField Xp(liqMix.X(p.Y())); p.rho() = liqMix.rho(p.pc(), p.T(), Xp); p.Cp() = liqMix.Cp(p.pc(), p.T(), Xp); p.d() = cbrt ( 6.0*mp /( p.nParticle() *p.rho() *constant::mathematical::pi ) ); } if (mq > VSMALL) { scalarField Xq(liqMix.X(q.Y())); q.rho() = liqMix.rho(q.pc(), q.T(), Xq); q.Cp() = liqMix.Cp(q.pc(), q.T(), Xq); q.d() = cbrt ( 6.0*mq /( q.nParticle() *q.rho() *constant::mathematical::pi ) ); } } } j++; } i++; } // remove coalesced particles (diameter set to 0) forAllIter(typename SprayCloud<CloudType>, *this, iter) { parcelType& p = iter(); if (p.mass() < VSMALL) { this->deleteParticle(p); } } } }