streamLines: Write out the streamline age

The streamLines function object now writes out "age" by default. This is
calculated as the total integration time from the starting point of the
streamline. This value can be negative if tracking is performed in the
reverse direction. Writing "age" can be deactivated by means of a
"writeAge no;" entry in the function object specification.
This commit is contained in:
Will Bainbridge
2018-07-20 16:16:50 +01:00
parent 4cd71d9d0d
commit aa4cb44b1e
4 changed files with 122 additions and 38 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -244,6 +244,8 @@ void Foam::functionObjects::streamLine::track()
// Size to maximum expected sizes. // Size to maximum expected sizes.
allTracks_.clear(); allTracks_.clear();
allTracks_.setCapacity(nSeeds); allTracks_.setCapacity(nSeeds);
allAges_.clear();
allAges_.setCapacity(nSeeds);
allScalars_.setSize(vsInterp.size()); allScalars_.setSize(vsInterp.size());
forAll(allScalars_, i) forAll(allScalars_, i)
{ {
@ -272,6 +274,7 @@ void Foam::functionObjects::streamLine::track()
trackLength_, // fixed track length trackLength_, // fixed track length
allTracks_, allTracks_,
allAges_,
allScalars_, allScalars_,
allVectors_ allVectors_
); );
@ -342,6 +345,8 @@ bool Foam::functionObjects::streamLine::read(const dictionary& dict)
<< exit(FatalIOError); << exit(FatalIOError);
} }
writeAge_ = dict.lookupOrDefault<Switch>("writeAge", true);
// The trackForward entry is maintained here for backwards compatibility // The trackForward entry is maintained here for backwards compatibility
if (!dict.found("direction") && dict.found("trackForward")) if (!dict.found("direction") && dict.found("trackForward"))
{ {
@ -498,9 +503,9 @@ bool Foam::functionObjects::streamLine::write()
); );
// Distribute the scalars // Distribute the scalars
forAll(allScalars_, scalarI) forAll(allScalars_, scalari)
{ {
allScalars_[scalarI].shrink(); allScalars_[scalari].shrink();
mapDistributeBase::distribute mapDistributeBase::distribute
( (
Pstream::commsTypes::scheduled, Pstream::commsTypes::scheduled,
@ -510,15 +515,15 @@ bool Foam::functionObjects::streamLine::write()
false, false,
distMap.constructMap(), distMap.constructMap(),
false, false,
allScalars_[scalarI], allScalars_[scalari],
flipOp() flipOp()
); );
allScalars_[scalarI].setCapacity(allScalars_[scalarI].size()); allScalars_[scalari].setCapacity(allScalars_[scalari].size());
} }
// Distribute the vectors // Distribute the vectors
forAll(allVectors_, vectorI) forAll(allVectors_, vectori)
{ {
allVectors_[vectorI].shrink(); allVectors_[vectori].shrink();
mapDistributeBase::distribute mapDistributeBase::distribute
( (
Pstream::commsTypes::scheduled, Pstream::commsTypes::scheduled,
@ -528,10 +533,10 @@ bool Foam::functionObjects::streamLine::write()
false, false,
distMap.constructMap(), distMap.constructMap(),
false, false,
allVectors_[vectorI], allVectors_[vectori],
flipOp() 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 // Convert scalar values
if (allScalars_.size() > 0) if (allScalars_.size() > 0 || writeAge_)
{ {
List<List<scalarField>> scalarValues(allScalars_.size()); List<List<scalarField>> ageAndScalarValues
(
allScalars_.size() + writeAge_
);
wordList ageAndScalarNames(allScalars_.size() + writeAge_);
forAll(allScalars_, scalarI) if (writeAge_)
{ {
DynamicList<scalarList>& allTrackVals = DynamicList<scalarList>& allTrackAges = allAges_;
allScalars_[scalarI];
scalarValues[scalarI].setSize(allTrackVals.size());
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<scalarList>& allTrackVals = allScalars_[scalari];
ageAndScalarValues[ageAndScalari].setSize(allTrackVals.size());
forAll(allTrackVals, trackI) forAll(allTrackVals, trackI)
{ {
scalarList& trackVals = allTrackVals[trackI]; ageAndScalarValues[ageAndScalari][trackI].transfer
scalarValues[scalarI][trackI].transfer(trackVals); (
allTrackVals[trackI]
);
} }
ageAndScalarNames[ageAndScalari] = scalarNames_[scalari];
} }
fileName vtkFile fileName vtkFile
@ -610,7 +640,7 @@ bool Foam::functionObjects::streamLine::write()
/ scalarFormatterPtr_().getFileName / scalarFormatterPtr_().getFileName
( (
tracks[0], tracks[0],
scalarNames_ ageAndScalarNames
) )
); );
@ -620,8 +650,8 @@ bool Foam::functionObjects::streamLine::write()
( (
true, // writeTracks true, // writeTracks
tracks, tracks,
scalarNames_, ageAndScalarNames,
scalarValues, ageAndScalarValues,
OFstream(vtkFile)() OFstream(vtkFile)()
); );
} }
@ -632,16 +662,17 @@ bool Foam::functionObjects::streamLine::write()
{ {
List<List<vectorField>> vectorValues(allVectors_.size()); List<List<vectorField>> vectorValues(allVectors_.size());
forAll(allVectors_, vectorI) forAll(allVectors_, vectori)
{ {
DynamicList<vectorList>& allTrackVals = DynamicList<vectorList>& allTrackVals = allVectors_[vectori];
allVectors_[vectorI];
vectorValues[vectorI].setSize(allTrackVals.size());
vectorValues[vectori].setSize(allTrackVals.size());
forAll(allTrackVals, trackI) forAll(allTrackVals, trackI)
{ {
vectorList& trackVals = allTrackVals[trackI]; vectorValues[vectori][trackI].transfer
vectorValues[vectorI][trackI].transfer(trackVals); (
allTrackVals[trackI]
);
} }
} }
@ -655,6 +686,8 @@ bool Foam::functionObjects::streamLine::write()
) )
); );
Info<< " Writing data to " << vtkFile.path() << endl;
vectorFormatterPtr_().write vectorFormatterPtr_().write
( (
true, // writeTracks true, // writeTracks

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -39,7 +39,7 @@ Description
setFormat vtk; setFormat vtk;
U U; U U;
trackForward yes; direction both;
fields fields
( (
@ -69,7 +69,9 @@ Usage
type | Type name: streamLine | yes | type | Type name: streamLine | yes |
setFormat | Output data type | yes | setFormat | Output data type | yes |
U | Tracking velocity field name | no | U U | Tracking velocity field name | no | U
direction | Direction in which to track | yes |
fields | Fields to sample | yes | fields | Fields to sample | yes |
writeTime | Write the flow time along the streamline | no | no
lifetime | Maximum number of particle tracking steps | yes | lifetime | Maximum number of particle tracking steps | yes |
trackLength | Tracking segment length | no | trackLength | Tracking segment length | no |
nSubCycle | Number of tracking steps per cell | no| nSubCycle | Number of tracking steps per cell | no|
@ -187,6 +189,9 @@ private:
//- Names of vector fields //- Names of vector fields
wordList vectorNames_; wordList vectorNames_;
//- Write the streamline ages
Switch writeAge_;
// Demand driven // Demand driven
@ -211,6 +216,9 @@ private:
//- All tracks. Per particle the points it passed through //- All tracks. Per particle the points it passed through
DynamicList<List<point>> allTracks_; DynamicList<List<point>> allTracks_;
//- All ages. Per particle the age when it passed through the points
DynamicList<List<scalar>> allAges_;
//- Per scalarField, per particle, the sampled value. //- Per scalarField, per particle, the sampled value.
List<DynamicList<scalarList>> allScalars_; List<DynamicList<scalarList>> allScalars_;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org \\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -26,6 +26,7 @@ License
#include "streamLineParticle.H" #include "streamLineParticle.H"
#include "streamLineParticleCloud.H" #include "streamLineParticleCloud.H"
#include "vectorFieldIOField.H" #include "vectorFieldIOField.H"
#include "scalarFieldIOField.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -88,7 +89,8 @@ Foam::streamLineParticle::streamLineParticle
) )
: :
particle(mesh, position, celli), particle(mesh, position, celli),
lifeTime_(lifeTime) lifeTime_(lifeTime),
age_(0)
{} {}
@ -106,8 +108,8 @@ Foam::streamLineParticle::streamLineParticle
List<scalarList> sampledScalars; List<scalarList> sampledScalars;
List<vectorList> sampledVectors; List<vectorList> sampledVectors;
is >> lifeTime_ >> sampledPositions_ >> sampledScalars is >> lifeTime_ >> age_ >> sampledPositions_ >> sampledTimes_
>> sampledVectors; >> sampledScalars >> sampledVectors;
sampledScalars_.setSize(sampledScalars.size()); sampledScalars_.setSize(sampledScalars.size());
forAll(sampledScalars, i) forAll(sampledScalars, i)
@ -137,8 +139,11 @@ Foam::streamLineParticle::streamLineParticle
: :
particle(p), particle(p),
lifeTime_(p.lifeTime_), lifeTime_(p.lifeTime_),
age_(p.age_),
sampledPositions_(p.sampledPositions_), 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. // Store current position and sampled velocity.
sampledPositions_.append(position()); sampledPositions_.append(position());
sampledTimes_.append(age_);
vector U = interpolateFields(td, position(), cell(), face()); vector U = interpolateFields(td, position(), cell(), face());
if (!td.trackForward_) if (!td.trackForward_)
@ -205,7 +211,10 @@ bool Foam::streamLineParticle::move
dt = maxDt; dt = maxDt;
} }
trackToAndHitFace(dt*U, 0, cloud, td); age_ +=
(td.trackForward_ ? +1 : -1)
*dt
*(1 - trackToAndHitFace(dt*U, 0, cloud, td));
if if
( (
@ -237,6 +246,7 @@ bool Foam::streamLineParticle::move
{ {
// Normal exit. Store last position and fields // Normal exit. Store last position and fields
sampledPositions_.append(position()); sampledPositions_.append(position());
sampledTimes_.append(age_);
interpolateFields(td, position(), cell(), face()); interpolateFields(td, position(), cell(), face());
if (debug) if (debug)
@ -248,10 +258,16 @@ bool Foam::streamLineParticle::move
} }
// Transfer particle data into trackingData. // Transfer particle data into trackingData.
td.allPositions_.append(vectorList()); {
vectorList& top = td.allPositions_.last(); td.allPositions_.append(vectorList());
top.transfer(sampledPositions_); vectorList& top = td.allPositions_.last();
top.transfer(sampledPositions_);
}
{
td.allTimes_.append(scalarList());
scalarList& top = td.allTimes_.last();
top.transfer(sampledTimes_);
}
forAll(sampledScalars_, i) forAll(sampledScalars_, i)
{ {
td.allScalars_[i].append(scalarList()); td.allScalars_[i].append(scalarList());
@ -406,11 +422,19 @@ void Foam::streamLineParticle::readFields(Cloud<streamLineParticle>& c)
); );
c.checkFieldIOobject(c, sampledPositions); c.checkFieldIOobject(c, sampledPositions);
scalarFieldIOField sampledTimes
(
c.fieldIOobject("sampledTimes", IOobject::MUST_READ),
valid
);
c.checkFieldIOobject(c, sampledTimes);
label i = 0; label i = 0;
forAllIter(Cloud<streamLineParticle>, c, iter) forAllIter(Cloud<streamLineParticle>, c, iter)
{ {
iter().lifeTime_ = lifeTime[i]; iter().lifeTime_ = lifeTime[i];
iter().sampledPositions_.transfer(sampledPositions[i]); iter().sampledPositions_.transfer(sampledPositions[i]);
iter().sampledTimes_.transfer(sampledTimes[i]);
i++; i++;
} }
} }
@ -432,17 +456,24 @@ void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
c.fieldIOobject("sampledPositions", IOobject::NO_READ), c.fieldIOobject("sampledPositions", IOobject::NO_READ),
np np
); );
scalarFieldIOField sampledTimes
(
c.fieldIOobject("sampledTimes", IOobject::NO_READ),
np
);
label i = 0; label i = 0;
forAllConstIter(Cloud<streamLineParticle>, c, iter) forAllConstIter(Cloud<streamLineParticle>, c, iter)
{ {
lifeTime[i] = iter().lifeTime_; lifeTime[i] = iter().lifeTime_;
sampledPositions[i] = iter().sampledPositions_; sampledPositions[i] = iter().sampledPositions_;
sampledTimes[i] = iter().sampledTimes_;
i++; i++;
} }
lifeTime.write(np > 0); lifeTime.write(np > 0);
sampledPositions.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<const particle&>(p) os << static_cast<const particle&>(p)
<< token::SPACE << p.lifeTime_ << token::SPACE << p.lifeTime_
<< token::SPACE << p.age_
<< token::SPACE << p.sampledPositions_ << token::SPACE << p.sampledPositions_
<< token::SPACE << p.sampledTimes_
<< token::SPACE << p.sampledScalars_ << token::SPACE << p.sampledScalars_
<< token::SPACE << p.sampledVectors_; << token::SPACE << p.sampledVectors_;

