Merge branch 'master' of github.com-OpenFOAM:OpenFOAM/OpenFOAM-dev

This commit is contained in:
Henry Weller
2021-11-24 14:54:11 +00:00
5 changed files with 181 additions and 73 deletions

View File

@ -270,6 +270,7 @@ void Foam::functionObjects::streamlines::track()
UIndex, // index of U in vvInterp
trackDirection_ == trackDirection::forward,
trackOutside_,
nSubCycle_, // automatic track control:step through cells in steps?
trackLength_, // fixed track length
@ -361,6 +362,8 @@ bool Foam::functionObjects::streamlines::read(const dictionary& dict)
trackDirection_ = trackDirectionNames_[word(dict.lookup("direction"))];
}
trackOutside_ = dict.lookupOrDefault<Switch>("outside", false);
dict.lookup("lifeTime") >> lifeTime_;
if (lifeTime_ < 1)
{

View File

@ -70,6 +70,7 @@ Usage
setFormat | Output data type | yes |
U | Tracking velocity field name | no | U
direction | Direction in which to track | yes |
outside | Track outside of periodic meshes | no | no
fields | Fields to sample | yes |
writeTime | Write the flow time along the streamlines | no | no
lifetime | Maximum number of particle tracking steps | yes |
@ -167,6 +168,9 @@ private:
//- The direction in which to track
trackDirection trackDirection_;
//- Whether or not to track outside of the mesh in periodic geometries
Switch trackOutside_;
//- Maximum lifetime (= number of cells) of particle
label lifeTime_;

View File

@ -28,6 +28,21 @@ License
#include "vectorFieldIOField.H"
#include "scalarFieldIOField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef IOList<transformer> transformerIOList;
defineTemplateTypeNameAndDebugWithName
(
transformerIOList,
"transformerList",
0
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::vector Foam::streamlinesParticle::interpolateFields
@ -47,34 +62,65 @@ Foam::vector Foam::streamlinesParticle::interpolateFields
sampledScalars_.setSize(td.vsInterp_.size());
forAll(td.vsInterp_, scalarI)
{
const scalar s =
td.vsInterp_[scalarI].interpolate(position, celli, facei);
sampledScalars_[scalarI].append
(
td.vsInterp_[scalarI].interpolate
(
position,
celli,
facei
)
td.trackOutside_ ? transform_.invTransform(s) : s
);
}
vector U = vector::uniform(NaN);
sampledVectors_.setSize(td.vvInterp_.size());
forAll(td.vvInterp_, vectorI)
{
const vector v =
td.vvInterp_[vectorI].interpolate(position, celli, facei);
if (vectorI == td.UIndex_)
{
U = v;
}
sampledVectors_[vectorI].append
(
td.vvInterp_[vectorI].interpolate
(
position,
celli,
facei
)
td.trackOutside_ ? transform_.invTransform(v) : v
);
}
const DynamicList<vector>& U = sampledVectors_[td.UIndex_];
return U;
}
return U.last();
void Foam::streamlinesParticle::endTrack(trackingData& td)
{
{
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());
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]);
}
}
@ -90,6 +136,7 @@ Foam::streamlinesParticle::streamlinesParticle
:
particle(mesh, position, celli),
lifeTime_(lifeTime),
transform_(transformer::I),
age_(0)
{}
@ -108,8 +155,8 @@ Foam::streamlinesParticle::streamlinesParticle
List<scalarList> sampledScalars;
List<vectorList> sampledVectors;
is >> lifeTime_ >> age_ >> sampledPositions_ >> sampledTimes_
>> sampledScalars >> sampledVectors;
is >> lifeTime_ >> transform_ >> age_ >> sampledPositions_
>> sampledTimes_ >> sampledScalars >> sampledVectors;
sampledScalars_.setSize(sampledScalars.size());
forAll(sampledScalars, i)
@ -139,6 +186,7 @@ Foam::streamlinesParticle::streamlinesParticle
:
particle(p),
lifeTime_(p.lifeTime_),
transform_(p.transform_),
age_(p.age_),
sampledPositions_(p.sampledPositions_),
sampledTimes_(p.sampledTimes_),
@ -173,7 +221,12 @@ bool Foam::streamlinesParticle::move
--lifeTime_;
// Store current position and sampled velocity.
sampledPositions_.append(position());
sampledPositions_.append
(
td.trackOutside_
? transform_.invTransformPosition(position())
: position()
);
sampledTimes_.append(age_);
vector U = interpolateFields(td, position(), cell(), face());
@ -216,13 +269,7 @@ bool Foam::streamlinesParticle::move
*dt
*(1 - trackToAndHitFace(dt*U, 0, cloud, td));
if
(
onFace()
|| !td.keepParticle
|| td.switchProcessor
|| lifeTime_ == 0
)
if (!td.keepParticle || td.switchProcessor || lifeTime_ == 0)
{
break;
}
@ -245,7 +292,12 @@ bool Foam::streamlinesParticle::move
else
{
// Normal exit. Store last position and fields
sampledPositions_.append(position());
sampledPositions_.append
(
td.trackOutside_
? transform_.invTransformPosition(position())
: position()
);
sampledTimes_.append(age_);
interpolateFields(td, position(), cell(), face());
@ -257,29 +309,8 @@ bool Foam::streamlinesParticle::move
}
}
// Transfer particle data into trackingData.
{
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());
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]);
}
// End this track
endTrack(td);
}
return td.keepParticle;
@ -328,51 +359,69 @@ void Foam::streamlinesParticle::hitSymmetryPatch
void Foam::streamlinesParticle::hitCyclicPatch
(
streamlinesCloud&,
streamlinesCloud& cloud,
trackingData& td
)
{
// Remove particle
td.keepParticle = false;
const cyclicPolyPatch& cpp =
static_cast<const cyclicPolyPatch&>(mesh().boundaryMesh()[patch()]);
// End this track
if (!td.trackOutside_ && cpp.transform().transformsPosition())
{
endTrack(td);
}
// Move across the cyclic
particle::hitCyclicPatch(cloud, td);
}
void Foam::streamlinesParticle::hitCyclicAMIPatch
(
const vector&,
const scalar,
streamlinesCloud&,
const vector& displacement,
const scalar fraction,
streamlinesCloud& cloud,
trackingData& td
)
{
// Remove particle
td.keepParticle = false;
// End this track
endTrack(td);
// Move across the cyclic
particle::hitCyclicAMIPatch(displacement, fraction, cloud, td);
}
void Foam::streamlinesParticle::hitCyclicACMIPatch
(
const vector&,
const scalar,
streamlinesCloud&,
const vector& displacement,
const scalar fraction,
streamlinesCloud& cloud,
trackingData& td
)
{
// Remove particle
td.keepParticle = false;
// End this track
endTrack(td);
// Move across the cyclic
particle::hitCyclicACMIPatch(displacement, fraction, cloud, td);
}
void Foam::streamlinesParticle::hitCyclicRepeatAMIPatch
(
const vector&,
const scalar,
streamlinesCloud&,
const vector& displacement,
const scalar fraction,
streamlinesCloud& cloud,
trackingData& td
)
{
// Remove particle
td.keepParticle = false;
// End this track
endTrack(td);
// Move across the cyclic
particle::hitCyclicRepeatAMIPatch(displacement, fraction, cloud, td);
}
@ -382,7 +431,16 @@ void Foam::streamlinesParticle::hitProcessorPatch
trackingData& td
)
{
// Switch particle
const processorPolyPatch& ppp =
static_cast<const processorPolyPatch&>(mesh().boundaryMesh()[patch()]);
// End this track
if (!td.trackOutside_ && ppp.transform().transformsPosition())
{
endTrack(td);
}
// Switch processor
td.switchProcessor = true;
}
@ -398,12 +456,17 @@ void Foam::streamlinesParticle::hitWallPatch
}
void Foam::streamlinesParticle::transformProperties
(
const transformer& transform
)
{
transform_ = transform & transform_;
}
void Foam::streamlinesParticle::readFields(Cloud<streamlinesParticle>& c)
{
// if (!c.size())
// {
// return;
// }
bool valid = c.size();
particle::readFields(c);
@ -415,6 +478,12 @@ void Foam::streamlinesParticle::readFields(Cloud<streamlinesParticle>& c)
);
c.checkFieldIOobject(c, lifeTime);
transformerIOList transform
(
c.fieldIOobject("transform", IOobject::MUST_READ),
valid
);
vectorFieldIOField sampledPositions
(
c.fieldIOobject("sampledPositions", IOobject::MUST_READ),
@ -433,6 +502,7 @@ void Foam::streamlinesParticle::readFields(Cloud<streamlinesParticle>& c)
forAllIter(Cloud<streamlinesParticle>, c, iter)
{
iter().lifeTime_ = lifeTime[i];
iter().transform_ = transform[i];
iter().sampledPositions_.transfer(sampledPositions[i]);
iter().sampledTimes_.transfer(sampledTimes[i]);
i++;
@ -451,11 +521,19 @@ void Foam::streamlinesParticle::writeFields(const Cloud<streamlinesParticle>& c)
c.fieldIOobject("lifeTime", IOobject::NO_READ),
np
);
transformerIOList transform
(
c.fieldIOobject("transform", IOobject::NO_READ),
np
);
vectorFieldIOField sampledPositions
(
c.fieldIOobject("sampledPositions", IOobject::NO_READ),
np
);
scalarFieldIOField sampledTimes
(
c.fieldIOobject("sampledTimes", IOobject::NO_READ),
@ -466,6 +544,7 @@ void Foam::streamlinesParticle::writeFields(const Cloud<streamlinesParticle>& c)
forAllConstIter(Cloud<streamlinesParticle>, c, iter)
{
lifeTime[i] = iter().lifeTime_;
transform[i] = iter().transform_;
sampledPositions[i] = iter().sampledPositions_;
sampledTimes[i] = iter().sampledTimes_;
i++;
@ -483,6 +562,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const streamlinesParticle& p)
{
os << static_cast<const particle&>(p)
<< token::SPACE << p.lifeTime_
<< token::SPACE << p.transform_
<< token::SPACE << p.age_
<< token::SPACE << p.sampledPositions_
<< token::SPACE << p.sampledTimes_

View File

@ -80,6 +80,8 @@ public:
bool trackForward_;
bool trackOutside_;
const label nSubCycle_;
const scalar trackLength_;
@ -103,6 +105,7 @@ public:
const PtrList<interpolation<vector>>& vvInterp,
const label UIndex,
const bool trackForward,
const bool trackOutside,
const label nSubCycle,
const scalar trackLength,
DynamicList<List<point>>& allPositions,
@ -116,6 +119,7 @@ public:
vvInterp_(vvInterp),
UIndex_(UIndex),
trackForward_(trackForward),
trackOutside_(trackOutside),
nSubCycle_(nSubCycle),
trackLength_(trackLength),
allPositions_(allPositions),
@ -133,6 +137,9 @@ private:
//- Lifetime of particle. Particle dies when reaches 0.
label lifeTime_;
//- Current compound transform
transformer transform_;
//- Age of the particle
scalar age_;
@ -160,6 +167,9 @@ private:
const label facei
);
//- End the current track
void endTrack(trackingData&);
public:
@ -276,6 +286,13 @@ public:
void hitWallPatch(streamlinesCloud&, trackingData&);
// Transformations
//- Transform the physical properties of the particle
// according to the given transformation tensor
virtual void transformProperties(const transformer&);
// I-O
//- Read

View File

@ -412,6 +412,8 @@ void Foam::particle::hitCyclicACMIPatch
{
typename TrackCloudType::particleType& p =
static_cast<typename TrackCloudType::particleType&>(*this);
typename TrackCloudType::particleType::trackingData& ttd =
static_cast<typename TrackCloudType::particleType::trackingData&>(td);
const cyclicACMIPolyPatch& cpp =
static_cast<const cyclicACMIPolyPatch&>(mesh_.boundaryMesh()[patch()]);
@ -445,7 +447,7 @@ void Foam::particle::hitCyclicACMIPatch
if (couple)
{
p.hitCyclicAMIPatch(displacement, fraction, cloud, td);
p.hitCyclicAMIPatch(displacement, fraction, cloud, ttd);
}
else
{
@ -468,8 +470,10 @@ void Foam::particle::hitCyclicRepeatAMIPatch
{
typename TrackCloudType::particleType& p =
static_cast<typename TrackCloudType::particleType&>(*this);
typename TrackCloudType::particleType::trackingData& ttd =
static_cast<typename TrackCloudType::particleType::trackingData&>(td);
p.hitCyclicAMIPatch(displacement, fraction, cloud, td);
p.hitCyclicAMIPatch(displacement, fraction, cloud, ttd);
}