diff --git a/src/functionObjects/field/streamLine/streamLine.C b/src/functionObjects/field/streamLine/streamLine.C index c55b9289b1..e40df1b8bd 100644 --- a/src/functionObjects/field/streamLine/streamLine.C +++ b/src/functionObjects/field/streamLine/streamLine.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -244,6 +244,8 @@ void Foam::functionObjects::streamLine::track() // Size to maximum expected sizes. allTracks_.clear(); allTracks_.setCapacity(nSeeds); + allAges_.clear(); + allAges_.setCapacity(nSeeds); allScalars_.setSize(vsInterp.size()); forAll(allScalars_, i) { @@ -272,6 +274,7 @@ void Foam::functionObjects::streamLine::track() trackLength_, // fixed track length allTracks_, + allAges_, allScalars_, allVectors_ ); @@ -342,6 +345,8 @@ bool Foam::functionObjects::streamLine::read(const dictionary& dict) << exit(FatalIOError); } + writeAge_ = dict.lookupOrDefault("writeAge", true); + // The trackForward entry is maintained here for backwards compatibility if (!dict.found("direction") && dict.found("trackForward")) { @@ -498,9 +503,9 @@ bool Foam::functionObjects::streamLine::write() ); // Distribute the scalars - forAll(allScalars_, scalarI) + forAll(allScalars_, scalari) { - allScalars_[scalarI].shrink(); + allScalars_[scalari].shrink(); mapDistributeBase::distribute ( Pstream::commsTypes::scheduled, @@ -510,15 +515,15 @@ bool Foam::functionObjects::streamLine::write() false, distMap.constructMap(), false, - allScalars_[scalarI], + allScalars_[scalari], flipOp() ); - allScalars_[scalarI].setCapacity(allScalars_[scalarI].size()); + allScalars_[scalari].setCapacity(allScalars_[scalari].size()); } // Distribute the vectors - forAll(allVectors_, vectorI) + forAll(allVectors_, vectori) { - allVectors_[vectorI].shrink(); + allVectors_[vectori].shrink(); mapDistributeBase::distribute ( Pstream::commsTypes::scheduled, @@ -528,10 +533,10 @@ bool Foam::functionObjects::streamLine::write() false, distMap.constructMap(), false, - allVectors_[vectorI], + allVectors_[vectori], flipOp() ); - allVectors_[vectorI].setCapacity(allVectors_[vectorI].size()); + allVectors_[vectori].setCapacity(allVectors_[vectori].size()); } } @@ -587,21 +592,46 @@ bool Foam::functionObjects::streamLine::write() // Convert scalar values - if (allScalars_.size() > 0) + if (allScalars_.size() > 0 || writeAge_) { - List> scalarValues(allScalars_.size()); + List> ageAndScalarValues + ( + allScalars_.size() + writeAge_ + ); + wordList ageAndScalarNames(allScalars_.size() + writeAge_); - forAll(allScalars_, scalarI) + if (writeAge_) { - DynamicList& allTrackVals = - allScalars_[scalarI]; - scalarValues[scalarI].setSize(allTrackVals.size()); + DynamicList& allTrackAges = allAges_; + ageAndScalarValues[0].setSize(allTrackAges.size()); + forAll(allTrackAges, trackI) + { + ageAndScalarValues[0][trackI].transfer + ( + allTrackAges[trackI] + ); + } + + ageAndScalarNames[0] = "age"; + } + + forAll(allScalars_, scalari) + { + const label ageAndScalari = scalari + writeAge_; + + DynamicList& allTrackVals = allScalars_[scalari]; + + ageAndScalarValues[ageAndScalari].setSize(allTrackVals.size()); forAll(allTrackVals, trackI) { - scalarList& trackVals = allTrackVals[trackI]; - scalarValues[scalarI][trackI].transfer(trackVals); + ageAndScalarValues[ageAndScalari][trackI].transfer + ( + allTrackVals[trackI] + ); } + + ageAndScalarNames[ageAndScalari] = scalarNames_[scalari]; } fileName vtkFile @@ -610,7 +640,7 @@ bool Foam::functionObjects::streamLine::write() / scalarFormatterPtr_().getFileName ( tracks[0], - scalarNames_ + ageAndScalarNames ) ); @@ -620,8 +650,8 @@ bool Foam::functionObjects::streamLine::write() ( true, // writeTracks tracks, - scalarNames_, - scalarValues, + ageAndScalarNames, + ageAndScalarValues, OFstream(vtkFile)() ); } @@ -632,16 +662,17 @@ bool Foam::functionObjects::streamLine::write() { List> vectorValues(allVectors_.size()); - forAll(allVectors_, vectorI) + forAll(allVectors_, vectori) { - DynamicList& allTrackVals = - allVectors_[vectorI]; - vectorValues[vectorI].setSize(allTrackVals.size()); + DynamicList& allTrackVals = allVectors_[vectori]; + vectorValues[vectori].setSize(allTrackVals.size()); forAll(allTrackVals, trackI) { - vectorList& trackVals = allTrackVals[trackI]; - vectorValues[vectorI][trackI].transfer(trackVals); + vectorValues[vectori][trackI].transfer + ( + allTrackVals[trackI] + ); } } @@ -655,6 +686,8 @@ bool Foam::functionObjects::streamLine::write() ) ); + Info<< " Writing data to " << vtkFile.path() << endl; + vectorFormatterPtr_().write ( true, // writeTracks diff --git a/src/functionObjects/field/streamLine/streamLine.H b/src/functionObjects/field/streamLine/streamLine.H index 975f58f2ec..b9c52a70fd 100644 --- a/src/functionObjects/field/streamLine/streamLine.H +++ b/src/functionObjects/field/streamLine/streamLine.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -39,7 +39,7 @@ Description setFormat vtk; U U; - trackForward yes; + direction both; fields ( @@ -69,7 +69,9 @@ Usage type | Type name: streamLine | yes | setFormat | Output data type | yes | U | Tracking velocity field name | no | U + direction | Direction in which to track | yes | fields | Fields to sample | yes | + writeTime | Write the flow time along the streamline | no | no lifetime | Maximum number of particle tracking steps | yes | trackLength | Tracking segment length | no | nSubCycle | Number of tracking steps per cell | no| @@ -187,6 +189,9 @@ private: //- Names of vector fields wordList vectorNames_; + //- Write the streamline ages + Switch writeAge_; + // Demand driven @@ -211,6 +216,9 @@ private: //- All tracks. Per particle the points it passed through DynamicList> allTracks_; + //- All ages. Per particle the age when it passed through the points + DynamicList> allAges_; + //- Per scalarField, per particle, the sampled value. List> allScalars_; diff --git a/src/functionObjects/field/streamLine/streamLineParticle.C b/src/functionObjects/field/streamLine/streamLineParticle.C index eb463a1582..7dd0c2daba 100644 --- a/src/functionObjects/field/streamLine/streamLineParticle.C +++ b/src/functionObjects/field/streamLine/streamLineParticle.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -26,6 +26,7 @@ License #include "streamLineParticle.H" #include "streamLineParticleCloud.H" #include "vectorFieldIOField.H" +#include "scalarFieldIOField.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -88,7 +89,8 @@ Foam::streamLineParticle::streamLineParticle ) : particle(mesh, position, celli), - lifeTime_(lifeTime) + lifeTime_(lifeTime), + age_(0) {} @@ -106,8 +108,8 @@ Foam::streamLineParticle::streamLineParticle List sampledScalars; List sampledVectors; - is >> lifeTime_ >> sampledPositions_ >> sampledScalars - >> sampledVectors; + is >> lifeTime_ >> age_ >> sampledPositions_ >> sampledTimes_ + >> sampledScalars >> sampledVectors; sampledScalars_.setSize(sampledScalars.size()); forAll(sampledScalars, i) @@ -137,8 +139,11 @@ Foam::streamLineParticle::streamLineParticle : particle(p), lifeTime_(p.lifeTime_), + age_(p.age_), sampledPositions_(p.sampledPositions_), - sampledScalars_(p.sampledScalars_) + sampledTimes_(p.sampledTimes_), + sampledScalars_(p.sampledScalars_), + sampledVectors_(p.sampledVectors_) {} @@ -169,6 +174,7 @@ bool Foam::streamLineParticle::move // Store current position and sampled velocity. sampledPositions_.append(position()); + sampledTimes_.append(age_); vector U = interpolateFields(td, position(), cell(), face()); if (!td.trackForward_) @@ -205,7 +211,10 @@ bool Foam::streamLineParticle::move dt = maxDt; } - trackToAndHitFace(dt*U, 0, cloud, td); + age_ += + (td.trackForward_ ? +1 : -1) + *dt + *(1 - trackToAndHitFace(dt*U, 0, cloud, td)); if ( @@ -237,6 +246,7 @@ bool Foam::streamLineParticle::move { // Normal exit. Store last position and fields sampledPositions_.append(position()); + sampledTimes_.append(age_); interpolateFields(td, position(), cell(), face()); if (debug) @@ -248,10 +258,16 @@ bool Foam::streamLineParticle::move } // Transfer particle data into trackingData. - td.allPositions_.append(vectorList()); - vectorList& top = td.allPositions_.last(); - top.transfer(sampledPositions_); - + { + td.allPositions_.append(vectorList()); + vectorList& top = td.allPositions_.last(); + top.transfer(sampledPositions_); + } + { + td.allTimes_.append(scalarList()); + scalarList& top = td.allTimes_.last(); + top.transfer(sampledTimes_); + } forAll(sampledScalars_, i) { td.allScalars_[i].append(scalarList()); @@ -406,11 +422,19 @@ void Foam::streamLineParticle::readFields(Cloud& c) ); c.checkFieldIOobject(c, sampledPositions); + scalarFieldIOField sampledTimes + ( + c.fieldIOobject("sampledTimes", IOobject::MUST_READ), + valid + ); + c.checkFieldIOobject(c, sampledTimes); + label i = 0; forAllIter(Cloud, c, iter) { iter().lifeTime_ = lifeTime[i]; iter().sampledPositions_.transfer(sampledPositions[i]); + iter().sampledTimes_.transfer(sampledTimes[i]); i++; } } @@ -432,17 +456,24 @@ void Foam::streamLineParticle::writeFields(const Cloud& c) c.fieldIOobject("sampledPositions", IOobject::NO_READ), np ); + scalarFieldIOField sampledTimes + ( + c.fieldIOobject("sampledTimes", IOobject::NO_READ), + np + ); label i = 0; forAllConstIter(Cloud, c, iter) { lifeTime[i] = iter().lifeTime_; sampledPositions[i] = iter().sampledPositions_; + sampledTimes[i] = iter().sampledTimes_; i++; } lifeTime.write(np > 0); sampledPositions.write(np > 0); + sampledTimes.write(np > 0); } @@ -452,7 +483,9 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const streamLineParticle& p) { os << static_cast(p) << token::SPACE << p.lifeTime_ + << token::SPACE << p.age_ << token::SPACE << p.sampledPositions_ + << token::SPACE << p.sampledTimes_ << token::SPACE << p.sampledScalars_ << token::SPACE << p.sampledVectors_; diff --git a/src/functionObjects/field/streamLine/streamLineParticle.H b/src/functionObjects/field/streamLine/streamLineParticle.H index 0fc1b325e8..af6cf7ed32 100644 --- a/src/functionObjects/field/streamLine/streamLineParticle.H +++ b/src/functionObjects/field/streamLine/streamLineParticle.H @@ -86,6 +86,8 @@ public: DynamicList& allPositions_; + DynamicList& allTimes_; + List>& allScalars_; List>& allVectors_; @@ -104,6 +106,7 @@ public: const label nSubCycle, const scalar trackLength, DynamicList>& allPositions, + DynamicList>& allTimes, List>& allScalars, List>& allVectors ) @@ -116,6 +119,7 @@ public: nSubCycle_(nSubCycle), trackLength_(trackLength), allPositions_(allPositions), + allTimes_(allTimes), allScalars_(allScalars), allVectors_(allVectors) {} @@ -129,9 +133,15 @@ private: //- Lifetime of particle. Particle dies when reaches 0. label lifeTime_; + //- Age of the particle + scalar age_; + //- Sampled positions DynamicList sampledPositions_; + //- Sampled times + DynamicList sampledTimes_; + //- Sampled scalars List> sampledScalars_;