OpenFOAM-5.x/src/meshTools/surfaceSets/surfaceSets.C
2014-12-10 22:40:10 +00:00

622 lines
16 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 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 "surfaceSets.H"
#include "polyMesh.H"
#include "triSurface.H"
#include "triSurfaceSearch.H"
#include "pointSet.H"
#include "cellSet.H"
#include "surfaceToCell.H"
#include "cellToPoint.H"
#include "cellToCell.H"
#include "pointToCell.H"
#include "meshSearch.H"
#include "cellClassification.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
//Foam::scalar Foam::surfaceSets::minEdgeLen
//(
// const primitiveMesh& mesh,
// const label pointI
//)
//{
// const edgeList& edges = mesh.edges();
//
// const pointField& points = mesh.points();
//
// const labelList& pEdges = mesh.pointEdges()[pointI];
//
// scalar minLen = GREAT;
//
// forAll(pEdges, i)
// {
// minLen = min(minLen, edges[pEdges[i]].mag(points));
// }
// return minLen;
//}
//
//
//// Returns true if cell uses at least one selected point
//bool Foam::surfaceSets::usesPoint
//(
// const primitiveMesh& mesh,
// const boolList& selectedPoint,
// const label cellI
//)
//{
// const labelList& cFaces = mesh.cells()[cellI];
//
// forAll(cFaces, cFaceI)
// {
// label faceI = cFaces[cFaceI];
//
// const face& f = mesh.faces()[faceI];
//
// forAll(f, fp)
// {
// if (selectedPoint[f[fp]])
// {
// return true;
// }
// }
// }
// return false;
//}
//// Remove cells in allCells which are connected to other cells in allCells
//// by outside vertices only. Since these outside vertices will be moved onto
//// a surface they might result in flat cells.
//Foam::label Foam::surfaceSets::removeHangingCells
//(
// const primitiveMesh& mesh,
// const triSurfaceSearch& querySurf,
// labelHashSet& internalCells
//)
//{
// const pointField& points = mesh.points();
// const cellList& cells = mesh.cells();
// const faceList& faces = mesh.faces();
//
// // Determine cells that have all points on the boundary.
// labelHashSet flatCandidates(getHangingCells(mesh, internalCells));
//
// // All boundary points will become visible after subsetting and will be
// // snapped
// // to surface. Calculate new volume for cells using only these points and
// // check if it does not become too small.
//
// // Get points used by flatCandidates.
// labelHashSet outsidePoints(flatCandidates.size());
//
// // Snap outside points to surface
// pointField newPoints(points);
//
// forAllConstIter(labelHashSet, flatCandidates, iter)
// {
// const cell& cFaces = cells[iter.key()];
//
// forAll(cFaces, cFaceI)
// {
// const face& f = faces[cFaces[cFaceI]];
//
// forAll(f, fp)
// {
// label pointI = f[fp];
//
// if (outsidePoints.insert(pointI))
// {
// // Calculate new position for this outside point
// tmp<pointField> tnearest =
// querySurf.calcNearest(pointField(1, points[pointI]));
// newPoints[pointI] = tnearest()[0];
// }
// }
// }
// }
//
//
// // Calculate new volume for mixed cells
// label nRemoved = 0;
// forAllConstIter(labelHashSet, flatCandidates, iter)
// {
// label cellI = iter.key();
//
// const cell& cll = cells[cellI];
//
// scalar newVol = cll.mag(newPoints, faces);
// scalar oldVol = mesh.cellVolumes()[cellI];
//
// if (newVol < 0.1 * oldVol)
// {
// internalCells.erase(cellI);
// nRemoved++;
// }
// }
//
// return nRemoved;
//}
//// Select all points out of pointSet where the distance to the surface
//// is less than a factor times a local length scale (minimum length of
//// connected edges)
//void Foam::surfaceSets::getNearPoints
//(
// const primitiveMesh& mesh,
// const triSurface&,
// const triSurfaceSearch& querySurf,
// const scalar edgeFactor,
// const pointSet& candidateSet,
// pointSet& nearPointSet
//)
//{
// if (edgeFactor <= 0)
// {
// return;
// }
//
// labelList candidates(candidateSet.toc());
//
// pointField candidatePoints(candidates.size());
// forAll(candidates, i)
// {
// candidatePoints[i] = mesh.points()[candidates[i]];
// }
//
// tmp<pointField> tnearest = querySurf.calcNearest(candidatePoints);
// const pointField& nearest = tnearest();
//
// const pointField& points = mesh.points();
//
// forAll(candidates, i)
// {
// label pointI = candidates[i];
//
// scalar minLen = minEdgeLen(mesh, pointI);
//
// scalar dist = mag(nearest[i] - points[pointI]);
//
// if (dist < edgeFactor * minLen)
// {
// nearPointSet.insert(pointI);
// }
// }
//}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::surfaceSets::getSurfaceSets
(
const polyMesh& mesh,
const fileName&,
const triSurface&,
const triSurfaceSearch& querySurf,
const pointField& outsidePts,
const label nCutLayers,
labelHashSet& inside,
labelHashSet& outside,
labelHashSet& cut
)
{
// Construct search engine on mesh
meshSearch queryMesh(mesh);
// Cut faces with surface and classify cells
cellClassification cellType
(
mesh,
queryMesh,
querySurf,
outsidePts
);
if (nCutLayers > 0)
{
// Trim cutCells so they are max nCutLayers away (as seen in point-cell
// walk) from outside cells.
cellType.trimCutCells
(
nCutLayers,
cellClassification::OUTSIDE,
cellClassification::INSIDE
);
}
forAll(cellType, cellI)
{
label cType = cellType[cellI];
if (cType == cellClassification::CUT)
{
cut.insert(cellI);
}
else if (cType == cellClassification::INSIDE)
{
inside.insert(cellI);
}
else if (cType == cellClassification::OUTSIDE)
{
outside.insert(cellI);
}
}
}
Foam::labelHashSet Foam::surfaceSets::getHangingCells
(
const primitiveMesh& mesh,
const labelHashSet& internalCells
)
{
const cellList& cells = mesh.cells();
const faceList& faces = mesh.faces();
// Divide points into
// -referenced by internal only
// -referenced by outside only
// -mixed
List<pointStatus> pointSide(mesh.nPoints(), NOTSET);
for (label cellI = 0; cellI < mesh.nCells(); cellI++)
{
if (internalCells.found(cellI))
{
// Inside cell. Mark all vertices seen from this cell.
const labelList& cFaces = cells[cellI];
forAll(cFaces, cFaceI)
{
const face& f = faces[cFaces[cFaceI]];
forAll(f, fp)
{
label pointI = f[fp];
if (pointSide[pointI] == NOTSET)
{
pointSide[pointI] = INSIDE;
}
else if (pointSide[pointI] == OUTSIDE)
{
pointSide[pointI] = MIXED;
}
else
{
// mixed or inside stay same
}
}
}
}
else
{
// Outside cell
const labelList& cFaces = cells[cellI];
forAll(cFaces, cFaceI)
{
const face& f = faces[cFaces[cFaceI]];
forAll(f, fp)
{
label pointI = f[fp];
if (pointSide[pointI] == NOTSET)
{
pointSide[pointI] = OUTSIDE;
}
else if (pointSide[pointI] == INSIDE)
{
pointSide[pointI] = MIXED;
}
else
{
// mixed or outside stay same
}
}
}
}
}
//OFstream mixedStr("mixed.obj");
//
//forAll(pointSide, pointI)
//{
// if (pointSide[pointI] == MIXED)
// {
// const point& pt = points[pointI];
//
// mixedStr << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
// << endl;
// }
//}
// Determine cells using mixed points only
labelHashSet mixedOnlyCells(internalCells.size());
forAllConstIter(labelHashSet, internalCells, iter)
{
const label cellI = iter.key();
const cell& cFaces = cells[cellI];
label usesMixedOnly = true;
forAll(cFaces, i)
{
const face& f = faces[cFaces[i]];
forAll(f, fp)
{
if (pointSide[f[fp]] != MIXED)
{
usesMixedOnly = false;
break;
}
}
if (!usesMixedOnly)
{
break;
}
}
if (usesMixedOnly)
{
mixedOnlyCells.insert(cellI);
}
}
return mixedOnlyCells;
}
//void Foam::surfaceSets::writeSurfaceSets
//(
// const polyMesh& mesh,
// const fileName& surfName,
// const triSurface& surf,
// const triSurfaceSearch& querySurf,
// const pointField& outsidePts,
// const scalar edgeFactor
//)
//{
// // Cellsets for inside/outside determination
// cellSet rawInside(mesh, "rawInside", mesh.nCells()/10);
// cellSet rawOutside(mesh, "rawOutside", mesh.nCells()/10);
// cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
//
// // Get inside/outside/cut cells
// getSurfaceSets
// (
// mesh,
// surfName,
// surf,
// querySurf,
// outsidePts,
//
// rawInside,
// rawOutside,
// cutCells
// );
//
//
// Pout<< "rawInside:" << rawInside.size() << endl;
//
// label nRemoved;
// do
// {
// nRemoved = removeHangingCells(mesh, querySurf, rawInside);
//
// Pout<< nl
// << "Removed " << nRemoved
// << " rawInside cells that have all their points on the outside"
// << endl;
// }
// while (nRemoved != 0);
//
// Pout<< "Writing inside cells (" << rawInside.size() << ") to cellSet "
// << rawInside.instance()/rawInside.local()/rawInside.name()
// << endl << endl;
// rawInside.write();
//
//
//
// // Select outside cells
// surfaceToCell outsideSource
// (
// mesh,
// surfName,
// surf,
// querySurf,
// outsidePts,
// false, // includeCut
// false, // includeInside
// true, // includeOutside
// -GREAT, // nearDist
// -GREAT // curvature
// );
//
// outsideSource.applyToSet(topoSetSource::NEW, rawOutside);
//
// Pout<< "rawOutside:" << rawOutside.size() << endl;
//
// do
// {
// nRemoved = removeHangingCells(mesh, querySurf, rawOutside);
//
// Pout<< nl
// << "Removed " << nRemoved
// << " rawOutside cells that have all their points on the outside"
// << endl;
// }
// while (nRemoved != 0);
//
// Pout<< "Writing outside cells (" << rawOutside.size() << ") to cellSet "
// << rawOutside.instance()/rawOutside.local()/rawOutside.name()
// << endl << endl;
// rawOutside.write();
//
//
// // Select cut cells by negating inside and outside set.
// cutCells.invert(mesh.nCells());
//
// cellToCell deleteInsideSource(mesh, rawInside.name());
//
// deleteInsideSource.applyToSet(topoSetSource::DELETE, cutCells);
// Pout<< "Writing cut cells (" << cutCells.size() << ") to cellSet "
// << cutCells.instance()/cutCells.local()/cutCells.name()
// << endl << endl;
// cutCells.write();
//
//
// //
// // Remove cells with points too close to surface.
// //
//
//
// // Get all points in cutCells.
// pointSet cutPoints(mesh, "cutPoints", 4*cutCells.size());
// cellToPoint cutSource(mesh, "cutCells", cellToPoint::ALL);
// cutSource.applyToSet(topoSetSource::NEW, cutPoints);
//
// // Get all points that are too close to surface.
// pointSet nearPoints(mesh, "nearPoints", cutPoints.size());
//
// getNearPoints
// (
// mesh,
// surf,
// querySurf,
// edgeFactor,
// cutPoints,
// nearPoints
// );
//
// Pout<< nl
// << "Selected " << nearPoints.size()
// << " points that are closer than " << edgeFactor
// << " times the local minimum lengthscale to the surface"
// << nl << endl;
//
//
// // Remove cells that use any of the points in nearPoints
// // from the inside and outsideCells.
// nearPoints.write();
// pointToCell pToCell(mesh, nearPoints.name(), pointToCell::ANY);
//
//
//
// // Start off from copy of rawInside, rawOutside
// cellSet inside(mesh, "inside", rawInside);
// cellSet outside(mesh, "outside", rawOutside);
//
// pToCell.applyToSet(topoSetSource::DELETE, inside);
// pToCell.applyToSet(topoSetSource::DELETE, outside);
//
// Pout<< nl
// << "Removed " << rawInside.size() - inside.size()
// << " inside cells that are too close to the surface" << endl;
//
// Pout<< nl
// << "Removed " << rawOutside.size() - outside.size()
// << " inside cells that are too close to the surface" << nl << endl;
//
//
//
// //
// // Remove cells with one or no faces on rest of cellSet. Note: Problem is
// // not these cells an sich but rather that all of their vertices will be
// // outside vertices and thus projected onto surface. Which might (if they
// // project onto same surface) result in flattened cells.
// //
//
// do
// {
// nRemoved = removeHangingCells(mesh, querySurf, inside);
//
// Pout<< nl
// << "Removed " << nRemoved
// << " inside cells that have all their points on the outside"
// << endl;
// }
// while (nRemoved != 0);
// do
// {
// nRemoved = removeHangingCells(mesh, querySurf, outside);
//
// Pout<< nl
// << "Removed " << nRemoved
// << " outside cells that have all their points on the inside"
// << endl;
// }
// while (nRemoved != 0);
//
//
// //
// // Write
// //
//
//
// Pout<< "Writing inside cells (" << inside.size() << ") to cellSet "
// << inside.instance()/inside.local()/inside.name()
// << endl << endl;
//
// inside.write();
//
// Pout<< "Writing outside cells (" << outside.size() << ") to cellSet "
// << outside.instance()/outside.local()/outside.name()
// << endl << endl;
//
// outside.write();
//}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //