/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "streamLineParticle.H" #include "vectorFieldIOField.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::vector Foam::streamLineParticle::interpolateFields ( const trackingData& td, const point& position, const label celli, const label facei ) { if (celli == -1) { FatalErrorInFunction << "Cell:" << celli << abort(FatalError); } sampledScalars_.setSize(td.vsInterp_.size()); forAll(td.vsInterp_, scalari) { sampledScalars_[scalari].append ( td.vsInterp_[scalari].interpolate ( position, celli, facei ) ); } sampledVectors_.setSize(td.vvInterp_.size()); forAll(td.vvInterp_, vectori) { sampledVectors_[vectori].append ( td.vvInterp_[vectori].interpolate ( position, celli, facei ) ); } const DynamicList& U = sampledVectors_[td.UIndex_]; return U.last(); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::streamLineParticle::streamLineParticle ( const polyMesh& mesh, const vector& position, const label celli, const label lifeTime ) : particle(mesh, position, celli), lifeTime_(lifeTime) {} Foam::streamLineParticle::streamLineParticle ( const polyMesh& mesh, Istream& is, bool readFields ) : particle(mesh, is, readFields) { if (readFields) { List sampledScalars; List sampledVectors; is >> lifeTime_ >> sampledPositions_ >> sampledScalars >> sampledVectors; sampledScalars_.setSize(sampledScalars.size()); forAll(sampledScalars, i) { sampledScalars_[i].transfer(sampledScalars[i]); } sampledVectors_.setSize(sampledVectors.size()); forAll(sampledVectors, i) { sampledVectors_[i].transfer(sampledVectors[i]); } } is.check(FUNCTION_NAME); } Foam::streamLineParticle::streamLineParticle ( const streamLineParticle& p ) : particle(p), lifeTime_(p.lifeTime_), sampledPositions_(p.sampledPositions_), sampledScalars_(p.sampledScalars_) {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // bool Foam::streamLineParticle::move ( trackingData& td, const scalar ) { td.switchProcessor = false; td.keepParticle = true; const scalar maxDt = mesh().bounds().mag(); while (td.keepParticle && !td.switchProcessor && lifeTime_ > 0) { scalar dt = maxDt; // Cross cell in steps: // - at subiter 0 calculate dt to cross cell in nSubCycle steps // - at the last subiter do all of the remaining track for (label subIter = 0; subIter < max(1, td.nSubCycle_); subIter++) { --lifeTime_; // Store current position and sampled velocity. sampledPositions_.append(position()); vector U = interpolateFields(td, position(), cell(), face()); if (!td.trackForward_) { U = -U; } scalar magU = mag(U); if (magU < SMALL) { // Stagnant particle. Might as well stop lifeTime_ = 0; break; } U /= magU; if (td.trackLength_ < GREAT) { // No sub-cycling. Track a set length on each step. dt = td.trackLength_; } else if (subIter == 0) { // Sub-cycling. Cross the cell in nSubCycle steps. particle copy(*this); copy.trackToFace(maxDt*U, 1); dt *= (copy.stepFraction() - stepFraction())/td.nSubCycle_; } else if (subIter == td.nSubCycle_ - 1) { // Sub-cycling. Track the whole cell on the last step. dt = maxDt; } trackToAndHitFace(dt*U, 0, td); if ( onFace() || !td.keepParticle || td.switchProcessor || lifeTime_ == 0 ) { break; } } } if (!td.keepParticle || lifeTime_ == 0) { if (lifeTime_ == 0) { // Failure exit. Particle stagnated or it's life ran out. if (debug) { Pout<< "streamLineParticle: Removing stagnant particle:" << position() << " sampled positions:" << sampledPositions_.size() << endl; } td.keepParticle = false; } else { // Normal exit. Store last position and fields sampledPositions_.append(position()); interpolateFields(td, position(), cell(), face()); if (debug) { Pout<< "streamLineParticle: Removing particle:" << position() << " sampled positions:" << sampledPositions_.size() << endl; } } // Transfer particle data into trackingData. td.allPositions_.append(vectorList()); vectorList& top = td.allPositions_.last(); top.transfer(sampledPositions_); forAll(sampledScalars_, i) { td.allScalars_[i].append(scalarList()); scalarList& top = td.allScalars_[i].last(); top.transfer(sampledScalars_[i]); } forAll(sampledVectors_, i) { td.allVectors_[i].append(vectorList()); vectorList& top = td.allVectors_[i].last(); top.transfer(sampledVectors_[i]); } } return td.keepParticle; } bool Foam::streamLineParticle::hitPatch ( const polyPatch&, trackingData& td, const label patchi, const scalar trackFraction, const tetIndices& tetIs ) { // Disable generic patch interaction return false; } void Foam::streamLineParticle::hitWedgePatch ( const wedgePolyPatch& pp, trackingData& td ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::hitSymmetryPlanePatch ( const symmetryPlanePolyPatch& pp, trackingData& td ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::hitSymmetryPatch ( const symmetryPolyPatch& pp, trackingData& td ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::hitCyclicPatch ( const cyclicPolyPatch& pp, trackingData& td ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::hitProcessorPatch ( const processorPolyPatch&, trackingData& td ) { // Switch particle td.switchProcessor = true; } void Foam::streamLineParticle::hitWallPatch ( const wallPolyPatch& wpp, trackingData& td, const tetIndices& ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::hitPatch ( const polyPatch& wpp, trackingData& td ) { // Remove particle td.keepParticle = false; } void Foam::streamLineParticle::readFields(Cloud& c) { if (!c.size()) { return; } particle::readFields(c); IOField