1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*----------------------------------------------------------------------------*/
26 #include "streamLineParticle.H"
27 #include "vectorFieldIOField.H"
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 // defineParticleTypeNameAndDebug(streamLineParticle, 0);
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 Foam::scalar Foam::streamLineParticle::calcSubCycleDeltaT
46 streamLineParticle testParticle(*this);
48 bool oldKeepParticle = td.keepParticle;
49 bool oldSwitchProcessor = td.switchProcessor;
50 scalar fraction = testParticle.trackToFace(position()+dt*U, td);
51 td.keepParticle = oldKeepParticle;
52 td.switchProcessor = oldSwitchProcessor;
53 // Adapt the dt to subdivide the trajectory into substeps.
54 return dt*fraction/td.nSubCycle_;
58 Foam::vector Foam::streamLineParticle::interpolateFields
60 const trackingData& td,
61 const point& position,
67 FatalErrorIn("streamLineParticle::interpolateFields(..)")
68 << "Cell:" << cellI << abort(FatalError);
71 sampledScalars_.setSize(td.vsInterp_.size());
72 forAll(td.vsInterp_, scalarI)
74 sampledScalars_[scalarI].append
76 td.vsInterp_[scalarI].interpolate
84 sampledVectors_.setSize(td.vvInterp_.size());
85 forAll(td.vvInterp_, vectorI)
87 sampledVectors_[vectorI].append
89 td.vvInterp_[vectorI].interpolate
97 const DynamicList<vector>& U = sampledVectors_[td.UIndex_];
103 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105 Foam::streamLineParticle::streamLineParticle
107 const polyMesh& mesh,
108 const vector& position,
113 particle(mesh, position, cellI),
118 Foam::streamLineParticle::streamLineParticle
120 const polyMesh& mesh,
125 particle(mesh, is, readFields)
129 //if (is.format() == IOstream::ASCII)
130 List<scalarList> sampledScalars;
131 List<vectorList> sampledVectors;
133 is >> lifeTime_ >> sampledPositions_ >> sampledScalars
136 sampledScalars_.setSize(sampledScalars.size());
137 forAll(sampledScalars, i)
139 sampledScalars_[i].transfer(sampledScalars[i]);
141 sampledVectors_.setSize(sampledVectors.size());
142 forAll(sampledVectors, i)
144 sampledVectors_[i].transfer(sampledVectors[i]);
148 // Check state of Istream
151 "streamLineParticle::streamLineParticle"
152 "(const Cloud<streamLineParticle>&, Istream&, bool)"
157 Foam::streamLineParticle::streamLineParticle
159 const streamLineParticle& p
163 lifeTime_(p.lifeTime_),
164 sampledPositions_(p.sampledPositions_),
165 sampledScalars_(p.sampledScalars_)
169 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
171 bool Foam::streamLineParticle::move
174 const scalar trackTime
177 streamLineParticle& p = static_cast<streamLineParticle&>(*this);
179 td.switchProcessor = false;
180 td.keepParticle = true;
182 scalar tEnd = (1.0 - stepFraction())*trackTime;
183 scalar maxDt = mesh_.bounds().mag();
188 && !td.switchProcessor
192 // set the lagrangian time-step
195 // Cross cell in steps:
196 // - at subiter 0 calculate dt to cross cell in nSubCycle steps
197 // - at the last subiter do all of the remaining track
198 for (label subIter = 0; subIter < td.nSubCycle_; subIter++)
202 // Store current position and sampled velocity.
203 sampledPositions_.append(position());
204 vector U = interpolateFields(td, position(), cell());
206 if (!td.trackForward_)
211 scalar magU = mag(U);
215 // Stagnant particle. Might as well stop
222 if (subIter == 0 && td.nSubCycle_ > 1)
224 // Adapt dt to cross cell in a few steps
225 dt = calcSubCycleDeltaT(td, dt, U);
227 else if (subIter == td.nSubCycle_ - 1)
229 // Do full step on last subcycle
234 scalar fraction = trackToFace(position() + dt*U, td);
238 stepFraction() = 1.0 - tEnd/trackTime;
240 if (tEnd <= ROOTVSMALL)
250 || td.switchProcessor
260 if (!td.keepParticle || lifeTime_ == 0)
266 Pout<< "streamLineParticle : Removing stagnant particle:"
267 << p << " sampled positions:" << sampledPositions_.size()
270 td.keepParticle = false;
274 // Normal exit. Store last position and fields
275 sampledPositions_.append(position());
276 interpolateFields(td, position(), cell());
280 Pout<< "streamLineParticle : Removing particle:"
281 << p << " sampled positions:" << sampledPositions_.size()
286 // Transfer particle data into trackingData.
287 //td.allPositions_.append(sampledPositions_);
288 td.allPositions_.append(vectorList());
289 vectorList& top = td.allPositions_.last();
290 top.transfer(sampledPositions_);
292 forAll(sampledScalars_, i)
294 //td.allScalars_[i].append(sampledScalars_[i]);
295 td.allScalars_[i].append(scalarList());
296 scalarList& top = td.allScalars_[i].last();
297 top.transfer(sampledScalars_[i]);
299 forAll(sampledVectors_, i)
301 //td.allVectors_[i].append(sampledVectors_[i]);
302 td.allVectors_[i].append(vectorList());
303 vectorList& top = td.allVectors_[i].last();
304 top.transfer(sampledVectors_[i]);
308 return td.keepParticle;
312 bool Foam::streamLineParticle::hitPatch
317 const scalar trackFraction,
318 const tetIndices& tetIs
321 // Disable generic patch interaction
326 void Foam::streamLineParticle::hitWedgePatch
328 const wedgePolyPatch& pp,
333 td.keepParticle = false;
337 void Foam::streamLineParticle::hitSymmetryPatch
339 const symmetryPolyPatch& pp,
344 td.keepParticle = false;
348 void Foam::streamLineParticle::hitCyclicPatch
350 const cyclicPolyPatch& pp,
355 td.keepParticle = false;
359 void Foam::streamLineParticle::hitProcessorPatch
361 const processorPolyPatch&,
366 td.switchProcessor = true;
370 void Foam::streamLineParticle::hitWallPatch
372 const wallPolyPatch& wpp,
378 td.keepParticle = false;
382 void Foam::streamLineParticle::hitPatch
384 const polyPatch& wpp,
389 td.keepParticle = false;
393 void Foam::streamLineParticle::readFields(Cloud<streamLineParticle>& c)
400 particle::readFields(c);
402 IOField<label> lifeTime
404 c.fieldIOobject("lifeTime", IOobject::MUST_READ)
406 c.checkFieldIOobject(c, lifeTime);
408 vectorFieldIOField sampledPositions
410 c.fieldIOobject("sampledPositions", IOobject::MUST_READ)
412 c.checkFieldIOobject(c, sampledPositions);
414 // vectorFieldIOField sampleVelocity
416 // c.fieldIOobject("sampleVelocity", IOobject::MUST_READ)
418 // c.checkFieldIOobject(c, sampleVelocity);
421 forAllIter(Cloud<streamLineParticle>, c, iter)
423 iter().lifeTime_ = lifeTime[i];
424 iter().sampledPositions_.transfer(sampledPositions[i]);
425 // iter().sampleVelocity_.transfer(sampleVelocity[i]);
431 void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
433 particle::writeFields(c);
437 IOField<label> lifeTime
439 c.fieldIOobject("lifeTime", IOobject::NO_READ),
442 vectorFieldIOField sampledPositions
444 c.fieldIOobject("sampledPositions", IOobject::NO_READ),
447 // vectorFieldIOField sampleVelocity
449 // c.fieldIOobject("sampleVelocity", IOobject::NO_READ),
454 forAllConstIter(Cloud<streamLineParticle>, c, iter)
456 lifeTime[i] = iter().lifeTime_;
457 sampledPositions[i] = iter().sampledPositions_;
458 // sampleVelocity[i] = iter().sampleVelocity_;
463 sampledPositions.write();
464 // sampleVelocity.write();
468 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
470 Foam::Ostream& Foam::operator<<(Ostream& os, const streamLineParticle& p)
472 os << static_cast<const particle&>(p)
473 << token::SPACE << p.lifeTime_
474 << token::SPACE << p.sampledPositions_
475 << token::SPACE << p.sampledScalars_
476 << token::SPACE << p.sampledVectors_;
478 // Check state of Ostream
479 os.check("Ostream& operator<<(Ostream&, const streamLineParticle&)");
485 // ************************************************************************* //