diff --git a/src/meshTools/meshSearch/meshSearch.C b/src/meshTools/meshSearch/meshSearch.C index 58c1d55e4058da58ffe1e03a4e6d7862d6806c74..d71178eb8681670c2f7527792ef5228c95768373 100644 --- a/src/meshTools/meshSearch/meshSearch.C +++ b/src/meshTools/meshSearch/meshSearch.C @@ -22,14 +22,11 @@ License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -Description - \*---------------------------------------------------------------------------*/ -#include "polyMesh.H" #include "meshSearch.H" -#include "triPointRef.H" -#include "octree.H" +#include "polyMesh.H" +#include "indexedOctree.H" #include "pointIndexHit.H" #include "DynamicList.H" #include "demandDrivenData.H" @@ -43,14 +40,75 @@ Foam::scalar Foam::meshSearch::tol_ = 1E-3; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +bool Foam::meshSearch::findNearer +( + const point& sample, + const pointField& points, + label& nearestI, + scalar& nearestDistSqr +) +{ + bool nearer = false; + + forAll(points, pointI) + { + scalar distSqr = magSqr(points[pointI] - sample); + + if (distSqr < nearestDistSqr) + { + nearestDistSqr = distSqr; + nearestI = pointI; + nearer = true; + } + } + + return nearer; +} + + +bool Foam::meshSearch::findNearer +( + const point& sample, + const pointField& points, + const labelList& indices, + label& nearestI, + scalar& nearestDistSqr +) +{ + bool nearer = false; + + forAll(indices, i) + { + label pointI = indices[i]; + + scalar distSqr = magSqr(points[pointI] - sample); + + if (distSqr < nearestDistSqr) + { + nearestDistSqr = distSqr; + nearestI = i; + nearer = true; + } + } + + return nearer; +} + + // tree based searching Foam::label Foam::meshSearch::findNearestCellTree(const point& location) const { - treeBoundBox tightest(treeBoundBox::greatBox); + const indexedOctree<treeDataPoint>& tree = cellCentreTree(); + + scalar span = mag(tree.bb().max() - tree.bb().min()); - scalar tightestDist = GREAT; + pointIndexHit info = tree.findNearest(location, Foam::sqr(span)); - return cellCentreTree().findNearest(location, tightest, tightestDist); + if (!info.hit()) + { + info = tree.findNearest(location, Foam::sqr(GREAT)); + } + return info.index(); } @@ -60,18 +118,15 @@ Foam::label Foam::meshSearch::findNearestCellLinear(const point& location) const const vectorField& centres = mesh_.cellCentres(); label nearestCelli = 0; - scalar minProximity = magSqr(centres[0] - location); + scalar minProximity = magSqr(centres[nearestCelli] - location); - forAll(centres, celli) - { - scalar proximity = magSqr(centres[celli] - location); - - if (proximity < minProximity) - { - nearestCelli = celli; - minProximity = proximity; - } - } + findNearer + ( + location, + centres, + nearestCelli, + minProximity + ); return nearestCelli; } @@ -105,27 +160,134 @@ Foam::label Foam::meshSearch::findNearestCellWalk do { - closer = false; + closer = findNearer + ( + location, + centres, + cc[curCell], + curCell, + distanceSqr + ); + } while (closer); + + return curCell; +} + + +// tree based searching +Foam::label Foam::meshSearch::findNearestFaceTree(const point& location) const +{ + // Search nearest cell centre. + const indexedOctree<treeDataPoint>& tree = cellCentreTree(); + + scalar span = mag(tree.bb().max() - tree.bb().min()); + + // Search with decent span + pointIndexHit info = tree.findNearest(location, Foam::sqr(span)); + + if (!info.hit()) + { + // Search with desparate span + info = tree.findNearest(location, Foam::sqr(GREAT)); + } + + + // Now check any of the faces of the nearest cell + const vectorField& centres = mesh_.faceCentres(); + const cell& ownFaces = mesh_.cells()[info.index()]; + label nearestFaceI = ownFaces[0]; + scalar minProximity = magSqr(centres[nearestFaceI] - location); + + findNearer + ( + location, + centres, + ownFaces, + nearestFaceI, + minProximity + ); + + return nearestFaceI; +} + + +// linear searching +Foam::label Foam::meshSearch::findNearestFaceLinear(const point& location) const +{ + const vectorField& centres = mesh_.faceCentres(); + + label nearestFaceI = 0; + scalar minProximity = magSqr(centres[nearestFaceI] - location); + + findNearer + ( + location, + centres, + nearestFaceI, + minProximity + ); + + return nearestFaceI; +} + + +// walking from seed +Foam::label Foam::meshSearch::findNearestFaceWalk +( + const point& location, + const label seedFaceI +) const +{ + if (seedFaceI < 0) + { + FatalErrorIn + ( + "meshSearch::findNearestFaceWalk(const point&, const label)" + ) << "illegal seedFace:" << seedFaceI << exit(FatalError); + } - // set the current list of neighbouring cells - const labelList& neighbours = cc[curCell]; + const vectorField& centres = mesh_.faceCentres(); + + + // Walk in direction of face that decreases distance + + label curFace = seedFaceI; + scalar distanceSqr = magSqr(centres[curFace] - location); + + while (true) + { + label betterFace = curFace; + + findNearer + ( + location, + centres, + mesh_.cells()[mesh_.faceOwner()[curFace]], + betterFace, + distanceSqr + ); - forAll (neighbours, nI) + if (mesh_.isInternalFace(curFace)) { - scalar curDistSqr = magSqr(centres[neighbours[nI]] - location); + findNearer + ( + location, + centres, + mesh_.cells()[mesh_.faceNeighbour()[curFace]], + betterFace, + distanceSqr + ); + } - // search through all the neighbours. - // If the cell is closer, reset current cell and distance - if (curDistSqr < distanceSqr) - { - distanceSqr = curDistSqr; - curCell = neighbours[nI]; - closer = true; // a closer neighbour has been found - } + if (betterFace == curFace) + { + break; } - } while (closer); - return curCell; + curFace = betterFace; + } + + return curFace; } @@ -180,12 +342,11 @@ Foam::label Foam::meshSearch::findNearestBoundaryFaceWalk const face& f = mesh_.faces()[curFaceI]; - scalar minDist = - f.nearestPoint - ( - location, - mesh_.points() - ).distance(); + scalar minDist = f.nearestPoint + ( + location, + mesh_.points() + ).distance(); bool closer; @@ -202,8 +363,7 @@ Foam::label Foam::meshSearch::findNearestBoundaryFaceWalk forAll (myEdges, myEdgeI) { - const labelList& neighbours = - mesh_.edgeFaces()[myEdges[myEdgeI]]; + const labelList& neighbours = mesh_.edgeFaces()[myEdges[myEdgeI]]; // Check any face which uses edge, is boundary face and // is not curFaceI itself. @@ -220,12 +380,11 @@ Foam::label Foam::meshSearch::findNearestBoundaryFaceWalk { const face& f = mesh_.faces()[faceI]; - pointHit curHit = - f.nearestPoint - ( - location, - mesh_.points() - ); + pointHit curHit = f.nearestPoint + ( + location, + mesh_.points() + ); // If the face is closer, reset current face and distance if (curHit.distance() < minDist) @@ -283,9 +442,11 @@ Foam::meshSearch::~meshSearch() clearOut(); } + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -const Foam::octree<Foam::octreeDataFace>& Foam::meshSearch::boundaryTree() const +const Foam::indexedOctree<Foam::treeDataFace>& Foam::meshSearch::boundaryTree() + const { if (!boundaryTreePtr_) { @@ -294,17 +455,26 @@ const Foam::octree<Foam::octreeDataFace>& Foam::meshSearch::boundaryTree() const // // all boundary faces (not just walls) - octreeDataFace shapes(mesh_); + labelList bndFaces(mesh_.nFaces()-mesh_.nInternalFaces()); + forAll(bndFaces, i) + { + bndFaces[i] = mesh_.nInternalFaces() + i; + } treeBoundBox overallBb(mesh_.points()); - boundaryTreePtr_ = new octree<octreeDataFace> + boundaryTreePtr_ = new indexedOctree<treeDataFace> ( - overallBb, // overall search domain - shapes, // all information needed to do checks on cells - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 10.0 + treeDataFace // all information needed to search faces + ( + false, // do not cache bb + mesh_, + bndFaces // boundary faces only + ), + overallBb, // overall search domain + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); } @@ -312,7 +482,8 @@ const Foam::octree<Foam::octreeDataFace>& Foam::meshSearch::boundaryTree() const } -const Foam::octree<Foam::octreeDataCell>& Foam::meshSearch::cellTree() const +const Foam::indexedOctree<Foam::treeDataCell>& Foam::meshSearch::cellTree() + const { if (!cellTreePtr_) { @@ -320,17 +491,19 @@ const Foam::octree<Foam::octreeDataCell>& Foam::meshSearch::cellTree() const // Construct tree // - octreeDataCell shapes(mesh_); - treeBoundBox overallBb(mesh_.points()); - cellTreePtr_ = new octree<octreeDataCell> + cellTreePtr_ = new indexedOctree<treeDataCell> ( + treeDataCell + ( + false, // not cache bb + mesh_ + ), overallBb, // overall search domain - shapes, // all information needed to do checks on cells - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells - 2.0 + 8, // maxLevel + 10, // leafsize + 3.0 // duplicity ); } @@ -339,8 +512,8 @@ const Foam::octree<Foam::octreeDataCell>& Foam::meshSearch::cellTree() const } -const Foam::octree<Foam::octreeDataPoint>& Foam::meshSearch::cellCentreTree() - const +const Foam::indexedOctree<Foam::treeDataPoint>& + Foam::meshSearch::cellCentreTree() const { if (!cellCentreTreePtr_) { @@ -348,17 +521,14 @@ const Foam::octree<Foam::octreeDataPoint>& Foam::meshSearch::cellCentreTree() // Construct tree // - // shapes holds reference to cellCentres! - octreeDataPoint shapes(mesh_.cellCentres()); - treeBoundBox overallBb(mesh_.cellCentres()); - cellCentreTreePtr_ = new octree<octreeDataPoint> + cellCentreTreePtr_ = new indexedOctree<treeDataPoint> ( + treeDataPoint(mesh_.cellCentres()), overallBb, // overall search domain - shapes, // all information needed to do checks on cells - 1, // min levels - 20.0, // maximum ratio of cubes v.s. cells + 10, // max levels + 10.0, // maximum ratio of cubes v.s. cells 100.0 // max. duplicity; n/a since no bounding boxes. ); } @@ -396,15 +566,14 @@ bool Foam::meshSearch::pointInCell(const point& p, label cellI) const forAll(f, fp) { - pointHit inter = - f.ray - ( - ctr, - dir, - mesh_.points(), - intersection::HALF_RAY, - intersection::VECTOR - ); + pointHit inter = f.ray + ( + ctr, + dir, + mesh_.points(), + intersection::HALF_RAY, + intersection::VECTOR + ); if (inter.hit()) { @@ -484,6 +653,31 @@ Foam::label Foam::meshSearch::findNearestCell } +Foam::label Foam::meshSearch::findNearestFace +( + const point& location, + const label seedFaceI, + const bool useTreeSearch +) const +{ + if (seedFaceI == -1) + { + if (useTreeSearch) + { + return findNearestFaceTree(location); + } + else + { + return findNearestFaceLinear(location); + } + } + else + { + return findNearestFaceWalk(location, seedFaceI); + } +} + + Foam::label Foam::meshSearch::findCell ( const point& location, @@ -607,19 +801,26 @@ Foam::label Foam::meshSearch::findNearestBoundaryFace { if (useTreeSearch) { - treeBoundBox tightest(treeBoundBox::greatBox); + const indexedOctree<treeDataFace>& tree = boundaryTree(); - scalar tightestDist = GREAT; + scalar span = mag(tree.bb().max() - tree.bb().min()); - label index = - boundaryTree().findNearest + pointIndexHit info = boundaryTree().findNearest + ( + location, + Foam::sqr(span) + ); + + if (!info.hit()) + { + info = boundaryTree().findNearest ( location, - tightest, - tightestDist + Foam::sqr(GREAT) ); + } - return boundaryTree().shapes().meshFaces()[index]; + return tree.shapes().faceLabels()[info.index()]; } else { @@ -670,7 +871,7 @@ Foam::pointIndexHit Foam::meshSearch::intersection if (curHit.hit()) { // Change index into octreeData into face label - curHit.setIndex(boundaryTree().shapes().meshFaces()[curHit.index()]); + curHit.setIndex(boundaryTree().shapes().faceLabels()[curHit.index()]); } return curHit; } @@ -733,7 +934,9 @@ Foam::List<Foam::pointIndexHit> Foam::meshSearch::intersections bool Foam::meshSearch::isInside(const point& p) const { - return boundaryTree().getSampleType(p) == octree<octreeDataFace>::INSIDE; + return + boundaryTree().getVolumeType(p) + == indexedOctree<treeDataFace>::INSIDE; } diff --git a/src/meshTools/meshSearch/meshSearch.H b/src/meshTools/meshSearch/meshSearch.H index c50c0b8bb0ee62eb14e32b2ff71c5d89993c1223..38ca70fcd9c38c4f9870e081d8c129fa0b5603b7 100644 --- a/src/meshTools/meshSearch/meshSearch.H +++ b/src/meshTools/meshSearch/meshSearch.H @@ -26,7 +26,8 @@ Class Foam::meshSearch Description - Various searches on polyMesh; uses (demand driven) octree to search. + Various (local, not parallel) searches on polyMesh; + uses (demand driven) octree to search. SourceFiles meshSearch.C @@ -36,11 +37,10 @@ SourceFiles #ifndef meshSearch_H #define meshSearch_H -#include "octreeDataCell.H" -#include "octreeDataFace.H" -#include "octreeDataPoint.H" +#include "treeDataCell.H" +#include "treeDataFace.H" +#include "treeDataPoint.H" #include "pointIndexHit.H" -#include "className.H" #include "Cloud.H" #include "passiveParticle.H" @@ -71,46 +71,77 @@ class meshSearch //- demand driven octrees - mutable octree<octreeDataFace>* boundaryTreePtr_; - mutable octree<octreeDataCell>* cellTreePtr_; - mutable octree<octreeDataPoint>* cellCentreTreePtr_; + mutable indexedOctree<treeDataFace>* boundaryTreePtr_; + mutable indexedOctree<treeDataCell>* cellTreePtr_; + mutable indexedOctree<treeDataPoint>* cellCentreTreePtr_; // Private Member Functions - //- nearest cell centre using octree - label findNearestCellTree(const point& location) const; + //- Updates nearestI, nearestDistSqr from any closer ones. + static bool findNearer + ( + const point& sample, + const pointField& points, + label& nearestI, + scalar& nearestDistSqr + ); + + //- Updates nearestI, nearestDistSqr from any selected closer ones. + static bool findNearer + ( + const point& sample, + const pointField& points, + const labelList& indices, + label& nearestI, + scalar& nearestDistSqr + ); - //- nearest cell centre going through all cells - label findNearestCellLinear(const point& location) const; - //- walk from seed. Does not 'go around' boundary, just returns - // last cell before boundary. - label findNearestCellWalk - ( - const point& location, - const label seedCellI - ) const; + // Cells - //- cell containing location. Linear search. - label findCellLinear(const point& location) const; + //- nearest cell centre using octree + label findNearestCellTree(const point&) const; + + //- nearest cell centre going through all cells + label findNearestCellLinear(const point&) const; + + //- walk from seed. Does not 'go around' boundary, just returns + // last cell before boundary. + label findNearestCellWalk(const point&, const label) const; + + //- cell containing location. Linear search. + label findCellLinear(const point&) const; + + + // Cells + + label findNearestFaceTree(const point&) const; + + label findNearestFaceLinear(const point&) const; + + label findNearestFaceWalk(const point&, const label) const; - //- walk from seed to find nearest boundary face. Gets stuck in - // local minimum. - label findNearestBoundaryFaceWalk - ( - const point& location, - const label seedFaceI - ) const; - //- Calculate offset vector in direction dir with as length a fraction - // of the cell size (of the cell straddling boundary face) - vector offset - ( - const point& bPoint, - const label bFaceI, - const vector& dir - ) const; + + // Boundary faces + + //- walk from seed to find nearest boundary face. Gets stuck in + // local minimum. + label findNearestBoundaryFaceWalk + ( + const point& location, + const label seedFaceI + ) const; + + //- Calculate offset vector in direction dir with as length a + // fraction of the cell size (of the cell straddling boundary face) + vector offset + ( + const point& bPoint, + const label bFaceI, + const vector& dir + ) const; //- Disallow default bitwise copy construct @@ -154,13 +185,13 @@ public: //- Get (demand driven) reference to octree holding all // boundary faces - const octree<octreeDataFace>& boundaryTree() const; + const indexedOctree<treeDataFace>& boundaryTree() const; //- Get (demand driven) reference to octree holding all cells - const octree<octreeDataCell>& cellTree() const; + const indexedOctree<treeDataCell>& cellTree() const; //- Get (demand driven) reference to octree holding all cell centres - const octree<octreeDataPoint>& cellCentreTree() const; + const indexedOctree<treeDataPoint>& cellCentreTree() const; // Queries @@ -181,6 +212,13 @@ public: const bool useTreeSearch = true ) const; + label findNearestFace + ( + const point& location, + const label seedFaceI, + const bool useTreeSearch + ) const; + //- Find cell containing (using pointInCell) location. // If seed provided walks and falls back to linear/tree search. // (so handles holes correctly)s @@ -206,7 +244,7 @@ public: //- Find first intersection of boundary in segment [pStart, pEnd] // (so inclusive of endpoints). Always octree for now pointIndexHit intersection(const point& pStart, const point& pEnd) - const; + const; //- Find all intersections of boundary within segment pStart .. pEnd // Always octree for now