ENH: wallBoundedStreamLine: near-wall tracking

This commit is contained in:
mattijs
2012-02-06 16:39:43 +00:00
parent d1767ccaca
commit 307a13f08b
10 changed files with 3214 additions and 0 deletions

View File

@ -29,6 +29,11 @@ streamLine/streamLineParticle.C
streamLine/streamLineParticleCloud.C streamLine/streamLineParticleCloud.C
streamLine/streamLineFunctionObject.C streamLine/streamLineFunctionObject.C
wallBoundedStreamLine/wallBoundedStreamLine.C
wallBoundedStreamLine/wallBoundedStreamLineFunctionObject.C
wallBoundedStreamLine/wallBoundedStreamLineParticle.C
wallBoundedStreamLine/wallBoundedStreamLineParticleCloud.C
surfaceInterpolateFields/surfaceInterpolateFields.C surfaceInterpolateFields/surfaceInterpolateFields.C
surfaceInterpolateFields/surfaceInterpolateFieldsFunctionObject.C surfaceInterpolateFields/surfaceInterpolateFieldsFunctionObject.C

View File

@ -0,0 +1,144 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 2.0.0 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application icoFoam;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0.5;
deltaT 0.005;
writeControl timeStep;
writeInterval 20;
purgeWrite 0;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
functions
{
readFields
{
// Where to load it from (if not already in solver)
functionObjectLibs ("libfieldFunctionObjects.so");
type readFields;
fields (p U k);
}
near
{
// Where to load it from
functionObjectLibs ("libfieldFunctionObjects.so");
type nearWallFields;
// Output every
outputControl outputTime;
//outputInterval 1;
// Fields to be sampled. Per field original name and mapped field to
// create.
fields
(
(U UNear)
);
// Patches/groups to sample (regular expressions)
patches (motorBike);
// Distance to sample
distance 0.001;
}
streamLines
{
// Where to load it from (if not already in solver)
functionObjectLibs ("libfieldFunctionObjects.so");
type wallBoundedStreamLine;
// Output every
outputControl timeStep; //outputTime;
// outputInterval 10;
setFormat vtk; //gnuplot; //xmgr; //raw; //jplot;
// Velocity field to use for tracking.
UName UNear;
// Interpolation method. Default is cellPoint. See sampleDict.
//interpolationScheme pointMVC;
// Tracked forwards (+U) or backwards (-U)
trackForward true;
interpolationScheme cellPoint;
// Names of fields to sample. Should contain above velocity field!
fields (p U k UNear);
// Steps particles can travel before being removed
lifeTime 100;
// Cloud name to use
cloudName particleTracks;
// Seeding method. See the sampleSets in sampleDict.
seedSampleSet patchSeed; //cloud;//triSurfaceMeshPointSet;
uniformCoeffs
{
type uniform;
axis x; //distance;
start (0.0035 0.0999 0.0001);
end (0.0035 0.0999 0.0099);
nPoints 20;
}
cloudCoeffs
{
type cloud;
axis x; //distance;
points ((0.351516548679288 -0.0116085375585099 1.24));
}
patchSeedCoeffs
{
type patchSeed;//patchCloud; //cloud; //uniform;
patches (motorBike);
axis x; //distance;
maxPoints 20000;
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,887 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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 "wallBoundedStreamLine.H"
#include "fvMesh.H"
#include "wallBoundedStreamLineParticleCloud.H"
#include "ReadFields.H"
#include "meshSearch.H"
#include "sampledSet.H"
#include "globalIndex.H"
#include "mapDistribute.H"
#include "interpolationCellPoint.H"
#include "PatchTools.H"
#include "meshSearchMeshObject.H"
#include "faceSet.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(Foam::wallBoundedStreamLine, 0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::autoPtr<Foam::indirectPrimitivePatch>
Foam::wallBoundedStreamLine::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()
)
);
}
Foam::tetIndices Foam::wallBoundedStreamLine::findNearestTet
(
const PackedBoolList& isWallPatch,
const point& seedPt,
const label cellI
) const
{
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
const cell& cFaces = mesh.cells()[cellI];
label minFaceI = -1;
label minTetPtI = -1;
scalar minDistSqr = sqr(GREAT);
forAll(cFaces, cFaceI)
{
label faceI = cFaces[cFaceI];
if (isWallPatch[faceI])
{
const face& f = mesh.faces()[faceI];
const label fp0 = mesh.tetBasePtIs()[faceI];
const point& basePoint = mesh.points()[f[fp0]];
label fp = f.fcIndex(fp0);
for (label i = 2; i < f.size(); i++)
{
const point& thisPoint = mesh.points()[f[fp]];
label nextFp = f.fcIndex(fp);
const point& nextPoint = mesh.points()[f[nextFp]];
const triPointRef tri(basePoint, thisPoint, nextPoint);
scalar d2 = magSqr(tri.centre() - seedPt);
if (d2 < minDistSqr)
{
minDistSqr = d2;
minFaceI = faceI;
minTetPtI = i-1;
}
fp = nextFp;
}
}
}
// Put particle in tet
return tetIndices
(
cellI,
minFaceI,
minTetPtI,
mesh
);
}
void Foam::wallBoundedStreamLine::track()
{
const Time& runTime = obr_.time();
const fvMesh& mesh = dynamic_cast<const fvMesh&>(obr_);
// Determine the 'wall' patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// These are the faces that need to be followed
autoPtr<indirectPrimitivePatch> boundaryPatch(wallPatch());
PackedBoolList isWallPatch(mesh.nFaces());
forAll(boundaryPatch().addressing(), i)
{
isWallPatch[boundaryPatch().addressing()[i]] = 1;
}
// Find nearest wall particle for the seedPoints
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IDLList<wallBoundedStreamLineParticle> initialParticles;
wallBoundedStreamLineParticleCloud particles
(
mesh,
cloudName_,
initialParticles
);
{
// Get the seed points
// ~~~~~~~~~~~~~~~~~~~
const sampledSet& seedPoints = sampledSetPtr_();
forAll(seedPoints, i)
{
const point& seedPt = seedPoints[i];
label cellI = seedPoints.cells()[i];
tetIndices ids(findNearestTet(isWallPatch, seedPt, cellI));
if (ids.face() != -1 && isWallPatch[ids.face()])
{
//Pout<< "Seeding particle :" << nl
// << " seedPt:" << seedPt << nl
// << " face :" << ids.face() << nl
// << " at :" << mesh.faceCentres()[ids.face()] << nl
// << " cell :" << mesh.cellCentres()[ids.cell()] << nl
// << endl;
particles.addParticle
(
new wallBoundedStreamLineParticle
(
mesh,
ids.faceTri(mesh).centre(),
ids.cell(),
ids.face(), // tetFace
ids.tetPt(),
-1, // not on a mesh edge
-1, // not on a diagonal edge
lifeTime_ // lifetime
)
);
}
else
{
Pout<< type() << " : ignoring seed " << seedPt
<< " since not in wall cell." << endl;
}
}
}
label nSeeds = returnReduce(particles.size(), sumOp<label>());
Info<< type() << " : 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;
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
{
FatalErrorIn("wallBoundedStreamLine::execute()")
<< "Cannot find field " << fields_[i] << endl
<< "Valid scalar fields are:"
<< mesh.names(volScalarField::typeName) << endl
<< "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)
{
FatalErrorIn("wallBoundedStreamLine::execute()")
<< "Cannot find field to move particles with : " << UName_
<< endl
<< "This field has to be present in the sampled fields "
<< fields_
<< " and in the objectRegistry." << endl
<< 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
wallBoundedStreamLineParticle::trackingData td
(
particles,
vsInterp,
vvInterp,
UIndex, // index of U in vvInterp
trackForward_, // track in +u direction?
isWallPatch, // which faces are to follow
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::wallBoundedStreamLine::wallBoundedStreamLine
(
const word& name,
const objectRegistry& obr,
const dictionary& dict,
const bool loadFromFiles
)
:
dict_(dict),
name_(name),
obr_(obr),
loadFromFiles_(loadFromFiles),
active_(true)
{
// Only active if a fvMesh is available
if (isA<fvMesh>(obr_))
{
read(dict_);
}
else
{
active_ = false;
WarningIn
(
"wallBoundedStreamLine::wallBoundedStreamLine\n"
"(\n"
"const word&,\n"
"const objectRegistry&,\n"
"const dictionary&,\n"
"const bool\n"
")"
) << "No fvMesh available, deactivating."
<< nl << endl;
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::wallBoundedStreamLine::~wallBoundedStreamLine()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::wallBoundedStreamLine::read(const dictionary& dict)
{
if (active_)
{
//dict_ = dict;
dict.lookup("fields") >> fields_;
if (dict.found("UName"))
{
dict.lookup("UName") >> UName_;
}
else
{
UName_ = "U";
if (dict.found("U"))
{
IOWarningIn
(
"wallBoundedStreamLine::read(const dictionary&)",
dict
) << "Using deprecated entry \"U\"."
<< " Please use \"UName\" instead."
<< endl;
dict.lookup("U") >> UName_;
}
}
if (findIndex(fields_, UName_) == -1)
{
FatalIOErrorIn
(
"wallBoundedStreamLine::read(const dictionary&)",
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)
{
FatalErrorIn(":wallBoundedStreamLine::read(const dictionary&)")
<< "Illegal value " << lifeTime_ << " for lifeTime"
<< exit(FatalError);
}
interpolationScheme_ = dict.lookupOrDefault
(
"interpolationScheme",
interpolationCellPoint<scalar>::typeName
);
//Info<< typeName << " using interpolation " << interpolationScheme_
// << endl;
cloudName_ = dict.lookupOrDefault<word>
(
"cloudName",
"wallBoundedStreamLine"
);
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"));
// Make sure that the mesh is trackable
if (debug)
{
// 1. positive volume decomposition tets
faceSet faces(mesh, "lowQualityTetFaces", mesh.nFaces()/100+1);
if
(
polyMeshTetDecomposition::checkFaceTets
(
mesh,
polyMeshTetDecomposition::minTetQuality,
true,
&faces
)
)
{
label nFaces = returnReduce(faces.size(), sumOp<label>());
FatalErrorIn("wallBoundedStreamLine::track()")
<< "Found " << nFaces
<<" faces with low quality or negative volume "
<< "decomposition tets. Writing to faceSet " << faces.name()
<< exit(FatalError);
}
// 2. all edges on a cell having two faces
EdgeMap<label> numFacesPerEdge;
forAll(mesh.cells(), cellI)
{
const cell& cFaces = mesh.cells()[cellI];
numFacesPerEdge.clear();
forAll(cFaces, cFaceI)
{
label faceI = cFaces[cFaceI];
const face& f = mesh.faces()[faceI];
forAll(f, fp)
{
const edge e(f[fp], f.nextLabel(fp));
EdgeMap<label>::iterator eFnd =
numFacesPerEdge.find(e);
if (eFnd != numFacesPerEdge.end())
{
eFnd()++;
}
else
{
numFacesPerEdge.insert(e, 1);
}
}
}
forAllConstIter(EdgeMap<label>, numFacesPerEdge, iter)
{
if (iter() != 2)
{
FatalErrorIn
(
"wallBoundedStreamLine::read(..)"
) << "problem cell:" << cellI
<< abort(FatalError);
}
}
}
}
}
}
void Foam::wallBoundedStreamLine::execute()
{}
void Foam::wallBoundedStreamLine::end()
{}
void Foam::wallBoundedStreamLine::write()
{
if (active_)
{
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.
mapDistribute::distribute
(
Pstream::scheduled,
distMap.schedule(),
distMap.constructSize(),
distMap.subMap(),
distMap.constructMap(),
allTracks_
);
// Distribute the scalars
forAll(allScalars_, scalarI)
{
mapDistribute::distribute
(
Pstream::scheduled,
distMap.schedule(),
distMap.constructSize(),
distMap.subMap(),
distMap.constructMap(),
allScalars_[scalarI]
);
}
// Distribute the vectors
forAll(allVectors_, vectorI)
{
mapDistribute::distribute
(
Pstream::scheduled,
distMap.schedule(),
distMap.constructSize(),
distMap.subMap(),
distMap.constructMap(),
allVectors_[vectorI]
);
}
}
label n = 0;
forAll(allTracks_, trackI)
{
n += allTracks_[trackI].size();
}
Info<< "Tracks:" << allTracks_.size()
<< " total samples:" << n << endl;
// Massage into form suitable for writers
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (Pstream::master() && allTracks_.size())
{
// Make output directory
fileName vtkPath
(
Pstream::parRun()
? runTime.path()/".."/"sets"/name()
: runTime.path()/"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_
)
);
//Info<< "Writing vector data to " << vtkFile << endl;
vectorFormatterPtr_().write
(
true, // writeTracks
tracks,
vectorNames_,
vectorValues,
OFstream(vtkFile)()
);
}
}
}
}
void Foam::wallBoundedStreamLine::updateMesh(const mapPolyMesh&)
{
read(dict_);
}
void Foam::wallBoundedStreamLine::movePoints(const pointField&)
{
// Moving mesh affects the search tree
read(dict_);
}
//void Foam::wallBoundedStreamLine::readUpdate
//(const polyMesh::readUpdateState state)
//{
// if (state != UNCHANGED)
// {
// read(dict_);
// }
//}
// ************************************************************************* //

View File

@ -0,0 +1,226 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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::wallBoundedStreamLine
Description
Generation of streamlines. Samples along track of passive particle.
SourceFiles
wallBoundedStreamLine.C
\*---------------------------------------------------------------------------*/
#ifndef wallBoundedStreamLine_H
#define wallBoundedStreamLine_H
#include "volFieldsFwd.H"
#include "pointFieldFwd.H"
#include "Switch.H"
#include "DynamicList.H"
#include "scalarList.H"
#include "vectorList.H"
#include "polyMesh.H"
#include "writer.H"
#include "indirectPrimitivePatch.H"
#include "tetIndices.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class objectRegistry;
class dictionary;
class mapPolyMesh;
class meshSearch;
class sampledSet;
/*---------------------------------------------------------------------------*\
Class wallBoundedStreamLine Declaration
\*---------------------------------------------------------------------------*/
class wallBoundedStreamLine
{
// Private data
//- Input dictionary
dictionary dict_;
//- Name of this set of field averages.
word name_;
//- Database this class is registered to
const objectRegistry& obr_;
//- Load fields from files (not from objectRegistry)
bool loadFromFiles_;
//- On/off switch
bool active_;
//- 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_;
//- 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 output writer
autoPtr<writer<scalar> > scalarFormatterPtr_;
autoPtr<writer<vector> > vectorFormatterPtr_;
// Generated data
//- All tracks. Per particle the points it passed through
DynamicList<List<point> > allTracks_;
//- Per scalarField, per particle, the sampled value.
List<DynamicList<scalarList> > allScalars_;
//- Per scalarField, per particle, the sampled value.
List<DynamicList<vectorList> > allVectors_;
//- Construct patch out of all wall patch faces
autoPtr<indirectPrimitivePatch> wallPatch() const;
//- Find wall tet on cell
tetIndices findNearestTet
(
const PackedBoolList& isWallPatch,
const point& seedPt,
const label cellI
) const;
//- Do all seeding and tracking
void track();
//- Disallow default bitwise copy construct
wallBoundedStreamLine(const wallBoundedStreamLine&);
//- Disallow default bitwise assignment
void operator=(const wallBoundedStreamLine&);
public:
//- Runtime type information
TypeName("wallBoundedStreamLine");
// Constructors
//- Construct for given objectRegistry and dictionary.
// Allow the possibility to load fields from files
wallBoundedStreamLine
(
const word& name,
const objectRegistry&,
const dictionary&,
const bool loadFromFiles = false
);
//- Destructor
virtual ~wallBoundedStreamLine();
// Member Functions
//- Return name of the set of field averages
virtual const word& name() const
{
return name_;
}
//- 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();
//- Calculate the field average data and write
virtual void write();
//- Update for changes of mesh
virtual void updateMesh(const mapPolyMesh&);
//- Update for mesh point-motion
virtual void movePoints(const pointField&);
////- Update for changes of mesh due to readUpdate
//virtual void readUpdate(const polyMesh::readUpdateState state);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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 "wallBoundedStreamLineFunctionObject.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineNamedTemplateTypeNameAndDebug(wallBoundedStreamLineFunctionObject, 0);
addToRunTimeSelectionTable
(
functionObject,
wallBoundedStreamLineFunctionObject,
dictionary
);
}
// ************************************************************************* //

View File

@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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/>.
Typedef
Foam::wallBoundedStreamLineFunctionObject
Description
FunctionObject wrapper around wallBoundedStreamLines
to allow them to be created via
the functions entry within controlDict.
SourceFiles
wallBoundedStreamLineFunctionObject.C
\*---------------------------------------------------------------------------*/
#ifndef wallBoundedStreamLineFunctionObject_H
#define wallBoundedStreamLineFunctionObject_H
#include "wallBoundedStreamLine.H"
#include "OutputFilterFunctionObject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef OutputFilterFunctionObject<wallBoundedStreamLine>
wallBoundedStreamLineFunctionObject;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,368 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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::wallBoundedStreamLineParticle
Description
Particle class that samples fields as it passes through. Used in streamline
calculation.
SourceFiles
wallBoundedStreamLineParticle.C
\*---------------------------------------------------------------------------*/
#ifndef wallBoundedStreamLineParticle_H
#define wallBoundedStreamLineParticle_H
#include "particle.H"
#include "autoPtr.H"
#include "interpolation.H"
#include "vectorList.H"
#include "InfoProxy.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class wallBoundedStreamLineParticleCloud;
/*---------------------------------------------------------------------------*\
Class wallBoundedStreamLineParticle Declaration
\*---------------------------------------------------------------------------*/
class wallBoundedStreamLineParticle
:
public particle
{
public:
//- Class used to pass tracking data to the trackToFace function
class trackingData
:
public particle::TrackingData<Cloud<wallBoundedStreamLineParticle> >
{
public:
const PtrList<interpolation<scalar> >& vsInterp_;
const PtrList<interpolation<vector> >& vvInterp_;
const label UIndex_;
const bool trackForward_;
const PackedBoolList& isWallPatch_;
DynamicList<vectorList>& allPositions_;
List<DynamicList<scalarList> >& allScalars_;
List<DynamicList<vectorList> >& allVectors_;
// Constructors
trackingData
(
Cloud<wallBoundedStreamLineParticle>& cloud,
const PtrList<interpolation<scalar> >& vsInterp,
const PtrList<interpolation<vector> >& vvInterp,
const label UIndex,
const bool trackForward,
const PackedBoolList& isWallPatch,
DynamicList<List<point> >& allPositions,
List<DynamicList<scalarList> >& allScalars,
List<DynamicList<vectorList> >& allVectors
)
:
particle::TrackingData<Cloud<wallBoundedStreamLineParticle> >
(
cloud
),
vsInterp_(vsInterp),
vvInterp_(vvInterp),
UIndex_(UIndex),
trackForward_(trackForward),
isWallPatch_(isWallPatch),
allPositions_(allPositions),
allScalars_(allScalars),
allVectors_(allVectors)
{}
};
private:
// Private data
//- Particle is on mesh edge:
// const face& f = mesh.faces()[tetFace()]
// const edge e(f[meshEdgeStart_], f.nextLabel(meshEdgeStart_));
// Note that this real edge
// is also one of the edges of the face-triangle (from
// tetFace()+tetPt()).
label meshEdgeStart_;
//- Particle is on diagonal edge:
// const face& f = mesh.faces()[tetFace()]
// label faceBasePtI = mesh.tetBasePtIs()[faceI];
// label diagPtI = (faceBasePtI+diagEdge_)%f.size();
// const edge e(f[faceBasePtI], f[diagPtI]);
label diagEdge_;
//- 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
//- Construct current edge
edge currentEdge() const;
//- Check if inside current tet
//void checkInside() const;
//- Check if on current edge
//void checkOnEdge() const;
//- Check if point on triangle
//void checkOnTriangle(const point&) const;
//- Cross mesh edge into different face on same cell
void crossEdgeConnectedFace(const edge& meshEdge);
//- Cross diagonal edge into different triangle on same face,cell
void crossDiagonalEdge();
//- Track through single triangle
scalar trackFaceTri(const vector& endPosition, label& minEdgeI);
//- Do all patch interaction
void patchInteraction(trackingData& td, const scalar trackFraction);
//- Is current triangle in the track direction
bool isTriAlongTrack(const point& endPosition) const;
//- Equivalent of trackToFace
scalar trackToEdge
(
trackingData& td,
const vector& endPosition
);
//- Interpolate all quantities; return interpolated velocity.
vector interpolateFields
(
const trackingData&,
const point&,
const label cellI,
const label faceI
);
//- Interpolate all quantities, return updated velocity.
vector sample(trackingData& td);
public:
// Constructors
//- Construct from components
wallBoundedStreamLineParticle
(
const polyMesh& c,
const vector& position,
const label cellI,
const label tetFaceI,
const label tetPtI,
const label meshEdgeStart,
const label diagEdge,
const label lifeTime
);
//- Construct from Istream
wallBoundedStreamLineParticle
(
const polyMesh& c,
Istream& is,
bool readFields = true
);
//- Construct copy
wallBoundedStreamLineParticle(const wallBoundedStreamLineParticle& p);
//- Construct and return a clone
autoPtr<particle> clone() const
{
return autoPtr<particle>(new wallBoundedStreamLineParticle(*this));
}
//- Factory class to read-construct particles used for
// parallel transfer
class iNew
{
const polyMesh& mesh_;
public:
iNew(const polyMesh& mesh)
:
mesh_(mesh)
{}
autoPtr<wallBoundedStreamLineParticle> operator()
(
Istream& is
) const
{
return autoPtr<wallBoundedStreamLineParticle>
(
new wallBoundedStreamLineParticle(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
// symmetryPlane
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
);
// Info
//- Return info proxy.
// Used to print particle information to a stream
InfoProxy<wallBoundedStreamLineParticle> info() const
{
return *this;
}
// I-O
//- Read
static void readFields(Cloud<wallBoundedStreamLineParticle>&);
//- Write
static void writeFields
(
const Cloud<wallBoundedStreamLineParticle>&
);
// Ostream Operator
friend Ostream& operator<<
(
Ostream&,
const wallBoundedStreamLineParticle&
);
friend Ostream& operator<<
(
Ostream&,
const InfoProxy<wallBoundedStreamLineParticle>&
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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 "wallBoundedStreamLineParticleCloud.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTemplateTypeNameAndDebug(Cloud<wallBoundedStreamLineParticle>, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::wallBoundedStreamLineParticleCloud::wallBoundedStreamLineParticleCloud
(
const polyMesh& mesh,
const word& cloudName,
bool readFields
)
:
Cloud<wallBoundedStreamLineParticle>(mesh, cloudName, false)
{
if (readFields)
{
wallBoundedStreamLineParticle::readFields(*this);
}
}
Foam::wallBoundedStreamLineParticleCloud::wallBoundedStreamLineParticleCloud
(
const polyMesh& mesh,
const word& cloudName,
const IDLList<wallBoundedStreamLineParticle>& particles
)
:
Cloud<wallBoundedStreamLineParticle>(mesh, cloudName, particles)
{}
// ************************************************************************* //

View File

@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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::wallBoundedStreamLineParticleCloud
Description
A Cloud of streamLine particles
SourceFiles
streamLineCloud.C
\*---------------------------------------------------------------------------*/
#ifndef streamLineCloud_H
#define streamLineCloud_H
#include "Cloud.H"
#include "wallBoundedStreamLineParticle.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class streamLineCloud Declaration
\*---------------------------------------------------------------------------*/
class wallBoundedStreamLineParticleCloud
:
public Cloud<wallBoundedStreamLineParticle>
{
// Private Member Functions
//- Disallow default bitwise copy construct
wallBoundedStreamLineParticleCloud
(
const wallBoundedStreamLineParticleCloud&
);
//- Disallow default bitwise assignment
void operator=(const wallBoundedStreamLineParticleCloud&);
public:
//- Type of parcel the cloud was instantiated for
typedef wallBoundedStreamLineParticle parcelType;
// Constructors
//- Construct given mesh
wallBoundedStreamLineParticleCloud
(
const polyMesh&,
const word& cloudName = "defaultCloud",
bool readFields = true
);
//- Construct from mesh, cloud name, and a list of particles
wallBoundedStreamLineParticleCloud
(
const polyMesh& mesh,
const word& cloudName,
const IDLList<wallBoundedStreamLineParticle>& particles
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //