Files
OpenFOAM-12/src/sampling/sampledSet/face/faceOnlySet.C
Will Bainbridge adffa0f33d Lagrangian: Enabled tracking through ACMI patches and minor code improvements
Particle collisions with ACMI patches are now handled. The hit detects
whether the location is within the overlap or the coupled region and
recurses, calling the hit routine appropriate for the region.

The low level tracking methods are now more consistently named. There is
now a distinction between tracking to a face and hitting it. Function
object side effects have been moved out of the base layer and into the
parcels on which they are meaningful.
2017-08-10 15:31:24 +01:00

379 lines
9.6 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 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 "faceOnlySet.H"
#include "meshSearch.H"
#include "DynamicList.H"
#include "polyMesh.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(faceOnlySet, 0);
addToRunTimeSelectionTable(sampledSet, faceOnlySet, word);
const scalar faceOnlySet::tol = 1e-6;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::faceOnlySet::trackToBoundary
(
passiveParticleCloud& particleCloud,
passiveParticle& singleParticle,
const scalar smallDist,
DynamicList<point>& samplingPts,
DynamicList<label>& samplingCells,
DynamicList<label>& samplingFaces,
DynamicList<scalar>& samplingCurveDist
) const
{
particle::TrackingData<passiveParticleCloud> trackData(particleCloud);
point trackPt = singleParticle.position();
while(true)
{
point oldPoint = trackPt;
singleParticle.trackToAndHitFace(end_ - start_, 0, trackData);
trackPt = singleParticle.position();
if (singleParticle.face() != -1 && mag(oldPoint - trackPt) > smallDist)
{
// Reached face. Sample.
samplingPts.append(trackPt);
samplingCells.append(singleParticle.cell());
samplingFaces.append(singleParticle.face());
samplingCurveDist.append(mag(trackPt - start_));
}
if (mag(trackPt - end_) < smallDist)
{
// End reached
return false;
}
else if (singleParticle.onBoundaryFace())
{
// Boundary reached
return true;
}
}
}
void Foam::faceOnlySet::calcSamples
(
DynamicList<point>& samplingPts,
DynamicList<label>& samplingCells,
DynamicList<label>& samplingFaces,
DynamicList<label>& samplingSegments,
DynamicList<scalar>& samplingCurveDist
) const
{
// Distance vector between sampling points
if (mag(end_ - start_) < SMALL)
{
FatalErrorInFunction
<< "Incorrect sample specification :"
<< " start equals end point." << endl
<< " start:" << start_
<< " end:" << end_
<< exit(FatalError);
}
const vector offset = (end_ - start_);
const vector normOffset = offset/mag(offset);
const vector smallVec = tol*offset;
const scalar smallDist = mag(smallVec);
// Force calculation of cloud addressing on all processors
const bool oldMoving = const_cast<polyMesh&>(mesh()).moving(false);
passiveParticleCloud particleCloud(mesh());
// Get all boundary intersections
List<pointIndexHit> bHits = searchEngine().intersections
(
start_ - smallVec,
end_ + smallVec
);
point bPoint(GREAT, GREAT, GREAT);
label bFacei = -1;
if (bHits.size())
{
bPoint = bHits[0].hitPoint();
bFacei = bHits[0].index();
}
// Get first tracking point. Use bPoint, bFacei if provided.
point trackPt;
label trackCelli = -1;
label trackFacei = -1;
// Pout<< "before getTrackingPoint : bPoint:" << bPoint
// << " bFacei:" << bFacei << endl;
getTrackingPoint
(
start_,
bPoint,
bFacei,
smallDist,
trackPt,
trackCelli,
trackFacei
);
// Pout<< "after getTrackingPoint : "
// << " trackPt:" << trackPt
// << " trackCelli:" << trackCelli
// << " trackFacei:" << trackFacei
// << endl;
if (trackCelli == -1)
{
// Line start_ - end_ does not intersect domain at all.
// (or is along edge)
// Set points and cell/face labels to empty lists
// Pout<< "calcSamples : Both start_ and end_ outside domain"
// << endl;
const_cast<polyMesh&>(mesh()).moving(oldMoving);
return;
}
if (trackFacei == -1)
{
// No boundary face. Check for nearish internal face
trackFacei = findNearFace(trackCelli, trackPt, smallDist);
}
// Pout<< "calcSamples : got first point to track from :"
// << " trackPt:" << trackPt
// << " trackCell:" << trackCelli
// << " trackFace:" << trackFacei
// << endl;
//
// Track until hit end of all boundary intersections
//
// current segment number
label segmentI = 0;
// starting index of current segment in samplePts
label startSegmentI = 0;
// index in bHits; current boundary intersection
label bHitI = 1;
while (true)
{
if (trackFacei != -1)
{
// Pout<< "trackPt:" << trackPt << " on face so use." << endl;
samplingPts.append(trackPt);
samplingCells.append(trackCelli);
samplingFaces.append(trackFacei);
samplingCurveDist.append(mag(trackPt - start_));
}
// Initialize tracking starting from trackPt
passiveParticle singleParticle
(
mesh(),
trackPt,
trackCelli
);
bool reachedBoundary = trackToBoundary
(
particleCloud,
singleParticle,
smallDist,
samplingPts,
samplingCells,
samplingFaces,
samplingCurveDist
);
// Fill sampleSegments
for (label i = samplingPts.size() - 1; i >= startSegmentI; --i)
{
samplingSegments.append(segmentI);
}
if (!reachedBoundary)
{
// Pout<< "calcSamples : Reached end of samples: "
// << " samplePt now:" << singleParticle.position()
// << endl;
break;
}
bool foundValidB = false;
while (bHitI < bHits.size())
{
scalar dist =
(bHits[bHitI].hitPoint() - singleParticle.position())
& normOffset;
// Pout<< "Finding next boundary : "
// << "bPoint:" << bHits[bHitI].hitPoint()
// << " tracking:" << singleParticle.position()
// << " dist:" << dist
// << endl;
if (dist > smallDist)
{
// Hit-point is past tracking position
foundValidB = true;
break;
}
else
{
bHitI++;
}
}
if (!foundValidB || bHitI == bHits.size() - 1)
{
// No valid boundary intersection found beyond tracking position
break;
}
// Update starting point for tracking
trackFacei = bHits[bHitI].index();
trackPt = pushIn(bHits[bHitI].hitPoint(), trackFacei);
trackCelli = getBoundaryCell(trackFacei);
segmentI++;
startSegmentI = samplingPts.size();
}
const_cast<polyMesh&>(mesh()).moving(oldMoving);
}
void Foam::faceOnlySet::genSamples()
{
// Storage for sample points
DynamicList<point> samplingPts;
DynamicList<label> samplingCells;
DynamicList<label> samplingFaces;
DynamicList<label> samplingSegments;
DynamicList<scalar> samplingCurveDist;
calcSamples
(
samplingPts,
samplingCells,
samplingFaces,
samplingSegments,
samplingCurveDist
);
samplingPts.shrink();
samplingCells.shrink();
samplingFaces.shrink();
samplingSegments.shrink();
samplingCurveDist.shrink();
// Copy into *this
setSamples
(
samplingPts,
samplingCells,
samplingFaces,
samplingSegments,
samplingCurveDist
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faceOnlySet::faceOnlySet
(
const word& name,
const polyMesh& mesh,
const meshSearch& searchEngine,
const word& axis,
const point& start,
const point& end
)
:
sampledSet(name, mesh, searchEngine, axis),
start_(start),
end_(end)
{
genSamples();
if (debug)
{
write(Info);
}
}
Foam::faceOnlySet::faceOnlySet
(
const word& name,
const polyMesh& mesh,
const meshSearch& searchEngine,
const dictionary& dict
)
:
sampledSet(name, mesh, searchEngine, dict),
start_(dict.lookup("start")),
end_(dict.lookup("end"))
{
genSamples();
if (debug)
{
write(Info);
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::faceOnlySet::~faceOnlySet()
{}
// ************************************************************************* //