Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
506 lines (420 sloc) 13.9 KB
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2018 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 "surfaceToCell.H"
#include "polyMesh.H"
#include "meshSearch.H"
#include "triSurface.H"
#include "triSurfaceSearch.H"
#include "cellClassification.H"
#include "cpuTime.H"
#include "demandDrivenData.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(surfaceToCell, 0);
addToRunTimeSelectionTable(topoSetSource, surfaceToCell, word);
addToRunTimeSelectionTable(topoSetSource, surfaceToCell, istream);
}
Foam::topoSetSource::addToUsageTable Foam::surfaceToCell::usage_
(
surfaceToCell::typeName,
"\n Usage: surfaceToCell"
"<surface> <outsidePoints> <cut> <inside> <outside> <near> <curvature>\n\n"
" <surface> name of triSurface\n"
" <outsidePoints> list of points that define outside\n"
" <cut> boolean whether to include cells cut by surface\n"
" <inside> ,, ,, inside surface\n"
" <outside> ,, ,, outside surface\n"
" <near> scalar; include cells with centre <= near to surface\n"
" <curvature> scalar; include cells close to strong curvature"
" on surface\n"
" (curvature defined as difference in surface normal at nearest"
" point on surface for each vertex of cell)\n\n"
);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::label Foam::surfaceToCell::getNearest
(
const triSurfaceSearch& querySurf,
const label pointi,
const point& pt,
const vector& span,
Map<label>& cache
)
{
Map<label>::const_iterator iter = cache.find(pointi);
if (iter != cache.end())
{
// Found cached answer
return iter();
}
else
{
pointIndexHit inter = querySurf.nearest(pt, span);
// Triangle label (can be -1)
label triI = inter.index();
// Store triangle on point
cache.insert(pointi, triI);
return triI;
}
}
bool Foam::surfaceToCell::differingPointNormals
(
const triSurfaceSearch& querySurf,
const vector& span, // Current search span
const label celli,
const label cellTriI, // Nearest (to cell centre) surface triangle
Map<label>& pointToNearest // Cache for nearest triangle to point
) const
{
const triSurface& surf = querySurf.surface();
const vectorField& normals = surf.faceNormals();
const faceList& faces = mesh().faces();
const pointField& points = mesh().points();
const labelList& cFaces = mesh().cells()[celli];
forAll(cFaces, cFacei)
{
const face& f = faces[cFaces[cFacei]];
forAll(f, fp)
{
label pointi = f[fp];
label pointTriI =
getNearest
(
querySurf,
pointi,
points[pointi],
span,
pointToNearest
);
if (pointTriI != -1 && pointTriI != cellTriI)
{
scalar cosAngle = normals[pointTriI] & normals[cellTriI];
if (cosAngle < 0.9)
{
return true;
}
}
}
}
return false;
}
void Foam::surfaceToCell::combine(topoSet& set, const bool add) const
{
cpuTime timer;
if (useSurfaceOrientation_ && (includeInside_ || includeOutside_))
{
const meshSearch queryMesh(mesh_);
//- Calculate for each searchPoint inside/outside status.
boolList isInside(querySurf().calcInside(mesh_.cellCentres()));
Info<< " Marked inside/outside using surface orientation in = "
<< timer.cpuTimeIncrement() << " s" << endl << endl;
forAll(isInside, celli)
{
if (isInside[celli] && includeInside_)
{
addOrDelete(set, celli, add);
}
else if (!isInside[celli] && includeOutside_)
{
addOrDelete(set, celli, add);
}
}
}
else if (includeCut_ || includeInside_ || includeOutside_)
{
//
// Cut cells with surface and classify cells
//
// Construct search engine on mesh
const meshSearch queryMesh(mesh_);
// Check all 'outside' points
forAll(outsidePoints_, outsideI)
{
const point& outsidePoint = outsidePoints_[outsideI];
// Find cell point is in. Linear search.
label celli = queryMesh.findCell(outsidePoint, -1, false);
if (returnReduce(celli, maxOp<label>()) == -1)
{
FatalErrorInFunction
<< "outsidePoint " << outsidePoint
<< " is not inside any cell"
<< exit(FatalError);
}
}
// Cut faces with surface and classify cells
cellClassification cellType
(
mesh_,
queryMesh,
querySurf(),
outsidePoints_
);
Info<< " Marked inside/outside using surface intersection in = "
<< timer.cpuTimeIncrement() << " s" << endl << endl;
//- Add/remove cells using set
forAll(cellType, celli)
{
label cType = cellType[celli];
if
(
(
includeCut_
&& (cType == cellClassification::CUT)
)
|| (
includeInside_
&& (cType == cellClassification::INSIDE)
)
|| (
includeOutside_
&& (cType == cellClassification::OUTSIDE)
)
)
{
addOrDelete(set, celli, add);
}
}
}
if (nearDist_ > 0)
{
//
// Determine distance to surface
//
const pointField& ctrs = mesh_.cellCentres();
// Box dimensions to search in octree.
const vector span(nearDist_, nearDist_, nearDist_);
if (curvature_ < -1)
{
Info<< " Selecting cells with cellCentre closer than "
<< nearDist_ << " to surface" << endl;
// No need to test curvature. Insert near cells into set.
forAll(ctrs, celli)
{
const point& c = ctrs[celli];
pointIndexHit inter = querySurf().nearest(c, span);
if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
{
addOrDelete(set, celli, add);
}
}
Info<< " Determined nearest surface point in = "
<< timer.cpuTimeIncrement() << " s" << endl << endl;
}
else
{
// Test near cells for curvature
Info<< " Selecting cells with cellCentre closer than "
<< nearDist_ << " to surface and curvature factor"
<< " less than " << curvature_ << endl;
// Cache for nearest surface triangle for a point
Map<label> pointToNearest(mesh_.nCells()/10);
forAll(ctrs, celli)
{
const point& c = ctrs[celli];
pointIndexHit inter = querySurf().nearest(c, span);
if (inter.hit() && (mag(inter.hitPoint() - c) < nearDist_))
{
if
(
differingPointNormals
(
querySurf(),
span,
celli,
inter.index(), // nearest surface triangle
pointToNearest
)
)
{
addOrDelete(set, celli, add);
}
}
}
Info<< " Determined nearest surface point in = "
<< timer.cpuTimeIncrement() << " s" << endl << endl;
}
}
}
void Foam::surfaceToCell::checkSettings() const
{
if
(
(nearDist_ < 0)
&& (curvature_ < -1)
&& (
(includeCut_ && includeInside_ && includeOutside_)
|| (!includeCut_ && !includeInside_ && !includeOutside_)
)
)
{
FatalErrorInFunction
<< "Illegal include cell specification."
<< " Result would be either all or no cells." << endl
<< "Please set one of includeCut, includeInside, includeOutside"
<< " to true, set nearDistance to a value > 0"
<< " or set curvature to a value -1 .. 1."
<< exit(FatalError);
}
if (useSurfaceOrientation_ && includeCut_)
{
FatalErrorInFunction
<< "Illegal include cell specification."
<< " You cannot specify both 'useSurfaceOrientation'"
<< " and 'includeCut'"
<< " since 'includeCut' specifies a topological split"
<< exit(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::surfaceToCell::surfaceToCell
(
const polyMesh& mesh,
const fileName& surfName,
const pointField& outsidePoints,
const bool includeCut,
const bool includeInside,
const bool includeOutside,
const bool useSurfaceOrientation,
const scalar nearDist,
const scalar curvature
)
:
topoSetSource(mesh),
surfName_(surfName),
outsidePoints_(outsidePoints),
includeCut_(includeCut),
includeInside_(includeInside),
includeOutside_(includeOutside),
useSurfaceOrientation_(useSurfaceOrientation),
nearDist_(nearDist),
curvature_(curvature),
surfPtr_(new triSurface(surfName_)),
querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
IOwnPtrs_(true)
{
checkSettings();
}
Foam::surfaceToCell::surfaceToCell
(
const polyMesh& mesh,
const fileName& surfName,
const triSurface& surf,
const triSurfaceSearch& querySurf,
const pointField& outsidePoints,
const bool includeCut,
const bool includeInside,
const bool includeOutside,
const bool useSurfaceOrientation,
const scalar nearDist,
const scalar curvature
)
:
topoSetSource(mesh),
surfName_(surfName),
outsidePoints_(outsidePoints),
includeCut_(includeCut),
includeInside_(includeInside),
includeOutside_(includeOutside),
useSurfaceOrientation_(useSurfaceOrientation),
nearDist_(nearDist),
curvature_(curvature),
surfPtr_(&surf),
querySurfPtr_(&querySurf),
IOwnPtrs_(false)
{
checkSettings();
}
Foam::surfaceToCell::surfaceToCell
(
const polyMesh& mesh,
const dictionary& dict
)
:
topoSetSource(mesh),
surfName_(fileName(dict.lookup("file")).expand()),
outsidePoints_(dict.lookup("outsidePoints")),
includeCut_(readBool(dict.lookup("includeCut"))),
includeInside_(readBool(dict.lookup("includeInside"))),
includeOutside_(readBool(dict.lookup("includeOutside"))),
useSurfaceOrientation_
(
dict.lookupOrDefault<bool>("useSurfaceOrientation", false)
),
nearDist_(readScalar(dict.lookup("nearDistance"))),
curvature_(readScalar(dict.lookup("curvature"))),
surfPtr_(new triSurface(surfName_)),
querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
IOwnPtrs_(true)
{
checkSettings();
}
Foam::surfaceToCell::surfaceToCell
(
const polyMesh& mesh,
Istream& is
)
:
topoSetSource(mesh),
surfName_(checkIs(is)),
outsidePoints_(checkIs(is)),
includeCut_(readBool(checkIs(is))),
includeInside_(readBool(checkIs(is))),
includeOutside_(readBool(checkIs(is))),
useSurfaceOrientation_(false),
nearDist_(readScalar(checkIs(is))),
curvature_(readScalar(checkIs(is))),
surfPtr_(new triSurface(surfName_)),
querySurfPtr_(new triSurfaceSearch(*surfPtr_)),
IOwnPtrs_(true)
{
checkSettings();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::surfaceToCell::~surfaceToCell()
{
if (IOwnPtrs_)
{
deleteDemandDrivenData(surfPtr_);
deleteDemandDrivenData(querySurfPtr_);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::surfaceToCell::applyToSet
(
const topoSetSource::setAction action,
topoSet& set
) const
{
if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
{
Info<< " Adding cells in relation to surface " << surfName_
<< " ..." << endl;
combine(set, true);
}
else if (action == topoSetSource::DELETE)
{
Info<< " Removing cells in relation to surface " << surfName_
<< " ..." << endl;
combine(set, false);
}
}
// ************************************************************************* //
You can’t perform that action at this time.