/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | foam-extend: Open Source CFD
\\ / O peration | Version: 3.2
\\ / A nd | Web: http://www.foam-extend.org
\\/ M anipulation | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
This file is part of foam-extend.
foam-extend 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.
foam-extend 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 foam-extend. If not, see .
Description
Select cells in relation to surface.
Divides cells into three sets:
- cutCells : cells cut by surface or close to surface.
- outside : cells not in cutCells and reachable from set of
user-defined points (outsidePoints)
- inside : same but not reachable.
Finally the wanted sets are combined into a cellSet 'selected'. Apart
from straightforward adding the contents there are a few extra rules to
make sure that the surface of the 'outside' of the mesh is singly
connected.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "objectRegistry.H"
#include "Time.H"
#include "polyMesh.H"
#include "IOdictionary.H"
#include "twoDPointCorrector.H"
#include "OFstream.H"
#include "meshTools.H"
#include "triSurface.H"
#include "triSurfaceSearch.H"
#include "meshSearch.H"
#include "cellClassification.H"
#include "cellSet.H"
#include "cellInfo.H"
#include "MeshWave.H"
#include "edgeStats.H"
#include "treeDataTriSurface.H"
#include "indexedOctree.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// cellType for cells included/not included in mesh.
static const label MESH = cellClassification::INSIDE;
static const label NONMESH = cellClassification::OUTSIDE;
void writeSet(const cellSet& cells, const string& msg)
{
Info<< "Writing " << msg << " (" << cells.size() << ") to cellSet "
<< cells.instance()/cells.local()/cells.name()
<< endl << endl;
cells.write();
}
void getType(const labelList& elems, const label type, labelHashSet& set)
{
forAll(elems, i)
{
if (elems[i] == type)
{
set.insert(i);
}
}
}
void cutBySurface
(
const polyMesh& mesh,
const meshSearch& queryMesh,
const triSurfaceSearch& querySurf,
const pointField& outsidePts,
const bool selectCut,
const bool selectInside,
const bool selectOutside,
const scalar nearDist,
cellClassification& cellType
)
{
// Cut with surface and classify as inside/outside/cut
cellType =
cellClassification
(
mesh,
queryMesh,
querySurf,
outsidePts
);
// Get inside/outside/cutCells cellSets.
cellSet inside(mesh, "inside", mesh.nCells()/10);
getType(cellType, cellClassification::INSIDE, inside);
writeSet(inside, "inside cells");
cellSet outside(mesh, "outside", mesh.nCells()/10);
getType(cellType, cellClassification::OUTSIDE, outside);
writeSet(outside, "outside cells");
cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
getType(cellType, cellClassification::CUT, cutCells);
writeSet(cutCells, "cells cut by surface");
// Change cellType to reflect selected part of mesh. Use
// MESH to denote selected part, NONMESH for all
// other cells.
// Is a bit of a hack but allows us to reuse all the functionality
// in cellClassification.
forAll(cellType, cellI)
{
label cType = cellType[cellI];
if (cType == cellClassification::CUT)
{
if (selectCut)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else if (cType == cellClassification::INSIDE)
{
if (selectInside)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else if (cType == cellClassification::OUTSIDE)
{
if (selectOutside)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else
{
FatalErrorIn("cutBySurface")
<< "Multiple mesh regions in original mesh" << endl
<< "Please use splitMeshRegions to separate these"
<< exit(FatalError);
}
}
if (nearDist > 0)
{
Info<< "Removing cells with points closer than " << nearDist
<< " to the surface ..." << nl << endl;
const pointField& pts = mesh.points();
const indexedOctree& tree = querySurf.tree();
label nRemoved = 0;
forAll(pts, pointI)
{
const point& pt = pts[pointI];
pointIndexHit hitInfo = tree.findNearest(pt, sqr(nearDist));
if (hitInfo.hit())
{
const labelList& pCells = mesh.pointCells()[pointI];
forAll(pCells, i)
{
if (cellType[pCells[i]] != NONMESH)
{
cellType[pCells[i]] = NONMESH;
nRemoved++;
}
}
}
}
// tmp tnearest = querySurf.calcNearest(pts);
// const pointField& nearest = tnearest();
//
// label nRemoved = 0;
//
// forAll(nearest, pointI)
// {
// if (mag(nearest[pointI] - pts[pointI]) < nearDist)
// {
// const labelList& pCells = mesh.pointCells()[pointI];
//
// forAll(pCells, i)
// {
// if (cellType[pCells[i]] != NONMESH)
// {
// cellType[pCells[i]] = NONMESH;
// nRemoved++;
// }
// }
// }
// }
Info<< "Removed " << nRemoved << " cells since too close to surface"
<< nl << endl;
}
}
// We're meshing the outside. Subset the currently selected mesh cells with the
// ones reachable from the outsidepoints.
label selectOutsideCells
(
const polyMesh& mesh,
const meshSearch& queryMesh,
const pointField& outsidePts,
cellClassification& cellType
)
{
//
// Check all outsidePts and for all of them inside a mesh cell
// collect the faces to start walking from
//
// Outside faces
labelHashSet outsideFacesMap(outsidePts.size() * 6 * 2);
DynamicList