View File

@ -86,6 +86,8 @@ public:
DynamicList<vectorList>& allPositions_; DynamicList<vectorList>& allPositions_;
DynamicList<scalarList>& allTimes_;
List<DynamicList<scalarList>>& allScalars_; List<DynamicList<scalarList>>& allScalars_;
List<DynamicList<vectorList>>& allVectors_; List<DynamicList<vectorList>>& allVectors_;
@ -104,6 +106,7 @@ public:
const label nSubCycle, const label nSubCycle,
const scalar trackLength, const scalar trackLength,
DynamicList<List<point>>& allPositions, DynamicList<List<point>>& allPositions,
DynamicList<List<scalar>>& allTimes,
List<DynamicList<scalarList>>& allScalars, List<DynamicList<scalarList>>& allScalars,
List<DynamicList<vectorList>>& allVectors List<DynamicList<vectorList>>& allVectors
) )
@ -116,6 +119,7 @@ public:
nSubCycle_(nSubCycle), nSubCycle_(nSubCycle),
trackLength_(trackLength), trackLength_(trackLength),
allPositions_(allPositions), allPositions_(allPositions),
allTimes_(allTimes),
allScalars_(allScalars), allScalars_(allScalars),
allVectors_(allVectors) allVectors_(allVectors)
{} {}
@ -129,9 +133,15 @@ private:
//- Lifetime of particle. Particle dies when reaches 0. //- Lifetime of particle. Particle dies when reaches 0.
label lifeTime_; label lifeTime_;
//- Age of the particle
scalar age_;
//- Sampled positions //- Sampled positions
DynamicList<point> sampledPositions_; DynamicList<point> sampledPositions_;
//- Sampled times
DynamicList<scalar> sampledTimes_;
//- Sampled scalars //- Sampled scalars
List<DynamicList<scalar>> sampledScalars_; List<DynamicList<scalar>> sampledScalars_;