void Foam::ThermoParcel<ParcelType>::setCellValues ( TrackData& td, const scalar dt, const label cellI ) { ParcelType::setCellValues(td, dt, cellI); tetIndices tetIs = this->currentTetIndices(); Cpc_ = td.CpInterp().interpolate(this->position(), tetIs); Tc_ = td.TInterp().interpolate(this->position(), tetIs); if (Tc_ < td.cloud().constProps().TMin()) { if (debug) { WarningIn ( "void Foam::ThermoParcel<ParcelType>::setCellValues" "(" "TrackData&, " "const scalar, " "const label" ")" ) << "Limiting observed temperature in cell " << cellI << " to " << td.cloud().constProps().TMin() << nl << endl; } Tc_ = td.cloud().constProps().TMin(); } }
bool Foam::KinematicParcel<ParcelType>::hitPatch ( const polyPatch& pp, TrackData& td, const label patchI, const scalar trackFraction, const tetIndices& tetIs ) { typename TrackData::cloudType::parcelType& p = static_cast<typename TrackData::cloudType::parcelType&>(*this); // Invoke post-processing model td.cloud().functions().postPatch(p, patchI, pp.whichFace(p.face())); // Invoke surface film model if (td.cloud().surfaceFilm().transferParcel(p, pp, td.keepParticle)) { // All interactions done return true; } else { // Invoke patch interaction model return td.cloud().patchInteraction().correct ( p, pp, td.keepParticle, trackFraction, tetIs ); } }
void Foam::ThermoParcel<ParcelType>::setCellValues ( TrackData& td, const scalar dt, const label cellI ) { KinematicParcel<ParcelType>::setCellValues(td, dt, cellI); cpc_ = td.cpInterp().interpolate(this->position(), cellI); Tc_ = td.TInterp().interpolate(this->position(), cellI); if (Tc_ < td.constProps().TMin()) { WarningIn ( "void Foam::ThermoParcel<ParcelType>::setCellValues" "(" "TrackData&, " "const scalar, " "const label" ")" ) << "Limiting observed temperature in cell " << cellI << " to " << td.constProps().TMin() << nl << endl; Tc_ = td.constProps().TMin(); } }
void Tracks::list() { QMapIterator<int, TrackData> i(tm); while (i.hasNext()) { i.next(); TrackData d = i.value(); qDebug("Tracks::list: item %d: ID: %d lang: '%s' name: '%s'", i.key(), d.ID(), d.lang().toUtf8().constData(), d.name().toUtf8().constData() ); } }
bool Foam::KinematicParcel<ParcelType>::move(TrackData& td) { ParcelType& p = static_cast<ParcelType&>(*this); td.switchProcessor = false; td.keepParticle = true; const polyMesh& mesh = td.cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); const scalar deltaT = mesh.time().deltaTValue(); scalar tEnd = (1.0 - p.stepFraction())*deltaT; 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 label cellI = p.cell(); dt *= p.trackToFace(p.position() + dt*U_, td); tEnd -= dt; p.stepFraction() = 1.0 - tEnd/deltaT; // Avoid problems with extremely small timesteps if (dt > ROOTVSMALL) { // Update cell based properties p.setCellValues(td, dt, cellI); if (td.cloud().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; } } } return td.keepParticle; }
Foam::scalar Foam::ThermoParcel<ParcelType>::calcHeatTransfer ( TrackData& td, const scalar dt, const label cellI, const scalar Re, const scalar Pr, const scalar kappa, const scalar d, const scalar rho, const scalar T, const scalar cp, const scalar NCpW, const scalar Sh, scalar& dhsTrans ) { if (!td.cloud().heatTransfer().active()) { return T; } // Calc heat transfer coefficient scalar htc = td.cloud().heatTransfer().htc(d, Re, Pr, kappa, NCpW); if (mag(htc) < ROOTVSMALL && !td.cloud().radiation()) { return max(T + dt*Sh/(this->volume(d)*rho*cp), td.constProps().TMin()); } const scalar As = this->areaS(d); scalar ap = Tc_ + Sh/As/htc; scalar bp = 6.0*(Sh/As + htc*(Tc_ - T)); if (td.cloud().radiation()) { const scalarField& G = td.cloud().mesh().objectRegistry::template lookupObject<volScalarField>("G"); const scalar Gc = G[cellI]; const scalar sigma = radiation::sigmaSB.value(); const scalar epsilon = td.constProps().epsilon0(); ap = (ap + epsilon*Gc/(4.0*htc))/(1.0 + epsilon*sigma*pow3(T)/htc); bp += 6.0*(epsilon*(Gc/4.0 - sigma*pow4(T))); } bp /= rho*d*cp*(ap - T); // Integrate to find the new parcel temperature IntegrationScheme<scalar>::integrationResult Tres = td.cloud().TIntegrator().integrate(T, dt, ap, bp); scalar Tnew = max(Tres.value(), td.constProps().TMin()); dhsTrans += dt*htc*As*(0.5*(T + Tnew) - Tc_); return Tnew; }
void Foam::ThermoParcel<ParcelType>::calcSurfaceValues ( TrackData& td, const label cellI, const scalar T, scalar& Ts, scalar& rhos, scalar& mus, scalar& Pr, scalar& kappas ) const { // Surface temperature using two thirds rule Ts = (2.0*T + Tc_)/3.0; if (Ts < td.cloud().constProps().TMin()) { if (debug) { WarningIn ( "void Foam::ThermoParcel<ParcelType>::calcSurfaceValues" "(" "TrackData&, " "const label, " "const scalar, " "scalar&, " "scalar&, " "scalar&, " "scalar&, " "scalar&" ") const" ) << "Limiting parcel surface temperature to " << td.cloud().constProps().TMin() << nl << endl; } Ts = td.cloud().constProps().TMin(); } // Assuming thermo props vary linearly with T for small d(T) const scalar TRatio = Tc_/Ts; rhos = this->rhoc_*TRatio; tetIndices tetIs = this->currentTetIndices(); mus = td.muInterp().interpolate(this->position(), tetIs)/TRatio; Pr = td.cloud().constProps().Pr(); Pr = max(ROOTVSMALL, Pr); kappas = Cpc_*mus/Pr; kappas = max(ROOTVSMALL, kappas); }
void Foam::ThermoParcel<ParcelType>::cellValueSourceCorrection ( TrackData& td, const scalar dt, const label cellI ) { this->Uc_ += td.cloud().UTrans()[cellI]/this->massCell(cellI); scalar cpMean = td.cpInterp().psi()[cellI]; Tc_ += td.cloud().hsTrans()[cellI]/(cpMean*this->massCell(cellI)); }
const Foam::vector Foam::KinematicParcel<ParcelType>::calcVelocity ( TrackData& td, const scalar dt, const label cellI, const scalar Re, const scalar mu, const scalar mass, const vector& Su, vector& dUTrans, scalar& Spu ) const { typedef typename TrackData::cloudType cloudType; typedef typename cloudType::parcelType parcelType; typedef typename cloudType::forceType forceType; const forceType& forces = td.cloud().forces(); // Momentum source due to particle forces const parcelType& p = static_cast<const parcelType&>(*this); const forceSuSp Fcp = forces.calcCoupled(p, dt, mass, Re, mu); const forceSuSp Fncp = forces.calcNonCoupled(p, dt, mass, Re, mu); const forceSuSp Feff = Fcp + Fncp; const scalar massEff = forces.massEff(p, mass); // New particle velocity //~~~~~~~~~~~~~~~~~~~~~~ // Update velocity - treat as 3-D const vector abp = (Feff.Sp()*Uc_ + (Feff.Su() + Su))/massEff; const scalar bp = Feff.Sp()/massEff; Spu = dt*Feff.Sp(); IntegrationScheme<vector>::integrationResult Ures = td.cloud().UIntegrator().integrate(U_, dt, abp, bp); vector Unew = Ures.value(); // note: Feff.Sp() and Fc.Sp() must be the same dUTrans += dt*(Feff.Sp()*(Ures.average() - Uc_) - Fcp.Su()); // Apply correction to velocity and dUTrans for reduced-D cases const polyMesh& mesh = td.cloud().pMesh(); meshTools::constrainDirection(mesh, mesh.solutionD(), Unew); meshTools::constrainDirection(mesh, mesh.solutionD(), dUTrans); return Unew; }
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::KinematicParcel<ParcelType>::calc ( TrackData& td, const scalar dt, const label cellI ) { // Define local properties at beginning of time step // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const scalar np0 = nParticle_; const scalar d0 = d_; const vector U0 = U_; const scalar rho0 = rho_; const scalar mass0 = mass(); // Reynolds number const scalar Re = this->Re(U0, d0, rhoc_, muc_); // Sources //~~~~~~~~ // Explicit momentum source for particle vector Su = vector::zero; // Momentum transfer from the particle to the carrier phase vector dUTrans = vector::zero; // Motion // ~~~~~~ // Calculate new particle velocity vector U1 = calcVelocity(td, dt, cellI, Re, muc_, d0, U0, rho0, mass0, Su, dUTrans); // Accumulate carrier phase source terms // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (td.cloud().coupled()) { // Update momentum transfer td.cloud().UTrans()[cellI] += np0*dUTrans; } // Set new particle properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ U_ = U1; }
Foam::scalar Foam::ReactingMultiphaseParcel<ParcelType>::LEff ( TrackData& td, const scalar p, const scalar T, const label idG, const label idL, const label idS ) const { return this->Y_[GAS]*td.cloud().composition().L(idG, YGas_, p, T) + this->Y_[LIQ]*td.cloud().composition().L(idL, YLiquid_, p, T) + this->Y_[SLD]*td.cloud().composition().L(idS, YSolid_, p, T); }
const Foam::vector Foam::KinematicParcel<ParcelType>::calcVelocity ( TrackData& td, const scalar dt, const label cellI, const scalar Re, const scalar mu, const scalar d, const vector& U, const scalar rho, const scalar mass, const vector& Su, vector& dUTrans ) const { const polyMesh& mesh = this->cloud().pMesh(); // Momentum transfer coefficient const scalar utc = td.cloud().drag().utc(Re, d, mu) + ROOTVSMALL; // Momentum source due to particle forces const vector FCoupled = mass*td.cloud().forces().calcCoupled(cellI, dt, rhoc_, rho, Uc_, U); const vector FNonCoupled = mass*td.cloud().forces().calcNonCoupled(cellI, dt, rhoc_, rho, Uc_, U); // New particle velocity //~~~~~~~~~~~~~~~~~~~~~~ // Update velocity - treat as 3-D const scalar As = this->areaS(d); const vector ap = Uc_ + (FCoupled + FNonCoupled + Su)/(utc*As); const scalar bp = 6.0*utc/(rho*d); IntegrationScheme<vector>::integrationResult Ures = td.cloud().UIntegrator().integrate(U, dt, ap, bp); vector Unew = Ures.value(); dUTrans += dt*(utc*As*(Ures.average() - Uc_) - FCoupled); // Apply correction to velocity and dUTrans for reduced-D cases meshTools::constrainDirection(mesh, mesh.solutionD(), Unew); meshTools::constrainDirection(mesh, mesh.solutionD(), dUTrans); return Unew; }
void Foam::KinematicCloud<CloudType>::motion(TrackData& td) { td.part() = TrackData::tpLinearTrack; CloudType::move(td, solution_.trackTime()); updateCellOccupancy(); }
void Foam::KinematicParcel<ParcelType>::hitFace(TrackData& td) { typename TrackData::cloudType::parcelType& p = static_cast<typename TrackData::cloudType::parcelType&>(*this); td.cloud().functions().postFace(p, p.face()); }
void Foam::KinematicParcel<ParcelType>::calc ( TrackData& td, const scalar dt, const label cellI ) { // Define local properties at beginning of time step // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const scalar np0 = nParticle_; const scalar mass0 = mass(); // Reynolds number const scalar Re = this->Re(U_, d_, rhoc_, muc_); // Sources //~~~~~~~~ // Explicit momentum source for particle vector Su = vector::zero; // Linearised momentum source coefficient scalar Spu = 0.0; // Momentum transfer from the particle to the carrier phase vector dUTrans = vector::zero; // Motion // ~~~~~~ // Calculate new particle velocity this->U_ = calcVelocity(td, dt, cellI, Re, muc_, mass0, Su, dUTrans, Spu); // Accumulate carrier phase source terms // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (td.cloud().solution().coupled()) { // Update momentum transfer td.cloud().UTrans()[cellI] += np0*dUTrans; // Update momentum transfer coefficient td.cloud().UCoeff()[cellI] += np0*Spu; } }
bool Foam::KinematicParcel<ParcelType>::hitPatch ( const polyPatch& pp, TrackData& td, const label patchI ) { ParcelType& p = static_cast<ParcelType&>(*this); td.cloud().postProcessing().postPatch(p, patchI); return td.cloud().patchInteraction().correct ( pp, this->face(), td.keepParticle, U_ ); }
void Foam::KinematicParcel<ParcelType>::cellValueSourceCorrection ( TrackData& td, const scalar dt, const label cellI ) { Uc_ += td.cloud().UTrans()[cellI]/massCell(cellI); }
void TCXParser::course(TrackData &track) { while (_reader.readNextStartElement()) { if (_reader.name() == "Track") trackpoints(track); else if (_reader.name() == "Name") track.setName(_reader.readElementText()); else if (_reader.name() == "Notes") track.setDescription(_reader.readElementText()); else if (_reader.name() == "CoursePoint") { Waypoint w; waypointData(w); if (!w.coordinates().isNull()) _waypoints.append(w); else warning("Missing Trackpoint coordinates"); } else _reader.skipCurrentElement(); } }
bool Foam::DsmcParcel<ParcelType>::move ( TrackData& td ) { ParcelType& p = static_cast<ParcelType&>(*this); td.switchProcessor = false; td.keepParticle = true; const polyMesh& mesh = td.cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); const scalar deltaT = mesh.time().deltaTValue(); scalar tEnd = (1.0 - p.stepFraction())*deltaT; const scalar dtMax = tEnd; // For reduced-D cases, the velocity used to track needs to be // constrained, but the actual U_ of the parcel must not be // altered or used, as it is altered by patch interactions an // needs to retain its 3D value for collision purposes. vector Utracking = U_; while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL) { // Apply correction to position for reduced-D cases meshTools::constrainToMeshCentre(mesh, p.position()); Utracking = U_; // Apply correction to velocity to constrain tracking for // reduced-D cases meshTools::constrainDirection(mesh, mesh.solutionD(), Utracking); // Set the Lagrangian time-step scalar dt = min(dtMax, tEnd); dt *= p.trackToFace(p.position() + dt*Utracking, td); tEnd -= dt; p.stepFraction() = 1.0 - tEnd/deltaT; if (p.onBoundary() && td.keepParticle) { if (isA<processorPolyPatch>(pbMesh[p.patch(p.face())])) { td.switchProcessor = true; } } } return td.keepParticle; }
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()); } }
void Foam::ThermoParcel<ParcelType>::cellValueSourceCorrection ( TrackData& td, const scalar dt, const label cellI ) { this->Uc_ += td.cloud().UTrans()[cellI]/this->massCell(cellI); const scalar CpMean = td.CpInterp().psi()[cellI]; Tc_ += td.cloud().hsTrans()[cellI]/(CpMean*this->massCell(cellI)); if (Tc_ < td.cloud().constProps().TMin()) { if (debug) { WarningIn ( "void Foam::ThermoParcel<ParcelType>::cellValueSourceCorrection" "(" "TrackData&, " "const scalar, " "const label" ")" ) << "Limiting observed temperature in cell " << cellI << " to " << td.cloud().constProps().TMin() << nl << endl; } Tc_ = td.cloud().constProps().TMin(); } }
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::ThermoParcel<ParcelType>::calcSurfaceValues ( TrackData& td, const label cellI, const scalar T, scalar& Ts, scalar& rhos, scalar& mus, scalar& Pr, scalar& kappa ) const { // Surface temperature using two thirds rule Ts = (2.0*T + Tc_)/3.0; // Assuming thermo props vary linearly with T for small dT scalar factor = td.TInterp().interpolate(this->position(), cellI)/Ts; rhos = this->rhoc_*factor; mus = td.muInterp().interpolate(this->position(), cellI)/factor; Pr = td.constProps().Pr(); kappa = cpc_*mus/Pr; }
void TCXParser::trackpoints(TrackData &track) { while (_reader.readNextStartElement()) { if (_reader.name() == "Trackpoint") { Trackpoint t; trackpointData(t); if (!t.coordinates().isNull()) track.append(t); else warning("Missing Trackpoint coordinates"); } else _reader.skipCurrentElement(); } }
void Foam::KinematicCloud<CloudType>::solve(TrackData& td) { if (solution_.steadyState()) { td.cloud().storeState(); td.cloud().preEvolve(); evolveCloud(td); if (solution_.coupled()) { td.cloud().relaxSources(td.cloud().cloudCopy()); } } else { td.cloud().preEvolve(); evolveCloud(td); if (solution_.coupled()) { td.cloud().scaleSources(); } } td.cloud().info(); td.cloud().postEvolve(); if (solution_.steadyState()) { td.cloud().restoreState(); } }
void Foam::KinematicParcel<ParcelType>::setCellValues ( TrackData& td, const scalar dt, const label cellI ) { tetIndices tetIs = this->currentTetIndices(); rhoc_ = td.rhoInterp().interpolate(this->position(), tetIs); if (rhoc_ < td.cloud().constProps().rhoMin()) { if (debug) { WarningIn ( "void Foam::KinematicParcel<ParcelType>::setCellValues" "(" "TrackData&, " "const scalar, " "const label" ")" ) << "Limiting observed density in cell " << cellI << " to " << td.cloud().constProps().rhoMin() << nl << endl; } rhoc_ = td.cloud().constProps().rhoMin(); } Uc_ = td.UInterp().interpolate(this->position(), tetIs); muc_ = td.muInterp().interpolate(this->position(), tetIs); // Apply dispersion components to carrier phase velocity Uc_ = td.cloud().dispersion().update ( dt, cellI, U_, Uc_, UTurb_, tTurb_ ); }
void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td) { if (!this->active()) { return; } // Retrieve the film model from the owner database const regionModels::surfaceFilmModels::surfaceFilmModel& filmModel = this->owner().db().objectRegistry::template lookupObject <regionModels::surfaceFilmModels::surfaceFilmModel> ( "surfaceFilmProperties" ); if (!filmModel.active()) { return; } const labelList& filmPatches = filmModel.intCoupledPatchIDs(); const labelList& primaryPatches = filmModel.primaryPatchIDs(); const fvMesh& mesh = this->owner().mesh(); const polyBoundaryMesh& pbm = mesh.boundaryMesh(); forAll(filmPatches, i) { const label filmPatchI = filmPatches[i]; const label primaryPatchI = primaryPatches[i]; const labelList& injectorCellsPatch = pbm[primaryPatchI].faceCells(); cacheFilmFields(filmPatchI, primaryPatchI, filmModel); const vectorField& Cf = mesh.C().boundaryField()[primaryPatchI]; const vectorField& Sf = mesh.Sf().boundaryField()[primaryPatchI]; const scalarField& magSf = mesh.magSf().boundaryField()[primaryPatchI]; forAll(injectorCellsPatch, j) { if (diameterParcelPatch_[j] > 0) { const label cellI = injectorCellsPatch[j]; // The position could bein any tet of the decomposed cell, // so arbitrarily choose the first face of the cell as the // tetFace and the first point on the face after the base // point as the tetPt. The tracking will pick the cell // consistent with the motion in the first tracking step. const label tetFaceI = this->owner().mesh().cells()[cellI][0]; const label tetPtI = 1; // const point& pos = this->owner().mesh().C()[cellI]; const scalar offset = max ( diameterParcelPatch_[j], deltaFilmPatch_[primaryPatchI][j] ); const point pos = Cf[j] - 1.1*offset*Sf[j]/magSf[j]; // Create a new parcel parcelType* pPtr = new parcelType ( this->owner().pMesh(), pos, cellI, tetFaceI, tetPtI ); // Check/set new parcel thermo properties td.cloud().setParcelThermoProperties(*pPtr, 0.0); setParcelProperties(*pPtr, j); if (pPtr->nParticle() > 0.001) { // Check new parcel properties // td.cloud().checkParcelProperties(*pPtr, 0.0, true); td.cloud().checkParcelProperties(*pPtr, 0.0, false); // Add the new parcel to the cloud td.cloud().addParticle(pPtr); nParcelsInjected_++; } else { // TODO: cache mass and re-distribute? delete pPtr; } } } } }
Foam::scalar Foam::ThermoParcel<ParcelType>::calcHeatTransfer ( TrackData& td, const scalar dt, const label cellI, const scalar Re, const scalar Pr, const scalar kappa, const scalar NCpW, const scalar Sh, scalar& dhsTrans, scalar& Sph ) { if (!td.cloud().heatTransfer().active()) { return T_; } const scalar d = this->d(); const scalar rho = this->rho(); // Calc heat transfer coefficient scalar htc = td.cloud().heatTransfer().htc(d, Re, Pr, kappa, NCpW); if (mag(htc) < ROOTVSMALL && !td.cloud().radiation()) { return max ( T_ + dt*Sh/(this->volume(d)*rho*Cp_), td.cloud().constProps().TMin() ); } htc = max(htc, ROOTVSMALL); const scalar As = this->areaS(d); scalar ap = Tc_ + Sh/(As*htc); scalar bp = 6.0*(Sh/As + htc*(Tc_ - T_)); if (td.cloud().radiation()) { tetIndices tetIs = this->currentTetIndices(); const scalar Gc = td.GInterp().interpolate(this->position(), tetIs); const scalar sigma = physicoChemical::sigma.value(); const scalar epsilon = td.cloud().constProps().epsilon0(); // Assume constant source scalar s = epsilon*(Gc/4.0 - sigma*pow4(T_)); ap += s/htc; bp += 6.0*s; } bp /= rho*d*Cp_*(ap - T_) + ROOTVSMALL; // Integrate to find the new parcel temperature IntegrationScheme<scalar>::integrationResult Tres = td.cloud().TIntegrator().integrate(T_, dt, ap*bp, bp); scalar Tnew = min ( max ( Tres.value(), td.cloud().constProps().TMin() ), td.cloud().constProps().TMax() ); Sph = dt*htc*As; dhsTrans += Sph*(Tres.average() - Tc_); return Tnew; }
void Foam::ThermoParcel<ParcelType>::calc ( TrackData& td, const scalar dt, const label cellI ) { // Define local properties at beginning of time step // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const scalar np0 = this->nParticle_; const scalar mass0 = this->mass(); // Store T for consistent radiation source const scalar T0 = this->T_; // Calc surface values // ~~~~~~~~~~~~~~~~~~~ scalar Ts, rhos, mus, Pr, kappas; calcSurfaceValues(td, cellI, this->T_, Ts, rhos, mus, Pr, kappas); // Reynolds number scalar Re = this->Re(this->U_, this->d_, rhos, mus); // Sources // ~~~~~~~ // Explicit momentum source for particle vector Su = vector::zero; // Linearised momentum source coefficient scalar Spu = 0.0; // Momentum transfer from the particle to the carrier phase vector dUTrans = vector::zero; // Explicit enthalpy source for particle scalar Sh = 0.0; // Linearised enthalpy source coefficient scalar Sph = 0.0; // Sensible enthalpy transfer from the particle to the carrier phase scalar dhsTrans = 0.0; // Heat transfer // ~~~~~~~~~~~~~ // Sum Ni*Cpi*Wi of emission species scalar NCpW = 0.0; // Calculate new particle temperature this->T_ = this->calcHeatTransfer ( td, dt, cellI, Re, Pr, kappas, NCpW, Sh, dhsTrans, Sph ); // Motion // ~~~~~~ // Calculate new particle velocity this->U_ = this->calcVelocity(td, dt, cellI, Re, mus, mass0, Su, dUTrans, Spu); // Accumulate carrier phase source terms // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (td.cloud().solution().coupled()) { // Update momentum transfer td.cloud().UTrans()[cellI] += np0*dUTrans; // Update momentum transfer coefficient td.cloud().UCoeff()[cellI] += np0*Spu; // Update sensible enthalpy transfer td.cloud().hsTrans()[cellI] += np0*dhsTrans; // Update sensible enthalpy coefficient td.cloud().hsCoeff()[cellI] += np0*Sph; // Update radiation fields if (td.cloud().radiation()) { const scalar ap = this->areaP(); const scalar T4 = pow4(T0); td.cloud().radAreaP()[cellI] += dt*np0*ap; td.cloud().radT4()[cellI] += dt*np0*T4; td.cloud().radAreaPT4()[cellI] += dt*np0*ap*T4; } } }