mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
GIT: Initial state after latest Foundation merge
This commit is contained in:
677
src/functionObjects/field/streamLine/streamLine.C
Normal file
677
src/functionObjects/field/streamLine/streamLine.C
Normal file
@ -0,0 +1,677 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "Pstream.H"
|
||||
#include "functionObjectList.H"
|
||||
#include "streamLine.H"
|
||||
#include "streamLineParticleCloud.H"
|
||||
#include "ReadFields.H"
|
||||
#include "meshSearch.H"
|
||||
#include "sampledSet.H"
|
||||
#include "globalIndex.H"
|
||||
#include "mapDistribute.H"
|
||||
#include "interpolationCellPoint.H"
|
||||
#include "PatchTools.H"
|
||||
#include "mapPolyMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
defineTypeNameAndDebug(streamLine, 0);
|
||||
addToRunTimeSelectionTable(functionObject, streamLine, dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::indirectPrimitivePatch>
|
||||
Foam::functionObjects::streamLine::wallPatch() const
|
||||
{
|
||||
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||
|
||||
label nFaces = 0;
|
||||
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
if (isA<wallPolyPatch>(patches[patchi]))
|
||||
{
|
||||
nFaces += patches[patchi].size();
|
||||
}
|
||||
}
|
||||
|
||||
labelList addressing(nFaces);
|
||||
|
||||
nFaces = 0;
|
||||
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
if (isA<wallPolyPatch>(patches[patchi]))
|
||||
{
|
||||
const polyPatch& pp = patches[patchi];
|
||||
|
||||
forAll(pp, i)
|
||||
{
|
||||
addressing[nFaces++] = pp.start()+i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return autoPtr<indirectPrimitivePatch>
|
||||
(
|
||||
new indirectPrimitivePatch
|
||||
(
|
||||
IndirectList<face>
|
||||
(
|
||||
mesh_.faces(),
|
||||
addressing
|
||||
),
|
||||
mesh_.points()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::streamLine::track()
|
||||
{
|
||||
IDLList<streamLineParticle> initialParticles;
|
||||
streamLineParticleCloud particles
|
||||
(
|
||||
mesh_,
|
||||
cloudName_,
|
||||
initialParticles
|
||||
);
|
||||
|
||||
const sampledSet& seedPoints = sampledSetPtr_();
|
||||
|
||||
forAll(seedPoints, i)
|
||||
{
|
||||
particles.addParticle
|
||||
(
|
||||
new streamLineParticle
|
||||
(
|
||||
mesh_,
|
||||
seedPoints[i],
|
||||
seedPoints.cells()[i],
|
||||
lifeTime_
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
label nSeeds = returnReduce(particles.size(), sumOp<label>());
|
||||
|
||||
Info << " seeded " << nSeeds << " particles" << endl;
|
||||
|
||||
// Read or lookup fields
|
||||
PtrList<volScalarField> vsFlds;
|
||||
PtrList<interpolation<scalar>> vsInterp;
|
||||
PtrList<volVectorField> vvFlds;
|
||||
PtrList<interpolation<vector>> vvInterp;
|
||||
|
||||
label UIndex = -1;
|
||||
|
||||
label nScalar = 0;
|
||||
label nVector = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
{
|
||||
if (mesh_.foundObject<volScalarField>(fields_[i]))
|
||||
{
|
||||
nScalar++;
|
||||
}
|
||||
else if (mesh_.foundObject<volVectorField>(fields_[i]))
|
||||
{
|
||||
nVector++;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find field " << fields_[i] << nl
|
||||
<< "Valid scalar fields are:"
|
||||
<< mesh_.names(volScalarField::typeName) << nl
|
||||
<< "Valid vector fields are:"
|
||||
<< mesh_.names(volVectorField::typeName)
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
vsInterp.setSize(nScalar);
|
||||
nScalar = 0;
|
||||
vvInterp.setSize(nVector);
|
||||
nVector = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
{
|
||||
if (mesh_.foundObject<volScalarField>(fields_[i]))
|
||||
{
|
||||
const volScalarField& f = mesh_.lookupObject<volScalarField>
|
||||
(
|
||||
fields_[i]
|
||||
);
|
||||
vsInterp.set
|
||||
(
|
||||
nScalar++,
|
||||
interpolation<scalar>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
f
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (mesh_.foundObject<volVectorField>(fields_[i]))
|
||||
{
|
||||
const volVectorField& f = mesh_.lookupObject<volVectorField>
|
||||
(
|
||||
fields_[i]
|
||||
);
|
||||
|
||||
if (f.name() == UName_)
|
||||
{
|
||||
UIndex = nVector;
|
||||
}
|
||||
|
||||
vvInterp.set
|
||||
(
|
||||
nVector++,
|
||||
interpolation<vector>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
f
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Store the names
|
||||
scalarNames_.setSize(vsInterp.size());
|
||||
forAll(vsInterp, i)
|
||||
{
|
||||
scalarNames_[i] = vsInterp[i].psi().name();
|
||||
}
|
||||
vectorNames_.setSize(vvInterp.size());
|
||||
forAll(vvInterp, i)
|
||||
{
|
||||
vectorNames_[i] = vvInterp[i].psi().name();
|
||||
}
|
||||
|
||||
// Check that we know the index of U in the interpolators.
|
||||
|
||||
if (UIndex == -1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find field to move particles with : " << UName_ << nl
|
||||
<< "This field has to be present in the sampled fields " << fields_
|
||||
<< " and in the objectRegistry."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Sampled data
|
||||
// ~~~~~~~~~~~~
|
||||
|
||||
// Size to maximum expected sizes.
|
||||
allTracks_.clear();
|
||||
allTracks_.setCapacity(nSeeds);
|
||||
allScalars_.setSize(vsInterp.size());
|
||||
forAll(allScalars_, i)
|
||||
{
|
||||
allScalars_[i].clear();
|
||||
allScalars_[i].setCapacity(nSeeds);
|
||||
}
|
||||
allVectors_.setSize(vvInterp.size());
|
||||
forAll(allVectors_, i)
|
||||
{
|
||||
allVectors_[i].clear();
|
||||
allVectors_[i].setCapacity(nSeeds);
|
||||
}
|
||||
|
||||
|
||||
// Additional particle info
|
||||
streamLineParticle::trackingData td
|
||||
(
|
||||
particles,
|
||||
vsInterp,
|
||||
vvInterp,
|
||||
UIndex, // index of U in vvInterp
|
||||
trackForward_, // track in +u direction?
|
||||
nSubCycle_, // automatic track control:step through cells in steps?
|
||||
trackLength_, // fixed track length
|
||||
|
||||
allTracks_,
|
||||
allScalars_,
|
||||
allVectors_
|
||||
);
|
||||
|
||||
|
||||
// Set very large dt. Note: cannot use GREAT since 1/GREAT is SMALL
|
||||
// which is a trigger value for the tracking...
|
||||
const scalar trackTime = Foam::sqrt(GREAT);
|
||||
|
||||
// Track
|
||||
particles.move(td, trackTime);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::streamLine::streamLine
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
dict_(dict),
|
||||
nSubCycle_(0)
|
||||
{
|
||||
read(dict_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::streamLine::~streamLine()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::streamLine::read(const dictionary& dict)
|
||||
{
|
||||
if (dict != dict_)
|
||||
{
|
||||
dict_ = dict;
|
||||
}
|
||||
|
||||
Info<< type() << " " << name() << ":" << nl;
|
||||
|
||||
dict.lookup("fields") >> fields_;
|
||||
if (dict.found("U"))
|
||||
{
|
||||
dict.lookup("U") >> UName_;
|
||||
}
|
||||
else
|
||||
{
|
||||
UName_ = "U";
|
||||
if (dict.found("U"))
|
||||
{
|
||||
IOWarningInFunction(dict)
|
||||
<< "Using deprecated entry \"U\"."
|
||||
<< " Please use \"UName\" instead."
|
||||
<< endl;
|
||||
dict.lookup("U") >> UName_;
|
||||
}
|
||||
}
|
||||
|
||||
if (findIndex(fields_, UName_) == -1)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Velocity field for tracking " << UName_
|
||||
<< " should be present in the list of fields " << fields_
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
|
||||
dict.lookup("trackForward") >> trackForward_;
|
||||
dict.lookup("lifeTime") >> lifeTime_;
|
||||
if (lifeTime_ < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal value " << lifeTime_ << " for lifeTime"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
bool subCycling = dict.found("nSubCycle");
|
||||
bool fixedLength = dict.found("trackLength");
|
||||
|
||||
if (subCycling && fixedLength)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Cannot both specify automatic time stepping (through '"
|
||||
<< "nSubCycle' specification) and fixed track length (through '"
|
||||
<< "trackLength')"
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
|
||||
nSubCycle_ = 1;
|
||||
if (dict.readIfPresent("nSubCycle", nSubCycle_))
|
||||
{
|
||||
trackLength_ = VGREAT;
|
||||
if (nSubCycle_ < 1)
|
||||
{
|
||||
nSubCycle_ = 1;
|
||||
}
|
||||
Info<< " automatic track length specified through"
|
||||
<< " number of sub cycles : " << nSubCycle_ << nl << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
dict.lookup("trackLength") >> trackLength_;
|
||||
|
||||
Info<< " fixed track length specified : "
|
||||
<< trackLength_ << nl << endl;
|
||||
}
|
||||
|
||||
|
||||
interpolationScheme_ = dict.lookupOrDefault
|
||||
(
|
||||
"interpolationScheme",
|
||||
interpolationCellPoint<scalar>::typeName
|
||||
);
|
||||
|
||||
cloudName_ = dict.lookupOrDefault<word>("cloudName", "streamLine");
|
||||
dict.lookup("seedSampleSet") >> seedSet_;
|
||||
|
||||
meshSearchPtr_.reset(new meshSearch(mesh_));
|
||||
|
||||
const dictionary& coeffsDict = dict.subDict(seedSet_ + "Coeffs");
|
||||
sampledSetPtr_ = sampledSet::New
|
||||
(
|
||||
seedSet_,
|
||||
mesh_,
|
||||
meshSearchPtr_(),
|
||||
coeffsDict
|
||||
);
|
||||
coeffsDict.lookup("axis") >> sampledSetAxis_;
|
||||
|
||||
scalarFormatterPtr_ = writer<scalar>::New(dict.lookup("setFormat"));
|
||||
vectorFormatterPtr_ = writer<vector>::New(dict.lookup("setFormat"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::streamLine::execute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::streamLine::write()
|
||||
{
|
||||
Info<< type() << " " << name() << " write:" << nl;
|
||||
|
||||
const Time& runTime = obr_.time();
|
||||
|
||||
// Do all injection and tracking
|
||||
track();
|
||||
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Append slave tracks to master ones
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
globalIndex globalTrackIDs(allTracks_.size());
|
||||
|
||||
// Construct a distribution map to pull all to the master.
|
||||
labelListList sendMap(Pstream::nProcs());
|
||||
labelListList recvMap(Pstream::nProcs());
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Master: receive all. My own first, then consecutive
|
||||
// processors.
|
||||
label trackI = 0;
|
||||
|
||||
forAll(recvMap, proci)
|
||||
{
|
||||
labelList& fromProc = recvMap[proci];
|
||||
fromProc.setSize(globalTrackIDs.localSize(proci));
|
||||
forAll(fromProc, i)
|
||||
{
|
||||
fromProc[i] = trackI++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
labelList& toMaster = sendMap[0];
|
||||
toMaster.setSize(globalTrackIDs.localSize());
|
||||
forAll(toMaster, i)
|
||||
{
|
||||
toMaster[i] = i;
|
||||
}
|
||||
|
||||
const mapDistribute distMap
|
||||
(
|
||||
globalTrackIDs.size(),
|
||||
sendMap.xfer(),
|
||||
recvMap.xfer()
|
||||
);
|
||||
|
||||
|
||||
// Distribute the track positions. Note: use scheduled comms
|
||||
// to prevent buffering.
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allTracks_,
|
||||
flipOp()
|
||||
);
|
||||
|
||||
// Distribute the scalars
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
allScalars_[scalarI].shrink();
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allScalars_[scalarI],
|
||||
flipOp()
|
||||
);
|
||||
allScalars_[scalarI].setCapacity(allScalars_[scalarI].size());
|
||||
}
|
||||
// Distribute the vectors
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
allVectors_[vectorI].shrink();
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allVectors_[vectorI],
|
||||
flipOp()
|
||||
);
|
||||
allVectors_[vectorI].setCapacity(allVectors_[vectorI].size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
label n = 0;
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
n += allTracks_[trackI].size();
|
||||
}
|
||||
|
||||
Info<< " Tracks:" << allTracks_.size() << nl
|
||||
<< " Total samples:" << n
|
||||
<< endl;
|
||||
|
||||
|
||||
// Massage into form suitable for writers
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if (Pstream::master() && allTracks_.size())
|
||||
{
|
||||
// Make output directory
|
||||
|
||||
fileName vtkPath
|
||||
(
|
||||
Pstream::parRun()
|
||||
? runTime.path()/".."/"postProcessing"/"sets"/name()
|
||||
: runTime.path()/"postProcessing"/"sets"/name()
|
||||
);
|
||||
if (mesh_.name() != fvMesh::defaultRegion)
|
||||
{
|
||||
vtkPath = vtkPath/mesh_.name();
|
||||
}
|
||||
vtkPath = vtkPath/mesh_.time().timeName();
|
||||
|
||||
mkDir(vtkPath);
|
||||
|
||||
// Convert track positions
|
||||
|
||||
PtrList<coordSet> tracks(allTracks_.size());
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
tracks.set
|
||||
(
|
||||
trackI,
|
||||
new coordSet
|
||||
(
|
||||
"track" + Foam::name(trackI),
|
||||
sampledSetAxis_ //"xyz"
|
||||
)
|
||||
);
|
||||
tracks[trackI].transfer(allTracks_[trackI]);
|
||||
}
|
||||
|
||||
// Convert scalar values
|
||||
|
||||
if (allScalars_.size() > 0)
|
||||
{
|
||||
List<List<scalarField>> scalarValues(allScalars_.size());
|
||||
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
DynamicList<scalarList>& allTrackVals =
|
||||
allScalars_[scalarI];
|
||||
scalarValues[scalarI].setSize(allTrackVals.size());
|
||||
|
||||
forAll(allTrackVals, trackI)
|
||||
{
|
||||
scalarList& trackVals = allTrackVals[trackI];
|
||||
scalarValues[scalarI][trackI].transfer(trackVals);
|
||||
}
|
||||
}
|
||||
|
||||
fileName vtkFile
|
||||
(
|
||||
vtkPath
|
||||
/ scalarFormatterPtr_().getFileName
|
||||
(
|
||||
tracks[0],
|
||||
scalarNames_
|
||||
)
|
||||
);
|
||||
|
||||
Info<< " Writing data to " << vtkFile.path() << endl;
|
||||
|
||||
scalarFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
tracks,
|
||||
scalarNames_,
|
||||
scalarValues,
|
||||
OFstream(vtkFile)()
|
||||
);
|
||||
}
|
||||
|
||||
// Convert vector values
|
||||
|
||||
if (allVectors_.size() > 0)
|
||||
{
|
||||
List<List<vectorField>> vectorValues(allVectors_.size());
|
||||
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
DynamicList<vectorList>& allTrackVals =
|
||||
allVectors_[vectorI];
|
||||
vectorValues[vectorI].setSize(allTrackVals.size());
|
||||
|
||||
forAll(allTrackVals, trackI)
|
||||
{
|
||||
vectorList& trackVals = allTrackVals[trackI];
|
||||
vectorValues[vectorI][trackI].transfer(trackVals);
|
||||
}
|
||||
}
|
||||
|
||||
fileName vtkFile
|
||||
(
|
||||
vtkPath
|
||||
/ vectorFormatterPtr_().getFileName
|
||||
(
|
||||
tracks[0],
|
||||
vectorNames_
|
||||
)
|
||||
);
|
||||
|
||||
vectorFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
tracks,
|
||||
vectorNames_,
|
||||
vectorValues,
|
||||
OFstream(vtkFile)()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::streamLine::updateMesh(const mapPolyMesh& mpm)
|
||||
{
|
||||
if (&mpm.mesh() == &mesh_)
|
||||
{
|
||||
read(dict_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::streamLine::movePoints(const polyMesh& mesh)
|
||||
{
|
||||
if (&mesh == &mesh_)
|
||||
{
|
||||
// Moving mesh affects the search tree
|
||||
read(dict_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
184
src/functionObjects/field/streamLine/streamLine.H
Normal file
184
src/functionObjects/field/streamLine/streamLine.H
Normal file
@ -0,0 +1,184 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::functionObjects::streamLine
|
||||
|
||||
Group
|
||||
grpFieldFunctionObjects
|
||||
|
||||
Description
|
||||
Generates streamline data by sampling a set of user-specified fields along a
|
||||
particle track, transported by a user-specified velocity field.
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
streamLine1
|
||||
{
|
||||
type streamLine;
|
||||
libs ("libfieldFunctionObjects.so");
|
||||
|
||||
writeControl writeTime;
|
||||
|
||||
setFormat vtk;
|
||||
trackForward yes;
|
||||
fields
|
||||
(
|
||||
U
|
||||
p
|
||||
);
|
||||
lifeTime 10000;
|
||||
trackLength 1e-3;
|
||||
nSubCycle 5;
|
||||
bounds (0.2 -10 -10)(0.22 10 10);
|
||||
cloudName particleTracks;
|
||||
seedSampleSet uniform;
|
||||
uniformCoeffs
|
||||
{
|
||||
type uniform;
|
||||
axis x; //distance;
|
||||
start (-0.0205 0.0001 0.00001);
|
||||
end (-0.0205 0.0005 0.00001);
|
||||
nPoints 100;
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
type | Type name: streamLine | yes |
|
||||
setFormat | Output data type | yes |
|
||||
U | Tracking velocity field name | yes |
|
||||
fields | Fields to sample | yes |
|
||||
lifetime | Maximum number of particle tracking steps | yes |
|
||||
trackLength | Tracking segment length | no |
|
||||
nSubCycle | Number of tracking steps per cell | no|
|
||||
cloudName | Cloud name to use | yes |
|
||||
bounds | Bounding box to trim tracks | no | greatBox
|
||||
seedSampleSet| Seeding method (see below)| yes |
|
||||
\endtable
|
||||
|
||||
Where \c seedSampleSet is typically one of
|
||||
\plaintable
|
||||
uniform | uniform particle seeding
|
||||
cloud | cloud of points
|
||||
triSurfaceMeshPointSet | points according to a tri-surface mesh
|
||||
\endplaintable
|
||||
|
||||
Note
|
||||
When specifying the track resolution, the \c trackLength OR \c nSubCycle
|
||||
option should be used
|
||||
|
||||
See also
|
||||
Foam::functionObject
|
||||
Foam::functionObjects::timeControl
|
||||
Foam::sampledSet
|
||||
Foam::wallBoundedStreamLine
|
||||
Foam::streamLineBase
|
||||
|
||||
SourceFiles
|
||||
streamLine.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_streamLine_H
|
||||
#define functionObjects_streamLine_H
|
||||
|
||||
#include "streamLineBase.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
|
||||
namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class streamLine Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class streamLine
|
||||
:
|
||||
public streamLineBase
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Number of subcycling steps
|
||||
label nSubCycle_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
streamLine(const streamLine&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const streamLine&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("streamLine");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
streamLine
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~streamLine();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read settings
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Do the actual tracking to fill the track data
|
||||
virtual void track();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionObjects
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
987
src/functionObjects/field/streamLine/streamLineBase.C
Normal file
987
src/functionObjects/field/streamLine/streamLineBase.C
Normal file
@ -0,0 +1,987 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "streamLineBase.H"
|
||||
#include "fvMesh.H"
|
||||
#include "ReadFields.H"
|
||||
#include "sampledSet.H"
|
||||
#include "globalIndex.H"
|
||||
#include "mapDistribute.H"
|
||||
#include "interpolationCellPoint.H"
|
||||
#include "wallPolyPatch.H"
|
||||
#include "meshSearchMeshObject.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(streamLineBase, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::indirectPrimitivePatch>
|
||||
Foam::streamLineBase::wallPatch() const
|
||||
{
|
||||
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
|
||||
|
||||
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||
|
||||
label nFaces = 0;
|
||||
|
||||
forAll(patches, patchI)
|
||||
{
|
||||
//if (!polyPatch::constraintType(patches[patchI].type()))
|
||||
if (isA<wallPolyPatch>(patches[patchI]))
|
||||
{
|
||||
nFaces += patches[patchI].size();
|
||||
}
|
||||
}
|
||||
|
||||
labelList addressing(nFaces);
|
||||
|
||||
nFaces = 0;
|
||||
|
||||
forAll(patches, patchI)
|
||||
{
|
||||
//if (!polyPatch::constraintType(patches[patchI].type()))
|
||||
if (isA<wallPolyPatch>(patches[patchI]))
|
||||
{
|
||||
const polyPatch& pp = patches[patchI];
|
||||
|
||||
forAll(pp, i)
|
||||
{
|
||||
addressing[nFaces++] = pp.start()+i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return autoPtr<indirectPrimitivePatch>
|
||||
(
|
||||
new indirectPrimitivePatch
|
||||
(
|
||||
IndirectList<face>
|
||||
(
|
||||
mesh.faces(),
|
||||
addressing
|
||||
),
|
||||
mesh.points()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::initInterpolations
|
||||
(
|
||||
const label nSeeds,
|
||||
label& UIndex,
|
||||
PtrList<volScalarField>& vsFlds,
|
||||
PtrList<interpolation<scalar>>& vsInterp,
|
||||
PtrList<volVectorField>& vvFlds,
|
||||
PtrList<interpolation<vector>>& vvInterp
|
||||
)
|
||||
{
|
||||
const Time& runTime = obr_.time();
|
||||
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
|
||||
|
||||
// Read or lookup fields
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
IOobjectList allObjects(mesh, runTime.timeName());
|
||||
|
||||
IOobjectList objects(2*fields_.size());
|
||||
forAll(fields_, i)
|
||||
{
|
||||
objects.add(*allObjects[fields_[i]]);
|
||||
}
|
||||
|
||||
ReadFields(mesh, objects, vsFlds);
|
||||
vsInterp.setSize(vsFlds.size());
|
||||
forAll(vsFlds, i)
|
||||
{
|
||||
vsInterp.set
|
||||
(
|
||||
i,
|
||||
interpolation<scalar>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
vsFlds[i]
|
||||
)
|
||||
);
|
||||
}
|
||||
ReadFields(mesh, objects, vvFlds);
|
||||
vvInterp.setSize(vvFlds.size());
|
||||
forAll(vvFlds, i)
|
||||
{
|
||||
vvInterp.set
|
||||
(
|
||||
i,
|
||||
interpolation<vector>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
vvFlds[i]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label nScalar = 0;
|
||||
label nVector = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
{
|
||||
if (mesh.foundObject<volScalarField>(fields_[i]))
|
||||
{
|
||||
nScalar++;
|
||||
}
|
||||
else if (mesh.foundObject<volVectorField>(fields_[i]))
|
||||
{
|
||||
nVector++;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find field " << fields_[i] << nl
|
||||
<< "Valid scalar fields are:"
|
||||
<< mesh.names(volScalarField::typeName) << nl
|
||||
<< "Valid vector fields are:"
|
||||
<< mesh.names(volVectorField::typeName)
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
vsInterp.setSize(nScalar);
|
||||
nScalar = 0;
|
||||
vvInterp.setSize(nVector);
|
||||
nVector = 0;
|
||||
|
||||
forAll(fields_, i)
|
||||
{
|
||||
if (mesh.foundObject<volScalarField>(fields_[i]))
|
||||
{
|
||||
const volScalarField& f = mesh.lookupObject<volScalarField>
|
||||
(
|
||||
fields_[i]
|
||||
);
|
||||
vsInterp.set
|
||||
(
|
||||
nScalar++,
|
||||
interpolation<scalar>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
f
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (mesh.foundObject<volVectorField>(fields_[i]))
|
||||
{
|
||||
const volVectorField& f = mesh.lookupObject<volVectorField>
|
||||
(
|
||||
fields_[i]
|
||||
);
|
||||
|
||||
if (f.name() == UName_)
|
||||
{
|
||||
UIndex = nVector;
|
||||
}
|
||||
|
||||
vvInterp.set
|
||||
(
|
||||
nVector++,
|
||||
interpolation<vector>::New
|
||||
(
|
||||
interpolationScheme_,
|
||||
f
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the names
|
||||
scalarNames_.setSize(vsInterp.size());
|
||||
forAll(vsInterp, i)
|
||||
{
|
||||
scalarNames_[i] = vsInterp[i].psi().name();
|
||||
}
|
||||
vectorNames_.setSize(vvInterp.size());
|
||||
forAll(vvInterp, i)
|
||||
{
|
||||
vectorNames_[i] = vvInterp[i].psi().name();
|
||||
}
|
||||
|
||||
// Check that we know the index of U in the interpolators.
|
||||
|
||||
if (UIndex == -1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find field to move particles with : " << UName_ << nl
|
||||
<< "This field has to be present in the sampled fields " << fields_
|
||||
<< " and in the objectRegistry."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Sampled data
|
||||
// ~~~~~~~~~~~~
|
||||
|
||||
// Size to maximum expected sizes.
|
||||
allTracks_.clear();
|
||||
allTracks_.setCapacity(nSeeds);
|
||||
allScalars_.setSize(vsInterp.size());
|
||||
forAll(allScalars_, i)
|
||||
{
|
||||
allScalars_[i].clear();
|
||||
allScalars_[i].setCapacity(nSeeds);
|
||||
}
|
||||
allVectors_.setSize(vvInterp.size());
|
||||
forAll(allVectors_, i)
|
||||
{
|
||||
allVectors_[i].clear();
|
||||
allVectors_[i].setCapacity(nSeeds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::storePoint
|
||||
(
|
||||
const label trackI,
|
||||
|
||||
const scalar w,
|
||||
const label leftI,
|
||||
const label rightI,
|
||||
|
||||
DynamicList<point>& newTrack,
|
||||
DynamicList<scalarList>& newScalars,
|
||||
DynamicList<vectorList>& newVectors
|
||||
) const
|
||||
{
|
||||
label sz = newTrack.size();
|
||||
|
||||
const List<point>& track = allTracks_[trackI];
|
||||
|
||||
newTrack.append((1.0-w)*track[leftI] + w*track[rightI]);
|
||||
|
||||
// Scalars
|
||||
{
|
||||
newScalars.append(scalarList(allScalars_.size()));
|
||||
scalarList& newVals = newScalars[sz];
|
||||
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
const scalarList& trackVals = allScalars_[scalarI][trackI];
|
||||
newVals[scalarI] = (1.0-w)*trackVals[leftI] + w*trackVals[rightI];
|
||||
}
|
||||
}
|
||||
|
||||
// Vectors
|
||||
{
|
||||
newVectors.append(vectorList(allVectors_.size()));
|
||||
vectorList& newVals = newVectors[sz];
|
||||
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
const vectorList& trackVals = allVectors_[vectorI][trackI];
|
||||
newVals[vectorI] = (1.0-w)*trackVals[leftI] + w*trackVals[rightI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Can split a track into multiple tracks
|
||||
void Foam::streamLineBase::trimToBox
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
const label trackI,
|
||||
PtrList<DynamicList<point>>& newTracks,
|
||||
PtrList<DynamicList<scalarList>>& newScalars,
|
||||
PtrList<DynamicList<vectorList>>& newVectors
|
||||
) const
|
||||
{
|
||||
const List<point>& track = allTracks_[trackI];
|
||||
if (track.size())
|
||||
{
|
||||
for
|
||||
(
|
||||
label segmentI = 1;
|
||||
segmentI < track.size();
|
||||
segmentI++
|
||||
)
|
||||
{
|
||||
const point& startPt = track[segmentI-1];
|
||||
const point& endPt = track[segmentI];
|
||||
|
||||
const vector d(endPt-startPt);
|
||||
scalar magD = mag(d);
|
||||
if (magD > ROOTVSMALL)
|
||||
{
|
||||
if (bb.contains(startPt))
|
||||
{
|
||||
// Store 1.0*track[segmentI-1]+0*track[segmentI]
|
||||
storePoint
|
||||
(
|
||||
trackI,
|
||||
|
||||
0.0,
|
||||
segmentI-1,
|
||||
segmentI,
|
||||
|
||||
newTracks.last(),
|
||||
newScalars.last(),
|
||||
newVectors.last()
|
||||
);
|
||||
|
||||
if (!bb.contains(endPt))
|
||||
{
|
||||
point clipPt;
|
||||
if (bb.intersects(endPt, startPt, clipPt))
|
||||
{
|
||||
// End of track. Store point and interpolated
|
||||
// values
|
||||
storePoint
|
||||
(
|
||||
trackI,
|
||||
|
||||
mag(clipPt-startPt)/magD,
|
||||
segmentI-1,
|
||||
segmentI,
|
||||
|
||||
newTracks.last(),
|
||||
newScalars.last(),
|
||||
newVectors.last()
|
||||
);
|
||||
|
||||
newTracks.last().shrink();
|
||||
newScalars.last().shrink();
|
||||
newVectors.last().shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// startPt outside box. New track. Get starting point
|
||||
|
||||
point clipPt;
|
||||
if (bb.intersects(startPt, endPt, clipPt))
|
||||
{
|
||||
// New track
|
||||
newTracks.append
|
||||
(
|
||||
new DynamicList<point>(track.size()/10)
|
||||
);
|
||||
newScalars.append
|
||||
(
|
||||
new DynamicList<scalarList>(track.size()/10)
|
||||
);
|
||||
newVectors.append
|
||||
(
|
||||
new DynamicList<vectorList>(track.size()/10)
|
||||
);
|
||||
|
||||
// Store point and interpolated values
|
||||
storePoint
|
||||
(
|
||||
trackI,
|
||||
|
||||
mag(clipPt-startPt)/magD,
|
||||
segmentI-1,
|
||||
segmentI,
|
||||
|
||||
newTracks.last(),
|
||||
newScalars.last(),
|
||||
newVectors.last()
|
||||
);
|
||||
|
||||
if (!bb.contains(endPt))
|
||||
{
|
||||
bb.intersects
|
||||
(
|
||||
endPt,
|
||||
point(clipPt),
|
||||
clipPt
|
||||
);
|
||||
|
||||
// Store point and interpolated values
|
||||
storePoint
|
||||
(
|
||||
trackI,
|
||||
|
||||
mag(clipPt-startPt)/magD,
|
||||
segmentI-1,
|
||||
segmentI,
|
||||
|
||||
newTracks.last(),
|
||||
newScalars.last(),
|
||||
newVectors.last()
|
||||
);
|
||||
|
||||
newTracks.last().shrink();
|
||||
newScalars.last().shrink();
|
||||
newVectors.last().shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last point
|
||||
if (bb.contains(track.last()))
|
||||
{
|
||||
storePoint
|
||||
(
|
||||
trackI,
|
||||
|
||||
1.0,
|
||||
track.size()-2,
|
||||
track.size()-1,
|
||||
|
||||
newTracks.last(),
|
||||
newScalars.last(),
|
||||
newVectors.last()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::trimToBox(const treeBoundBox& bb)
|
||||
{
|
||||
// Storage for new tracks. Per track, per sample the coordinate (newTracks)
|
||||
// or values for all the sampled fields (newScalars, newVectors)
|
||||
PtrList<DynamicList<point>> newTracks;
|
||||
PtrList<DynamicList<scalarList>> newScalars;
|
||||
PtrList<DynamicList<vectorList>> newVectors;
|
||||
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
const List<point>& track = allTracks_[trackI];
|
||||
|
||||
if (track.size())
|
||||
{
|
||||
// New track. Assume it consists of the whole track
|
||||
newTracks.append(new DynamicList<point>(track.size()));
|
||||
newScalars.append(new DynamicList<scalarList>(track.size()));
|
||||
newVectors.append(new DynamicList<vectorList>(track.size()));
|
||||
|
||||
// Trim, split and append to newTracks
|
||||
trimToBox(bb, trackI, newTracks, newScalars, newVectors);
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer newTracks to allTracks_
|
||||
allTracks_.setSize(newTracks.size());
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
allTracks_[trackI].transfer(newTracks[trackI]);
|
||||
}
|
||||
// Replace track scalars
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
DynamicList<scalarList>& fieldVals = allScalars_[scalarI];
|
||||
fieldVals.setSize(newTracks.size());
|
||||
|
||||
forAll(fieldVals, trackI)
|
||||
{
|
||||
scalarList& trackVals = allScalars_[scalarI][trackI];
|
||||
trackVals.setSize(newScalars[trackI].size());
|
||||
forAll(trackVals, sampleI)
|
||||
{
|
||||
trackVals[sampleI] = newScalars[trackI][sampleI][scalarI];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Replace track vectors
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
DynamicList<vectorList>& fieldVals = allVectors_[vectorI];
|
||||
fieldVals.setSize(newTracks.size());
|
||||
forAll(fieldVals, trackI)
|
||||
{
|
||||
vectorList& trackVals = allVectors_[vectorI][trackI];
|
||||
trackVals.setSize(newVectors[trackI].size());
|
||||
forAll(trackVals, sampleI)
|
||||
{
|
||||
trackVals[sampleI] = newVectors[trackI][sampleI][vectorI];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::streamLineBase::streamLineBase
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obr,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles
|
||||
)
|
||||
:
|
||||
functionObjectState(obr, name),
|
||||
dict_(dict),
|
||||
obr_(obr),
|
||||
loadFromFiles_(loadFromFiles),
|
||||
log_(true)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::streamLineBase::~streamLineBase()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::streamLineBase::read(const dictionary& dict)
|
||||
{
|
||||
if (active_)
|
||||
{
|
||||
log_.readIfPresent("log", dict);
|
||||
|
||||
if (log_) Info<< type() << " " << name_ << ":" << nl;
|
||||
|
||||
dict.lookup("fields") >> fields_;
|
||||
if (dict.found("UName"))
|
||||
{
|
||||
dict.lookup("UName") >> UName_;
|
||||
}
|
||||
else
|
||||
{
|
||||
UName_ = "U";
|
||||
if (dict.found("U"))
|
||||
{
|
||||
IOWarningInFunction(dict)
|
||||
<< "Using deprecated entry \"U\"."
|
||||
<< " Please use \"UName\" instead."
|
||||
<< endl;
|
||||
dict.lookup("U") >> UName_;
|
||||
}
|
||||
}
|
||||
|
||||
if (findIndex(fields_, UName_) == -1)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Velocity field for tracking " << UName_
|
||||
<< " should be present in the list of fields " << fields_
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
|
||||
dict.lookup("trackForward") >> trackForward_;
|
||||
dict.lookup("lifeTime") >> lifeTime_;
|
||||
if (lifeTime_ < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal value " << lifeTime_ << " for lifeTime"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
trackLength_ = VGREAT;
|
||||
if (dict.found("trackLength"))
|
||||
{
|
||||
dict.lookup("trackLength") >> trackLength_;
|
||||
|
||||
if (log_)
|
||||
{
|
||||
Info<< type() << " : fixed track length specified : "
|
||||
<< trackLength_ << nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bounds_ = boundBox::greatBox;
|
||||
if (dict.readIfPresent("bounds", bounds_))
|
||||
{
|
||||
if (log_) Info<< " clipping all segments to " << bounds_ << nl << endl;
|
||||
}
|
||||
|
||||
|
||||
interpolationScheme_ = dict.lookupOrDefault
|
||||
(
|
||||
"interpolationScheme",
|
||||
interpolationCellPoint<scalar>::typeName
|
||||
);
|
||||
|
||||
//if (log_) Info<< " using interpolation " << interpolationScheme_
|
||||
// << endl;
|
||||
|
||||
cloudName_ = dict.lookupOrDefault<word>("cloudName", type());
|
||||
dict.lookup("seedSampleSet") >> seedSet_;
|
||||
|
||||
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
|
||||
|
||||
const dictionary& coeffsDict = dict.subDict(seedSet_ + "Coeffs");
|
||||
|
||||
sampledSetPtr_ = sampledSet::New
|
||||
(
|
||||
seedSet_,
|
||||
mesh,
|
||||
meshSearchMeshObject::New(mesh),
|
||||
coeffsDict
|
||||
);
|
||||
coeffsDict.lookup("axis") >> sampledSetAxis_;
|
||||
|
||||
scalarFormatterPtr_ = writer<scalar>::New(dict.lookup("setFormat"));
|
||||
vectorFormatterPtr_ = writer<vector>::New(dict.lookup("setFormat"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::execute()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::streamLineBase::end()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::streamLineBase::timeSet()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::streamLineBase::write()
|
||||
{
|
||||
if (active_)
|
||||
{
|
||||
if (log_) Info<< type() << " " << name_ << " output:" << nl;
|
||||
|
||||
const Time& runTime = obr_.time();
|
||||
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
|
||||
|
||||
|
||||
// Do all injection and tracking
|
||||
track();
|
||||
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Append slave tracks to master ones
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
globalIndex globalTrackIDs(allTracks_.size());
|
||||
|
||||
// Construct a distribution map to pull all to the master.
|
||||
labelListList sendMap(Pstream::nProcs());
|
||||
labelListList recvMap(Pstream::nProcs());
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Master: receive all. My own first, then consecutive
|
||||
// processors.
|
||||
label trackI = 0;
|
||||
|
||||
forAll(recvMap, procI)
|
||||
{
|
||||
labelList& fromProc = recvMap[procI];
|
||||
fromProc.setSize(globalTrackIDs.localSize(procI));
|
||||
forAll(fromProc, i)
|
||||
{
|
||||
fromProc[i] = trackI++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
labelList& toMaster = sendMap[0];
|
||||
toMaster.setSize(globalTrackIDs.localSize());
|
||||
forAll(toMaster, i)
|
||||
{
|
||||
toMaster[i] = i;
|
||||
}
|
||||
|
||||
const mapDistribute distMap
|
||||
(
|
||||
globalTrackIDs.size(),
|
||||
sendMap.xfer(),
|
||||
recvMap.xfer()
|
||||
);
|
||||
|
||||
|
||||
// Distribute the track positions. Note: use scheduled comms
|
||||
// to prevent buffering.
|
||||
allTracks_.shrink();
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allTracks_,
|
||||
flipOp()
|
||||
);
|
||||
allTracks_.setCapacity(allTracks_.size());
|
||||
|
||||
// Distribute the scalars
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
allScalars_[scalarI].shrink();
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allScalars_[scalarI],
|
||||
flipOp()
|
||||
);
|
||||
allScalars_[scalarI].setCapacity(allScalars_[scalarI].size());
|
||||
}
|
||||
// Distribute the vectors
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
allVectors_[vectorI].shrink();
|
||||
mapDistributeBase::distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
distMap.schedule(),
|
||||
distMap.constructSize(),
|
||||
distMap.subMap(),
|
||||
false,
|
||||
distMap.constructMap(),
|
||||
false,
|
||||
allVectors_[vectorI],
|
||||
flipOp()
|
||||
);
|
||||
allVectors_[vectorI].setCapacity(allVectors_[vectorI].size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: filenames scattered below since used in global call
|
||||
fileName scalarVtkFile;
|
||||
fileName vectorVtkFile;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (bounds_ != boundBox::greatBox)
|
||||
{
|
||||
// Clip to bounding box
|
||||
trimToBox(treeBoundBox(bounds_));
|
||||
}
|
||||
|
||||
|
||||
label nTracks = 0;
|
||||
label n = 0;
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
if (allTracks_[trackI].size())
|
||||
{
|
||||
nTracks++;
|
||||
n += allTracks_[trackI].size();
|
||||
}
|
||||
}
|
||||
|
||||
if (log_)
|
||||
{
|
||||
Info<< " Tracks:" << nTracks << nl
|
||||
<< " Total samples:" << n
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
// Massage into form suitable for writers
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Make output directory
|
||||
|
||||
fileName vtkPath
|
||||
(
|
||||
Pstream::parRun()
|
||||
? runTime.path()/".."/"postProcessing"/"sets"/name()
|
||||
: runTime.path()/"postProcessing"/"sets"/name()
|
||||
);
|
||||
if (mesh.name() != fvMesh::defaultRegion)
|
||||
{
|
||||
vtkPath = vtkPath/mesh.name();
|
||||
}
|
||||
vtkPath = vtkPath/mesh.time().timeName();
|
||||
|
||||
mkDir(vtkPath);
|
||||
|
||||
// Convert track positions (and compact out empty tracks)
|
||||
|
||||
PtrList<coordSet> tracks(nTracks);
|
||||
nTracks = 0;
|
||||
labelList oldToNewTrack(allTracks_.size(), -1);
|
||||
|
||||
forAll(allTracks_, trackI)
|
||||
{
|
||||
if (allTracks_[trackI].size())
|
||||
{
|
||||
tracks.set
|
||||
(
|
||||
nTracks,
|
||||
new coordSet
|
||||
(
|
||||
"track" + Foam::name(nTracks),
|
||||
sampledSetAxis_ //"xyz"
|
||||
)
|
||||
);
|
||||
oldToNewTrack[trackI] = nTracks;
|
||||
tracks[nTracks].transfer(allTracks_[trackI]);
|
||||
nTracks++;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert scalar values
|
||||
|
||||
if (allScalars_.size() > 0)
|
||||
{
|
||||
List<List<scalarField>> scalarValues(allScalars_.size());
|
||||
|
||||
forAll(allScalars_, scalarI)
|
||||
{
|
||||
DynamicList<scalarList>& allTrackVals =
|
||||
allScalars_[scalarI];
|
||||
scalarValues[scalarI].setSize(nTracks);
|
||||
|
||||
forAll(allTrackVals, trackI)
|
||||
{
|
||||
scalarList& vals = allTrackVals[trackI];
|
||||
if (vals.size())
|
||||
{
|
||||
label newTrackI = oldToNewTrack[trackI];
|
||||
scalarValues[scalarI][newTrackI].transfer(vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scalarVtkFile = fileName
|
||||
(
|
||||
vtkPath
|
||||
/ scalarFormatterPtr_().getFileName
|
||||
(
|
||||
tracks[0],
|
||||
scalarNames_
|
||||
)
|
||||
);
|
||||
|
||||
if (log_) Info
|
||||
<< " Writing data to " << scalarVtkFile.path() << endl;
|
||||
|
||||
scalarFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
tracks,
|
||||
scalarNames_,
|
||||
scalarValues,
|
||||
OFstream(scalarVtkFile)()
|
||||
);
|
||||
}
|
||||
|
||||
// Convert vector values
|
||||
|
||||
if (allVectors_.size() > 0)
|
||||
{
|
||||
List<List<vectorField>> vectorValues(allVectors_.size());
|
||||
|
||||
forAll(allVectors_, vectorI)
|
||||
{
|
||||
DynamicList<vectorList>& allTrackVals =
|
||||
allVectors_[vectorI];
|
||||
vectorValues[vectorI].setSize(nTracks);
|
||||
|
||||
forAll(allTrackVals, trackI)
|
||||
{
|
||||
vectorList& vals = allTrackVals[trackI];
|
||||
if (vals.size())
|
||||
{
|
||||
label newTrackI = oldToNewTrack[trackI];
|
||||
vectorValues[vectorI][newTrackI].transfer(vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vectorVtkFile = fileName
|
||||
(
|
||||
vtkPath
|
||||
/ vectorFormatterPtr_().getFileName
|
||||
(
|
||||
tracks[0],
|
||||
vectorNames_
|
||||
)
|
||||
);
|
||||
|
||||
//if (log_) Info<< " Writing vector data to "
|
||||
// << vectorVtkFile << endl;
|
||||
|
||||
vectorFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
tracks,
|
||||
vectorNames_,
|
||||
vectorValues,
|
||||
OFstream(vectorVtkFile)()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fileNames are generated on the master but setProperty needs to
|
||||
// be across all procs
|
||||
Pstream::scatter(scalarVtkFile);
|
||||
forAll(scalarNames_, nameI)
|
||||
{
|
||||
dictionary propsDict;
|
||||
propsDict.add("file", scalarVtkFile);
|
||||
const word& fieldName = scalarNames_[nameI];
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
|
||||
Pstream::scatter(vectorVtkFile);
|
||||
forAll(vectorNames_, nameI)
|
||||
{
|
||||
dictionary propsDict;
|
||||
propsDict.add("file", vectorVtkFile);
|
||||
const word& fieldName = vectorNames_[nameI];
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::updateMesh(const mapPolyMesh&)
|
||||
{
|
||||
read(dict_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineBase::movePoints(const polyMesh&)
|
||||
{
|
||||
// Moving mesh affects the search tree
|
||||
read(dict_);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
246
src/functionObjects/field/streamLine/streamLineBase.H
Normal file
246
src/functionObjects/field/streamLine/streamLineBase.H
Normal file
@ -0,0 +1,246 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::streamLineBase
|
||||
|
||||
SeeAlso
|
||||
Foam::streamLine
|
||||
Foam::wallBoundedStreamLine
|
||||
|
||||
SourceFiles
|
||||
streamLineBase.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef streamLineBase_H
|
||||
#define streamLineBase_H
|
||||
|
||||
#include "functionObjectState.H"
|
||||
#include "DynamicList.H"
|
||||
#include "scalarList.H"
|
||||
#include "vectorList.H"
|
||||
#include "writer.H"
|
||||
#include "indirectPrimitivePatch.H"
|
||||
#include "interpolation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
class mapPolyMesh;
|
||||
class meshSearch;
|
||||
class sampledSet;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class streamLineBase Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class streamLineBase
|
||||
:
|
||||
public functionObjectState
|
||||
{
|
||||
protected:
|
||||
|
||||
//- Input dictionary
|
||||
dictionary dict_;
|
||||
|
||||
//- Database this class is registered to
|
||||
const objectRegistry& obr_;
|
||||
|
||||
//- Load fields from files (not from objectRegistry)
|
||||
bool loadFromFiles_;
|
||||
|
||||
//- Switch to send output to Info as well as to file
|
||||
Switch log_;
|
||||
|
||||
//- List of fields to sample
|
||||
wordList fields_;
|
||||
|
||||
//- Field to transport particle with
|
||||
word UName_;
|
||||
|
||||
//- Interpolation scheme to use
|
||||
word interpolationScheme_;
|
||||
|
||||
//- Whether to use +u or -u
|
||||
bool trackForward_;
|
||||
|
||||
//- Maximum lifetime (= number of cells) of particle
|
||||
label lifeTime_;
|
||||
|
||||
//- Track length
|
||||
scalar trackLength_;
|
||||
|
||||
//- Optional trimming of tracks
|
||||
boundBox bounds_;
|
||||
|
||||
//- Optional specified name of particles
|
||||
word cloudName_;
|
||||
|
||||
//- Type of seed
|
||||
word seedSet_;
|
||||
|
||||
//- Names of scalar fields
|
||||
wordList scalarNames_;
|
||||
|
||||
//- Names of vector fields
|
||||
wordList vectorNames_;
|
||||
|
||||
|
||||
// Demand driven
|
||||
|
||||
//- Mesh searching enigne
|
||||
autoPtr<meshSearch> meshSearchPtr_;
|
||||
|
||||
//- Seed set engine
|
||||
autoPtr<sampledSet> sampledSetPtr_;
|
||||
|
||||
//- Axis of the sampled points to output
|
||||
word sampledSetAxis_;
|
||||
|
||||
//- File writer for scalar data
|
||||
autoPtr<writer<scalar>> scalarFormatterPtr_;
|
||||
|
||||
//- File writer for vector data
|
||||
autoPtr<writer<vector>> vectorFormatterPtr_;
|
||||
|
||||
|
||||
// Generated data
|
||||
|
||||
//- All tracks. Per track the points it passed through
|
||||
DynamicList<List<point>> allTracks_;
|
||||
|
||||
//- Per scalarField, per track, the sampled values
|
||||
List<DynamicList<scalarList>> allScalars_;
|
||||
|
||||
//- Per vectorField, per track, the sampled values
|
||||
List<DynamicList<vectorList>> allVectors_;
|
||||
|
||||
|
||||
//- Construct patch out of all wall patch faces
|
||||
autoPtr<indirectPrimitivePatch> wallPatch() const;
|
||||
|
||||
//- Initialise fields, interpolators and track storage
|
||||
void initInterpolations
|
||||
(
|
||||
const label nSeeds,
|
||||
label& UIndex,
|
||||
PtrList<volScalarField>& vsFlds,
|
||||
PtrList<interpolation<scalar>>& vsInterp,
|
||||
PtrList<volVectorField>& vvFlds,
|
||||
PtrList<interpolation<vector>>& vvInterp
|
||||
);
|
||||
|
||||
//- Generate point and values by interpolating from existing values
|
||||
void storePoint
|
||||
(
|
||||
const label trackI,
|
||||
|
||||
const scalar w,
|
||||
const label leftI,
|
||||
const label rightI,
|
||||
|
||||
DynamicList<point>& newTrack,
|
||||
DynamicList<List<scalar>>& newScalars,
|
||||
DynamicList<List<vector>>& newVectors
|
||||
) const;
|
||||
|
||||
//- Trim and possibly split a track
|
||||
void trimToBox
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
const label trackI,
|
||||
PtrList<DynamicList<point>>& newTracks,
|
||||
PtrList<DynamicList<scalarList>>& newScalars,
|
||||
PtrList<DynamicList<vectorList>>& newVectors
|
||||
) const;
|
||||
|
||||
//- Trim tracks to bounding box
|
||||
void trimToBox(const treeBoundBox& bb);
|
||||
|
||||
//- Do the actual tracking to fill the track data
|
||||
virtual void track() = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("streamLineBase");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct for given objectRegistry and dictionary.
|
||||
// Allow the possibility to load fields from files
|
||||
streamLineBase
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry&,
|
||||
const dictionary&,
|
||||
const bool loadFromFiles = false
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~streamLineBase();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read the field average data
|
||||
virtual void read(const dictionary&);
|
||||
|
||||
//- Execute the averaging
|
||||
virtual void execute();
|
||||
|
||||
//- Execute the averaging at the final time-loop, currently does nothing
|
||||
virtual void end();
|
||||
|
||||
//- Called when time was set at the end of the Time::operator++
|
||||
virtual void timeSet();
|
||||
|
||||
//- Track and write
|
||||
virtual void write();
|
||||
|
||||
//- Update for changes of mesh
|
||||
virtual void updateMesh(const mapPolyMesh&);
|
||||
|
||||
//- Update for mesh point-motion
|
||||
virtual void movePoints(const polyMesh&);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
507
src/functionObjects/field/streamLine/streamLineParticle.C
Normal file
507
src/functionObjects/field/streamLine/streamLineParticle.C
Normal file
@ -0,0 +1,507 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "streamLineParticle.H"
|
||||
#include "vectorFieldIOField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// defineParticleTypeNameAndDebug(streamLineParticle, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::streamLineParticle::calcSubCycleDeltaT
|
||||
(
|
||||
trackingData& td,
|
||||
const scalar dt,
|
||||
const vector& U
|
||||
) const
|
||||
{
|
||||
particle testParticle(*this);
|
||||
|
||||
bool oldKeepParticle = td.keepParticle;
|
||||
bool oldSwitchProcessor = td.switchProcessor;
|
||||
scalar fraction = testParticle.trackToFace(position()+dt*U, td);
|
||||
td.keepParticle = oldKeepParticle;
|
||||
td.switchProcessor = oldSwitchProcessor;
|
||||
// Adapt the dt to subdivide the trajectory into substeps.
|
||||
return dt*fraction/td.nSubCycle_;
|
||||
}
|
||||
|
||||
|
||||
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<vector>& 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)
|
||||
{
|
||||
//if (is.format() == IOstream::ASCII)
|
||||
List<scalarList> sampledScalars;
|
||||
List<vectorList> 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]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check state of Istream
|
||||
is.check
|
||||
(
|
||||
"streamLineParticle::streamLineParticle"
|
||||
"(const Cloud<streamLineParticle>&, Istream&, bool)"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
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 trackTime
|
||||
)
|
||||
{
|
||||
streamLineParticle& p = static_cast<streamLineParticle&>(*this);
|
||||
|
||||
td.switchProcessor = false;
|
||||
td.keepParticle = true;
|
||||
|
||||
scalar tEnd = (1.0 - stepFraction())*trackTime;
|
||||
scalar maxDt = mesh_.bounds().mag();
|
||||
|
||||
while
|
||||
(
|
||||
td.keepParticle
|
||||
&& !td.switchProcessor
|
||||
&& lifeTime_ > 0
|
||||
)
|
||||
{
|
||||
// set the lagrangian time-step
|
||||
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 < 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)
|
||||
{
|
||||
dt = td.trackLength_;
|
||||
//Pout<< " subiteration " << subIter
|
||||
// << " : fixed length: updated dt:" << dt << endl;
|
||||
}
|
||||
else if (subIter == 0 && td.nSubCycle_ > 1)
|
||||
{
|
||||
// Adapt dt to cross cell in a few steps
|
||||
dt = calcSubCycleDeltaT(td, dt, U);
|
||||
}
|
||||
else if (subIter == td.nSubCycle_ - 1)
|
||||
{
|
||||
// Do full step on last subcycle
|
||||
dt = maxDt;
|
||||
}
|
||||
|
||||
|
||||
scalar fraction = trackToFace(position() + dt*U, td);
|
||||
dt *= fraction;
|
||||
|
||||
tEnd -= dt;
|
||||
stepFraction() = 1.0 - tEnd/trackTime;
|
||||
|
||||
if (tEnd <= ROOTVSMALL)
|
||||
{
|
||||
// Force removal
|
||||
lifeTime_ = 0;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
face() != -1
|
||||
|| !td.keepParticle
|
||||
|| td.switchProcessor
|
||||
|| lifeTime_ == 0
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!td.keepParticle || lifeTime_ == 0)
|
||||
{
|
||||
if (lifeTime_ == 0)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "streamLineParticle : Removing stagnant particle:"
|
||||
<< p.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:"
|
||||
<< p.position()
|
||||
<< " sampled positions:" << sampledPositions_.size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer particle data into trackingData.
|
||||
//td.allPositions_.append(sampledPositions_);
|
||||
td.allPositions_.append(vectorList());
|
||||
vectorList& top = td.allPositions_.last();
|
||||
top.transfer(sampledPositions_);
|
||||
|
||||
forAll(sampledScalars_, i)
|
||||
{
|
||||
//td.allScalars_[i].append(sampledScalars_[i]);
|
||||
td.allScalars_[i].append(scalarList());
|
||||
scalarList& top = td.allScalars_[i].last();
|
||||
top.transfer(sampledScalars_[i]);
|
||||
}
|
||||
forAll(sampledVectors_, i)
|
||||
{
|
||||
//td.allVectors_[i].append(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<streamLineParticle>& c)
|
||||
{
|
||||
if (!c.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
particle::readFields(c);
|
||||
|
||||
IOField<label> lifeTime
|
||||
(
|
||||
c.fieldIOobject("lifeTime", IOobject::MUST_READ)
|
||||
);
|
||||
c.checkFieldIOobject(c, lifeTime);
|
||||
|
||||
vectorFieldIOField sampledPositions
|
||||
(
|
||||
c.fieldIOobject("sampledPositions", IOobject::MUST_READ)
|
||||
);
|
||||
c.checkFieldIOobject(c, sampledPositions);
|
||||
|
||||
// vectorFieldIOField sampleVelocity
|
||||
// (
|
||||
// c.fieldIOobject("sampleVelocity", IOobject::MUST_READ)
|
||||
// );
|
||||
// c.checkFieldIOobject(c, sampleVelocity);
|
||||
|
||||
label i = 0;
|
||||
forAllIter(Cloud<streamLineParticle>, c, iter)
|
||||
{
|
||||
iter().lifeTime_ = lifeTime[i];
|
||||
iter().sampledPositions_.transfer(sampledPositions[i]);
|
||||
// iter().sampleVelocity_.transfer(sampleVelocity[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
|
||||
{
|
||||
particle::writeFields(c);
|
||||
|
||||
label np = c.size();
|
||||
|
||||
IOField<label> lifeTime
|
||||
(
|
||||
c.fieldIOobject("lifeTime", IOobject::NO_READ),
|
||||
np
|
||||
);
|
||||
vectorFieldIOField sampledPositions
|
||||
(
|
||||
c.fieldIOobject("sampledPositions", IOobject::NO_READ),
|
||||
np
|
||||
);
|
||||
// vectorFieldIOField sampleVelocity
|
||||
// (
|
||||
// c.fieldIOobject("sampleVelocity", IOobject::NO_READ),
|
||||
// np
|
||||
// );
|
||||
|
||||
label i = 0;
|
||||
forAllConstIter(Cloud<streamLineParticle>, c, iter)
|
||||
{
|
||||
lifeTime[i] = iter().lifeTime_;
|
||||
sampledPositions[i] = iter().sampledPositions_;
|
||||
// sampleVelocity[i] = iter().sampleVelocity_;
|
||||
i++;
|
||||
}
|
||||
|
||||
lifeTime.write();
|
||||
sampledPositions.write();
|
||||
// sampleVelocity.write();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::operator<<(Ostream& os, const streamLineParticle& p)
|
||||
{
|
||||
os << static_cast<const particle&>(p)
|
||||
<< token::SPACE << p.lifeTime_
|
||||
<< token::SPACE << p.sampledPositions_
|
||||
<< token::SPACE << p.sampledScalars_
|
||||
<< token::SPACE << p.sampledVectors_;
|
||||
|
||||
// Check state of Ostream
|
||||
os.check("Ostream& operator<<(Ostream&, const streamLineParticle&)");
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
317
src/functionObjects/field/streamLine/streamLineParticle.H
Normal file
317
src/functionObjects/field/streamLine/streamLineParticle.H
Normal file
@ -0,0 +1,317 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::streamLineParticle
|
||||
|
||||
Description
|
||||
Particle class that samples fields as it passes through. Used in streamline
|
||||
calculation.
|
||||
|
||||
SourceFiles
|
||||
streamLineParticle.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef streamLineParticle_H
|
||||
#define streamLineParticle_H
|
||||
|
||||
#include "particle.H"
|
||||
#include "autoPtr.H"
|
||||
#include "interpolation.H"
|
||||
#include "vectorList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class streamLineParticleCloud;
|
||||
|
||||
|
||||
// Forward declaration of friend functions and operators
|
||||
|
||||
class streamLineParticle;
|
||||
|
||||
Ostream& operator<<(Ostream&, const streamLineParticle&);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class streamLineParticle Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class streamLineParticle
|
||||
:
|
||||
public particle
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Class used to pass tracking data to the trackToFace function
|
||||
class trackingData
|
||||
:
|
||||
public particle::TrackingData<Cloud<streamLineParticle>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
const PtrList<interpolation<scalar>>& vsInterp_;
|
||||
const PtrList<interpolation<vector>>& vvInterp_;
|
||||
const label UIndex_;
|
||||
const bool trackForward_;
|
||||
const label nSubCycle_;
|
||||
const scalar trackLength_;
|
||||
|
||||
DynamicList<vectorList>& allPositions_;
|
||||
List<DynamicList<scalarList>>& allScalars_;
|
||||
List<DynamicList<vectorList>>& allVectors_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
trackingData
|
||||
(
|
||||
Cloud<streamLineParticle>& cloud,
|
||||
const PtrList<interpolation<scalar>>& vsInterp,
|
||||
const PtrList<interpolation<vector>>& vvInterp,
|
||||
const label UIndex,
|
||||
const bool trackForward,
|
||||
const label nSubCycle,
|
||||
const scalar trackLength,
|
||||
|
||||
DynamicList<List<point>>& allPositions,
|
||||
List<DynamicList<scalarList>>& allScalars,
|
||||
List<DynamicList<vectorList>>& allVectors
|
||||
)
|
||||
:
|
||||
particle::TrackingData<Cloud<streamLineParticle>>(cloud),
|
||||
vsInterp_(vsInterp),
|
||||
vvInterp_(vvInterp),
|
||||
UIndex_(UIndex),
|
||||
trackForward_(trackForward),
|
||||
nSubCycle_(nSubCycle),
|
||||
trackLength_(trackLength),
|
||||
|
||||
allPositions_(allPositions),
|
||||
allScalars_(allScalars),
|
||||
allVectors_(allVectors)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Lifetime of particle. Particle dies when reaches 0.
|
||||
label lifeTime_;
|
||||
|
||||
//- Sampled positions
|
||||
DynamicList<point> sampledPositions_;
|
||||
|
||||
//- Sampled scalars
|
||||
List<DynamicList<scalar>> sampledScalars_;
|
||||
|
||||
//- Sampled vectors
|
||||
List<DynamicList<vector>> sampledVectors_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Estimate dt to cross from current face to next one in nSubCycle
|
||||
// steps.
|
||||
scalar calcSubCycleDeltaT
|
||||
(
|
||||
trackingData& td,
|
||||
const scalar dt,
|
||||
const vector& U
|
||||
) const;
|
||||
|
||||
void constrainVelocity
|
||||
(
|
||||
trackingData& td,
|
||||
const scalar dt,
|
||||
vector& U
|
||||
);
|
||||
|
||||
//- Interpolate all quantities; return interpolated velocity.
|
||||
vector interpolateFields
|
||||
(
|
||||
const trackingData&,
|
||||
const point&,
|
||||
const label celli,
|
||||
const label facei
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
streamLineParticle
|
||||
(
|
||||
const polyMesh& c,
|
||||
const vector& position,
|
||||
const label celli,
|
||||
const label lifeTime
|
||||
);
|
||||
|
||||
//- Construct from Istream
|
||||
streamLineParticle
|
||||
(
|
||||
const polyMesh& c,
|
||||
Istream& is,
|
||||
bool readFields = true
|
||||
);
|
||||
|
||||
//- Construct copy
|
||||
streamLineParticle(const streamLineParticle& p);
|
||||
|
||||
//- Construct and return a clone
|
||||
autoPtr<particle> clone() const
|
||||
{
|
||||
return autoPtr<particle>(new streamLineParticle(*this));
|
||||
}
|
||||
|
||||
//- Factory class to read-construct particles used for
|
||||
// parallel transfer
|
||||
class iNew
|
||||
{
|
||||
const polyMesh& mesh_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const polyMesh& mesh)
|
||||
:
|
||||
mesh_(mesh)
|
||||
{}
|
||||
|
||||
autoPtr<streamLineParticle> operator()(Istream& is) const
|
||||
{
|
||||
return autoPtr<streamLineParticle>
|
||||
(
|
||||
new streamLineParticle(mesh_, is, true)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Tracking
|
||||
|
||||
//- Track all particles to their end point
|
||||
bool move(trackingData&, const scalar trackTime);
|
||||
|
||||
|
||||
//- Overridable function to handle the particle hitting a patch
|
||||
// Executed before other patch-hitting functions
|
||||
bool hitPatch
|
||||
(
|
||||
const polyPatch&,
|
||||
trackingData& td,
|
||||
const label patchi,
|
||||
const scalar trackFraction,
|
||||
const tetIndices& tetIs
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a wedge
|
||||
void hitWedgePatch
|
||||
(
|
||||
const wedgePolyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a
|
||||
// symmetry plane
|
||||
void hitSymmetryPlanePatch
|
||||
(
|
||||
const symmetryPlanePolyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a
|
||||
// symmetry patch
|
||||
void hitSymmetryPatch
|
||||
(
|
||||
const symmetryPolyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a cyclic
|
||||
void hitCyclicPatch
|
||||
(
|
||||
const cyclicPolyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a
|
||||
//- processorPatch
|
||||
void hitProcessorPatch
|
||||
(
|
||||
const processorPolyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a wallPatch
|
||||
void hitWallPatch
|
||||
(
|
||||
const wallPolyPatch&,
|
||||
trackingData& td,
|
||||
const tetIndices&
|
||||
);
|
||||
|
||||
//- Overridable function to handle the particle hitting a polyPatch
|
||||
void hitPatch
|
||||
(
|
||||
const polyPatch&,
|
||||
trackingData& td
|
||||
);
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Read
|
||||
static void readFields(Cloud<streamLineParticle>&);
|
||||
|
||||
//- Write
|
||||
static void writeFields(const Cloud<streamLineParticle>&);
|
||||
|
||||
|
||||
// Ostream Operator
|
||||
|
||||
friend Ostream& operator<<(Ostream&, const streamLineParticle&);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,64 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "streamLineParticleCloud.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTemplateTypeNameAndDebug(Cloud<streamLineParticle>, 0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::streamLineParticleCloud::streamLineParticleCloud
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& cloudName,
|
||||
bool readFields
|
||||
)
|
||||
:
|
||||
Cloud<streamLineParticle>(mesh, cloudName, false)
|
||||
{
|
||||
if (readFields)
|
||||
{
|
||||
streamLineParticle::readFields(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::streamLineParticleCloud::streamLineParticleCloud
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& cloudName,
|
||||
const IDLList<streamLineParticle>& particles
|
||||
)
|
||||
:
|
||||
Cloud<streamLineParticle>(mesh, cloudName, particles)
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::streamLineParticleCloud
|
||||
|
||||
Description
|
||||
A Cloud of streamLine particles
|
||||
|
||||
SourceFiles
|
||||
streamLineCloud.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef streamLineCloud_H
|
||||
#define streamLineCloud_H
|
||||
|
||||
#include "Cloud.H"
|
||||
#include "streamLineParticle.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class streamLineCloud Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class streamLineParticleCloud
|
||||
:
|
||||
public Cloud<streamLineParticle>
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
streamLineParticleCloud(const streamLineParticleCloud&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const streamLineParticleCloud&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Type of parcel the cloud was instantiated for
|
||||
typedef streamLineParticle parcelType;
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given mesh
|
||||
streamLineParticleCloud
|
||||
(
|
||||
const polyMesh&,
|
||||
const word& cloudName = "defaultCloud",
|
||||
bool readFields = true
|
||||
);
|
||||
|
||||
//- Construct from mesh, cloud name, and a list of particles
|
||||
streamLineParticleCloud
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& cloudName,
|
||||
const IDLList<streamLineParticle>& particles
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user