diff --git a/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/files b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..73871a7532e1c273d0030d8c8bc4180e1ecef2a7 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/files @@ -0,0 +1,3 @@ +checkCvMesh.C + +EXE = $(FOAM_APPBIN)/checkCvMesh diff --git a/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/options b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..ba68fd3819b53037f9711dfbb9691846a215f4d3 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/Make/options @@ -0,0 +1,14 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/triSurface/lnInclude \ + -I$(LIB_SRC)/mesh/autoMesh/lnInclude \ + -I$(LIB_SRC)/dynamicMesh/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -ldynamicMesh \ + -ltriSurface \ + -lautoMesh \ + -lmeshTools + diff --git a/applications/utilities/mesh/generation/cvMesh/checkCvMesh/checkCvMesh.C b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/checkCvMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..df2a3b90f81834625c22ab8fc3b490c4c0b73d99 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/checkCvMesh/checkCvMesh.C @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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/>. + +Application + checkCvMesh + +Description + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "fvMesh.H" +#include "autoSnapDriver.H" +#include "faceSet.H" +#include "motionSmoother.H" +#include "timeSelector.H" + + +using namespace Foam; + + +int main(int argc, char *argv[]) +{ +# include "addOverwriteOption.H" + +# include "setRootCase.H" +# include "createTime.H" + + instantList timeDirs = timeSelector::select0(runTime, args); + +# include "createMesh.H" + + runTime.functionObjects().off(); + + forAll(timeDirs, timeI) + { + runTime.setTime(timeDirs[timeI], timeI); + + Info<< "Create mesh for time = " << runTime.timeName() + << nl << endl; + + mesh.readUpdate(); + + Info<< "Read mesh in = " + << runTime.cpuTimeIncrement() << " s" << endl; + + // Check patches and faceZones are synchronised + mesh.boundaryMesh().checkParallelSync(true); + meshRefinement::checkCoupledFaceZones(mesh); + + // Read meshing dictionary + IOdictionary cvMeshDict + ( + IOobject + ( + "cvMeshDict", + runTime.system(), + mesh, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ); + + // mesh motion and mesh quality parameters + const dictionary& meshQualityDict + = cvMeshDict.subDict("meshQualityControls"); + + + Info<< "Checking initial mesh ..." << endl; + faceSet wrongFaces(mesh, "wrongFaces", mesh.nFaces()/100); + motionSmoother::checkMesh(false, mesh, meshQualityDict, wrongFaces); + + const label nInitErrors = returnReduce + ( + wrongFaces.size(), + sumOp<label>() + ); + + Info<< "Detected " << nInitErrors << " illegal faces" + << " (concave, zero area or negative cell pyramid volume)" + << endl; + + if (nInitErrors > 0) + { + Info<< "Writing " << nInitErrors + << " faces in error to set " + << wrongFaces.name() << endl; + + wrongFaces.instance() = mesh.pointsInstance(); + wrongFaces.write(); + } + + Info<< nl << "End of time " << runTime.timeName() << nl << endl; + } + + Info<< "End\n" << endl; + + return 0; + +} + diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C index edafdb50f912e02a89acc6133fc0d7cf7491cd5c..a2d44f0ee1ab506045eabdeac7ccb7300ad3d275 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.C @@ -724,6 +724,8 @@ void Foam::backgroundMeshDecomposition::buildPatchAndTree() globalBackgroundBounds_ = treeBoundBox(bbMin, bbMax); + octreeNearestDistances_ = bFTreePtr_().calcNearestDistance(); + if (cvMesh_.cvMeshControls().objOutput()) { OFstream fStr @@ -795,6 +797,7 @@ Foam::backgroundMeshDecomposition::backgroundMeshDecomposition ), boundaryFacesPtr_(), bFTreePtr_(), + octreeNearestDistances_(), allBackgroundMeshBounds_(Pstream::nProcs()), globalBackgroundBounds_(), decomposeDict_ @@ -1150,6 +1153,8 @@ bool Foam::backgroundMeshDecomposition::positionOnThisProcessor const point& pt ) const { +// return bFTreePtr_().findAnyOverlap(pt, 0.0); + return bFTreePtr_().getVolumeType(pt) == indexedOctree<treeDataBPatch>::INSIDE; @@ -1176,6 +1181,7 @@ bool Foam::backgroundMeshDecomposition::overlapsThisProcessor const treeBoundBox& box ) const { +// return !procBounds().contains(box); return !bFTreePtr_().findBox(box).empty(); } @@ -1183,9 +1189,11 @@ bool Foam::backgroundMeshDecomposition::overlapsThisProcessor bool Foam::backgroundMeshDecomposition::overlapsThisProcessor ( const point& centre, - scalar radiusSqr + const scalar radiusSqr ) const { + //return bFTreePtr_().findAnyOverlap(centre, radiusSqr); + return bFTreePtr_().findNearest(centre, radiusSqr).hit(); } @@ -1645,6 +1653,7 @@ Foam::labelListList Foam::backgroundMeshDecomposition::overlapsProcessors // If the sphere finds a nearest element of the patch, then it overlaps sphereOverlapsCandidate[sI] = bFTreePtr_().findNearest(c, rSqr).hit(); + //sphereOverlapsCandidate[sI] = bFTreePtr_().findAnyOverlap(c, rSqr); } map().reverseDistribute diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H index 87ab88af356873a7fc4f4512645ac46873806110..d8e6388cfb00e28d73c38928d9be482179689697 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecomposition.H @@ -111,6 +111,8 @@ class backgroundMeshDecomposition //- Search tree for the boundaryFaces_ patch autoPtr<indexedOctree<treeDataBPatch> > bFTreePtr_; + List<scalar> octreeNearestDistances_; + //- The bounds of all background meshes on all processors treeBoundBoxList allBackgroundMeshBounds_; @@ -225,16 +227,16 @@ public: //- Are the given positions inside the domain of this decomposition boolList positionOnThisProcessor(const List<point>& pts) const; - //- Does the given box overlap the faces of the bounday of this + //- Does the given box overlap the faces of the boundary of this // processor bool overlapsThisProcessor(const treeBoundBox& box) const; - //- Does the given sphere overlap the faces of the bounday of this + //- Does the given sphere overlap the faces of the boundary of this // processor bool overlapsThisProcessor ( const point& centre, - scalar radiusSqr + const scalar radiusSqr ) const; //- Find nearest intersection of line between start and end, (exposing @@ -289,6 +291,12 @@ public: //- Return access to the underlying mesh inline const fvMesh& mesh() const; + //- Return access to the underlying tree + inline const indexedOctree<treeDataBPatch>& tree() const; + + //- Return access to the nearest distance of the octree nodes + inline const List<scalar>& octreeNearestDistances() const; + //- Return the boundBox of this processor inline const treeBoundBox& procBounds() const; }; diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H index df659cfd9cc0fed0f996b2bb97ff0b68622a1dcf..2897d3fc5830e133ba305b23436df6f829ccff99 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/backgroundMeshDecomposition/backgroundMeshDecompositionI.H @@ -30,6 +30,18 @@ const Foam::fvMesh& Foam::backgroundMeshDecomposition::mesh() const return mesh_; } +const Foam::indexedOctree<Foam::treeDataBPatch>& +Foam::backgroundMeshDecomposition::tree() const +{ + return bFTreePtr_(); +} + +const Foam::List<Foam::scalar>& +Foam::backgroundMeshDecomposition::octreeNearestDistances() const +{ + return octreeNearestDistances_; +} + const Foam::treeBoundBox& Foam::backgroundMeshDecomposition::procBounds() const { diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C index e8cedc49c2cbd5e05256b513c4be1250f8140e4f..958fcf6763ec79332bf98faee94882df8eb0c640 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C @@ -240,9 +240,9 @@ void Foam::conformalVoronoiMesh::insertPoints { label preDistributionSize(points.size()); - DynamicList<Foam::point> transferPoints(points.size()/2); + DynamicList<Foam::point> transferPoints; - DynamicList<Point> pointsOnProcessor(points.size()/2); + DynamicList<Point> pointsOnProcessor; for ( @@ -277,12 +277,16 @@ void Foam::conformalVoronoiMesh::insertPoints decomposition_().distributePoints(transferPoints) ); + const label oldSize = points.size(); + + points.setSize(oldSize + transferPoints.size()); + forAll(transferPoints, tPI) { - points.append(toPoint(transferPoints[tPI])); + points[tPI + oldSize] = toPoint(transferPoints[tPI]); } - label sizeChange = preDistributionSize - label(points.size()); + label sizeChange = preDistributionSize - points.size(); // if (mag(sizeChange) > 0) // { @@ -417,7 +421,6 @@ void Foam::conformalVoronoiMesh::insertPoints // ); // } - rangeInsertWithInfo ( pts.begin(), @@ -1246,6 +1249,8 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh // better balance the surface conformation load. distributeBackground(); +// conformToSurface(); + buildSurfaceConformation(rmCoarse); // The introduction of the surface conformation may have distorted the @@ -1313,7 +1318,7 @@ void Foam::conformalVoronoiMesh::move() { cit->cellIndex() = dualVertI; - dualVertices[dualVertI] = topoint(dual(cit)); + dualVertices[dualVertI] = cit->dual(); dualVertI++; } @@ -1511,7 +1516,6 @@ void Foam::conformalVoronoiMesh::move() ( toPoint(0.5*(dVA + dVB)) ); - } } else if @@ -1671,9 +1675,57 @@ void Foam::conformalVoronoiMesh::move() insertPoints(pointsToInsert); + // Remove internal points that have been inserted outside the surface. + label internalPtIsOutside = 0; + + for + ( + Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); + vit != finite_vertices_end(); + ++vit + ) + { + if (vit->internalPoint()) + { + bool inside + = geometryToConformTo_.inside(topoint(vit->point())); + + if (!inside) + { + remove(vit); + internalPtIsOutside++; + } + } + } + + Info<< " " << internalPtIsOutside + << " internal points were inserted outside the domain. " + << "They have been removed." << endl; + + // Fix points that have not been significantly displaced +// for +// ( +// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); +// vit != finite_vertices_end(); +// ++vit +// ) +// { +// if (vit->internalPoint()) +// { +// if +// ( +// mag(displacementAccumulator[vit->index()]) +// < 0.1*targetCellSize(topoint(vit->point())) +// ) +// { +// vit->setVertexFixed(); +// } +// } +// } + if (cvMeshControls().objOutput() && runTime_.outputTime()) { - writePoints("points_" + runTime_.timeName() + ".obj", false); + writePoints("points_" + runTime_.timeName() + ".obj", true); } timeCheck("Internal points inserted"); diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H index b590eb31cd67383146216cfbdc4f211a38397137..a514c660a1d96350897478ca826dba7efe5af1d8 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H @@ -48,7 +48,6 @@ SourceFiles #define CGAL_INEXACT #include "CGALTriangulation3Ddefs.H" -#include <CGAL/Spatial_sort_traits_adapter_3.h> #include "uint.H" #include "ulong.H" #include "searchableSurfaces.H" @@ -595,6 +594,12 @@ private: Foam::point& b ) const; + label removeProcessorBoundarySeeds(bool reinsertBoundPts); + + void seedProcessorBoundarySurfaces(bool seedProcessors); + + label numberOfUnusedReferredPoints() const; + //- Build the parallelInterfaces of the mesh void buildParallelInterface ( @@ -1240,7 +1245,7 @@ public: Traits_for_spatial_sort<Triangulation>() ); - typename Triangulation::Cell_handle hint; + typename Triangulation::Vertex_handle hint; for ( @@ -1250,16 +1255,9 @@ public: ++p ) { - typename Triangulation::Locate_type lt; - typename Triangulation::Cell_handle c; - label li, lj; - - c = T.locate(*(p->first), lt, li, lj, hint); - const size_t checkInsertion = T.number_of_vertices(); - typename Triangulation::Vertex_handle v - = T.insert(*(p->first), lt, c, li, lj); + hint = T.insert(*(p->first), hint); if (checkInsertion != T.number_of_vertices() - 1) { @@ -1278,12 +1276,11 @@ public: // type directly (note that this routine never gets // called for referredPoints so type will never be // -procI - type += T.number_of_vertices() - 1; + type += checkInsertion; } - v->index() = indices[oldIndex] - + T.number_of_vertices() - 1; - v->type() = type; + hint->index() = indices[oldIndex] + checkInsertion; + hint->type() = type; } } } diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C index 04ef2af045d22226200bce8d1943ec4ed9438696..d103d3c0fcb1ff968452105319a3c304e5a65578 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshCalcDualMesh.C @@ -1890,7 +1890,7 @@ void Foam::conformalVoronoiMesh::indexDualVertices { cit->cellIndex() = dualVertI; - pts[dualVertI] = topoint(dual(cit)); + pts[dualVertI] = cit->dual(); if ( diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C index 847974a2f4ed3c01bdc652fe52baafafcb8bc96c..7f4c7abb6ef2cd34a4513fda2e94a41cf5af0d9b 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshConformToSurface.C @@ -41,6 +41,11 @@ void Foam::conformalVoronoiMesh::conformToSurface() { reconformationMode reconfMode = reconformationControl(); + if (Pstream::parRun()) + { + seedProcessorBoundarySurfaces(true); + } + if (reconfMode == rmNone) { // Reinsert stored surface conformation @@ -69,6 +74,16 @@ void Foam::conformalVoronoiMesh::conformToSurface() storeSurfaceConformation(); } + if (Pstream::parRun()) + { + label nFarPoints = removeProcessorBoundarySeeds(true); + + reduce(nFarPoints, sumOp<label>()); + + Info<< " Removed " << nFarPoints + << " far points from the mesh." << endl; + } + // reportSurfaceConformationQuality(); } @@ -140,13 +155,8 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation buildEdgeLocationTree(existingEdgeLocations); buildSurfacePtLocationTree(existingSurfacePtLocations); - - // Initialise the edgeLocationTree - //buildEdgeLocationTree(edgeLocationTree, existingEdgeLocations); - label initialTotalHits = 0; - // Surface protrusion conformation is done in two steps. // 1. the dual edges (of all internal vertices) can stretch to // 'infinity' so any intersection would be badly behaved. So @@ -382,7 +392,7 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation ( Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); vit != finite_vertices_end(); - vit++ + ++vit ) { // The initial surface conformation has already identified the @@ -511,14 +521,18 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation timeCheck("Conformation iteration " + name(iterationNo)); - // Update the parallel interface - buildParallelInterface - ( - referralVertices, - receivedVertices, - false, - name(iterationNo) - ); + // Only need to update the interface if there are surface/edge hits + if (totalHits > 0) + { + // Update the parallel interface + buildParallelInterface + ( + referralVertices, + receivedVertices, + false, + name(iterationNo) + ); + } iterationNo++; @@ -563,8 +577,8 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAnyIntersection continue; } - Foam::point dE0 = topoint(dual(fit->first)); - Foam::point dE1 = topoint(dual(fit->first->neighbor(fit->second))); + Foam::point dE0 = fit->first->dual(); + Foam::point dE1 = fit->first->neighbor(fit->second)->dual(); if (Pstream::parRun()) { @@ -631,8 +645,8 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections // Construct the dual edge and search for intersections of the edge // with the surface - Foam::point dE0 = topoint(dual(fit->first)); - Foam::point dE1 = topoint(dual(fit->first->neighbor(fit->second))); + Foam::point dE0 = fit->first->dual(); + Foam::point dE1 = fit->first->neighbor(fit->second)->dual(); pointIndexHit infoIntersection; label hitSurfaceIntersection = -1; @@ -801,6 +815,144 @@ void Foam::conformalVoronoiMesh::buildParallelInterface } +Foam::label Foam::conformalVoronoiMesh::removeProcessorBoundarySeeds +( + bool reinsertBoundPts +) +{ + label nFarPoints = 0; + + + + std::list<Vertex_handle> toRemove; + + for + ( + Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); + vit != finite_vertices_end(); + ++vit + ) + { + if (vit->farPoint()) + { + //remove(vit); + toRemove.push_back(vit); + nFarPoints++; + } + } + + // This function removes the points in the iterator range and then + // retriangulates. + timeCheck("Start Removing Seeded Points " + name(toRemove.size())); + + remove_cluster(toRemove.begin(), toRemove.end()); + + + // Need to do this to make sure the triangulation is well-behaved + if (reinsertBoundPts) + { + reinsertBoundingPoints(); + } + + + +// DynamicList<Foam::point> toAdd; +// DynamicList<label> indices; +// DynamicList<label> types; +// +// for +// ( +// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); +// vit != finite_vertices_end(); +// ++vit +// ) +// { +// if (!vit->farPoint()) +// { +// toAdd.append(topoint(vit->point())); +// indices.append(vit->index()); +// types.append(vit->type()); +// +// nFarPoints++; +// } +// } +// +// this->clear(); +// +// // Need to do this to make sure the triangulation is well-behaved +// if (reinsertBoundPts) +// { +// reinsertBoundingPoints(); +// } +// +// forAll(toAdd, pI) +// { +// insertPoint(toAdd[pI], indices[pI], types[pI]); +// } + + + timeCheck("End Removing Seeded Points"); + + return nFarPoints; +} + + +void Foam::conformalVoronoiMesh::seedProcessorBoundarySurfaces +( + bool seedProcessors +) +{ + //removeProcessorBoundarySeeds(false); + + // Loop over processor patch faces and insert a point in the centre of the + // face + const fvMesh& mesh = decomposition_().mesh(); + const polyBoundaryMesh& bMesh = mesh.boundaryMesh(); + + DynamicList<Foam::point> pts; + DynamicList<label> indices; + DynamicList<label> types; + + label nFarPoints = 0; + + const scalar normalDistance = 5.0; + const scalar pert = 0.1*(rndGen_.scalar01() - 0.5); + + forAll(bMesh, patchI) + { + const polyPatch& patch = bMesh[patchI]; + + if (!seedProcessors && isA<processorPolyPatch>(patch)) + { + continue; + } + + forAll(patch, faceI) + { + if (faceI % 1 == 0) + { + const face& f = patch[faceI]; + + pts.append + ( + f.centre(mesh.points()) + + pert*normalDistance*f.normal(mesh.points()) + ); + indices.append(nFarPoints++); + types.append(Vb::vtFar); + } + } + } + + insertPoints(pts, indices, types, false); + + reduce(nFarPoints, sumOp<label>()); + + Info<< " Inserted " << nFarPoints + << " far points into the mesh." << endl; +} + + void Foam::conformalVoronoiMesh::buildParallelInterface ( List<labelHashSet>& referralVertices, @@ -835,22 +987,88 @@ void Foam::conformalVoronoiMesh::buildParallelInterface timeCheck("After buildParallelInterfaceAll"); } - if (initialEdgeReferral) - { - // Used as an initial pass to localise the vertex referring - find - // vertices whose dual edges pierce nearby processor volumes and refer - // them to establish a sensible boundary interface region before - // running a circumsphere assessment. - buildParallelInterfaceIntersection - ( - referralVertices, - receivedVertices, - outputName - ); + // Reject points that are not near the boundary from the subsequent + // searches - timeCheck("After buildParallelInterfaceIntersection"); - } +// label nearProcCount = 0; +// label notNearProcCount = 0; +// boundBox quickRejectionBox(decomposition_().procBounds()); +// +//// Pout<< "Processor boundBox: " << quickRejectionBox << endl; +// +// quickRejectionBox.inflate(-0.1); +// +// OFstream str("rejectionBox_" + name(Pstream::myProcNo()) + ".obj"); +// +// meshTools::writeOBJ +// ( +// str, +// boundBox::faces(), +// quickRejectionBox.points() +// ); +// +// Pout<< "Inflated rejection boundBox: " << quickRejectionBox << endl; + +// for +// ( +// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); +// vit != finite_vertices_end(); +// vit++ +// ) +// { +// if (vit->real() && !vit->nearProcBoundary()) +// { +// const Foam::point& pt = topoint(vit->point()); +// const scalar range = targetCellSize(pt); +// +//// if +//// ( +//// decomposition_().overlapsThisProcessor +//// ( +//// pt, +//// range +//// ) +//// ) +// if (!quickRejectionBox.contains(pt)) +// { +// vit->setNearProcBoundary(); +// nearProcCount++; +// } +// else +// { +// //vit->setNearProcBoundary(); +// notNearProcCount++; +// } +// } +// } +// +// reduce(nearProcCount, sumOp<label>()); +// reduce(notNearProcCount, sumOp<label>()); +// +// timeCheck +// ( +// "End of potential intersection search. " +// + name(nearProcCount) + " are near a processor boundary. " +// + name(notNearProcCount) + " are not." +// ); + +// if (initialEdgeReferral) +// { +// // Used as an initial pass to localise the vertex referring - find +// // vertices whose dual edges pierce nearby processor volumes and refer +// // them to establish a sensible boundary interface region before +// // running a circumsphere assessment. +// +// buildParallelInterfaceIntersection +// ( +// referralVertices, +// receivedVertices, +// outputName +// ); +// +// timeCheck("After buildParallelInterfaceIntersection"); +// } buildParallelInterfaceInfluence ( @@ -860,6 +1078,56 @@ void Foam::conformalVoronoiMesh::buildParallelInterface ); timeCheck("After buildParallelInterface"); + + // Check all referred vertices are actually used on the processor. + label nUnusedReferred = numberOfUnusedReferredPoints(); + + reduce(nUnusedReferred, sumOp<label>()); + + Info<< " Number of referred points that are not used : " + << nUnusedReferred << " (approximate)" << endl; +} + + +Foam::label Foam::conformalVoronoiMesh::numberOfUnusedReferredPoints() const +{ + label nUnusedPoints = 0; + + for + ( + Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); + vit != finite_vertices_end(); + ++vit + ) + { + if (vit->referred()) + { + std::list<Vertex_handle> adjVertices; + finite_adjacent_vertices(vit, std::back_inserter(adjVertices)); + + bool isUsed = false; + + for + ( + std::list<Vertex_handle>::iterator adjVit = adjVertices.begin(); + adjVit != adjVertices.end(); + ++adjVit + ) + { + if ((*adjVit)->real()) + { + isUsed = true; + } + } + + if (!isUsed) + { + nUnusedPoints++; + } + } + } + + return nUnusedPoints; } @@ -880,7 +1148,7 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceAll ( Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); vit != finite_vertices_end(); - vit++ + ++vit ) { if (!vit->farPoint()) @@ -966,7 +1234,10 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceIntersection // If either Delaunay cell at the end of the Dual edge is infinite, // skip. - if (!is_infinite(c1) && !is_infinite(c2)) + if + ( + !is_infinite(c1) && !is_infinite(c2) + ) { // The Delaunauy cells at either end of the dual edge need to be // real, i.e. all vertices form part of the internal or boundary @@ -977,12 +1248,14 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceIntersection && c2->internalOrBoundaryDualVertex() ) { - Foam::point a = topoint(dual(c1)); - Foam::point b = topoint(dual(c2)); + const Foam::point& a = c1->dual(); + const Foam::point& b = c2->dual(); // Only if the dual edge cuts the boundary of this processor is // it going to be counted. - if (decomposition_().findLineAny(a, b).hit()) + pointIndexHit info = decomposition_().findLineAny(a, b); + + if (info.hit()) { dE0.append(a); dE1.append(b); @@ -995,11 +1268,22 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceIntersection fIOuter++; } + reduce(fIOuter, sumOp<label>()); + + timeCheck + ( + "End of actual intersection search over " + + name(fIOuter) + + " faces." + ); + // Preform intersections in both directions, as there is no sense // associated with the Dual edge List<List<pointIndexHit> > intersectionForward(intersectsProc(dE0, dE1)); List<List<pointIndexHit> > intersectionReverse(intersectsProc(dE1, dE0)); + timeCheck("End of find processor intersection"); + // Reset counter fIOuter = 0; @@ -1175,13 +1459,58 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence DynamicList<Foam::point> circumcentre; DynamicList<scalar> circumradiusSqr; - PackedBoolList testCellInfluence(number_of_cells(), false); // Index outer (all) Delaunauy cells for whether they are potential // overlaps, index (inner) the list of tests an results. label cIInner = 0; label cIOuter = 0; + + label cellIndexCount = 0; + for + ( + Delaunay::Finite_cells_iterator cit = finite_cells_begin(); + cit != finite_cells_end(); + ++cit + ) + { + cit->cellIndex() = cellIndexCount++; + } + + timeCheck("End of cell Indexing"); + + labelList testCellInfluence(number_of_cells(), 0); + + label nQuickRejections = 0; + + for + ( + Delaunay::Finite_cells_iterator cit = finite_cells_begin(); + cit != finite_cells_end(); + ++cit + ) + { + const Foam::point& cc = cit->dual(); + + const scalar crSqr = magSqr(cc - topoint(cit->vertex(0)->point())); + + if + ( + decomposition_().tree().quickCircumsphereRejection + ( + cc, + crSqr, + decomposition_().octreeNearestDistances() + ) + ) + { + nQuickRejections++; + testCellInfluence[cit->cellIndex()] = -1; + } + } + + timeCheck("End of octreeNearestDistances calculation"); + for ( Delaunay::Finite_cells_iterator cit = finite_cells_begin(); @@ -1196,14 +1525,15 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence // The Delaunay cells to assess have to be real, i.e. all vertices form // part of the internal or any part of the boundary definition - if (cit->real()) + if + ( + (testCellInfluence[cit->cellIndex()] == 0) + && (cit->real() || cit->hasFarPoint()) + ) { - Foam::point cc(topoint(dual(cit))); + const Foam::point& cc = cit->dual(); - scalar crSqr - ( - magSqr(cc - topoint(cit->vertex(0)->point())) - ); + const scalar crSqr = magSqr(cc - topoint(cit->vertex(0)->point())); // Only if the circumsphere overlaps the boundary of this processor // is there a chance of it overlapping others @@ -1212,7 +1542,7 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence circumcentre.append(cc); circumradiusSqr.append(crSqr); - testCellInfluence[cIOuter] = true; + testCellInfluence[cit->cellIndex()] = 1; } } @@ -1221,6 +1551,9 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence timeCheck("End of testing cell influence"); + Pout<< "Number of quick rejections = " << nQuickRejections << endl; + Pout<< "Number of influences = " << circumcentre.size() << endl; + // Increasing the circumspheres to increase the overlaps and compensate for // floating point errors missing some referrals labelListList circumsphereOverlaps @@ -1242,7 +1575,7 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence ) { // Pre-tested circumsphere potential influence - if (testCellInfluence[cIOuter]) + if (testCellInfluence[cit->cellIndex()] == 1) { const labelList& citOverlaps = circumsphereOverlaps[cIInner]; @@ -1289,6 +1622,70 @@ void Foam::conformalVoronoiMesh::buildParallelInterfaceInfluence cIOuter++; } + +// label nFarPoints = removeProcessorBoundarySeeds(true); +// +// reduce(nFarPoints, sumOp<label>()); +// +// Info<< " Removed " << nFarPoints +// << " far points from the mesh." << endl; + + +// seedProcessorBoundarySurfaces(false); + +// cIInner = 0; +// cIOuter = 0; + + + // Relying on the order of iteration of cells being the same as before +// for +// ( +// Delaunay::Finite_cells_iterator cit = finite_cells_begin(); +// cit != finite_cells_end(); +// ++cit +// ) +// { +// // Pre-tested circumsphere potential influence +// if (testCellInfluence[cIOuter]) +// { +// const labelList& citOverlaps = circumsphereOverlaps[cIInner]; +// +// forAll(citOverlaps, cOI) +// { +// label procI = citOverlaps[cOI]; +// +// recursiveCircumsphereSearch +// ( +// cit, +// procI, +// referralVertices, +// checkedCells, +// parallelInfluencePoints, +// parallelInfluenceIndices, +// targetProcessor +// ); +// } +// +// cIInner++; +// } +// +// cIOuter++; +// } + +// for +// ( +// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin(); +// vit != finite_vertices_end(); +// ++vit +// ) +// { +// if (vit->referred()) +// { +// //Pout << "REMOVE: " << topoint(vit->point()) << endl; +// remove(vit); +// } +// } + referVertices ( targetProcessor, @@ -1344,6 +1741,8 @@ void Foam::conformalVoronoiMesh::referVertices ); } + timeCheck("Start of referVertices " + stageName + " insertion."); + for (label procI = 0; procI < Pstream::nProcs(); procI++) { const labelList& constructMap = pointMap.constructMap()[procI]; @@ -1397,7 +1796,7 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion hitSurfaceLargest = -1; std::list<Facet> facets; - incident_facets(vit, std::back_inserter(facets)); + finite_incident_facets(vit, std::back_inserter(facets)); const Foam::point vert = topoint(vit->point()); @@ -1410,52 +1809,45 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion ++fit ) { - if + const Foam::point edgeMid = + 0.5 + *( + fit->first->dual() + + fit->first->neighbor(fit->second)->dual() + ); + + pointIndexHit surfHit; + label hitSurface; + + geometryToConformTo_.findSurfaceAnyIntersection ( - !is_infinite(fit->first) - && !is_infinite(fit->first->neighbor(fit->second)) - ) - { - const Foam::point edgeMid = - 0.5 - *( - topoint(dual(fit->first)) - + topoint(dual(fit->first->neighbor(fit->second))) - ); + vert, + edgeMid, + surfHit, + hitSurface + ); - pointIndexHit surfHit; - label hitSurface; + if (surfHit.hit()) + { + vectorField norm(1); - geometryToConformTo_.findSurfaceAnyIntersection + allGeometry_[hitSurface].getNormal ( - vert, - edgeMid, - surfHit, - hitSurface + List<pointIndexHit>(1, surfHit), + norm ); - if (surfHit.hit()) - { - vectorField norm(1); - - allGeometry_[hitSurface].getNormal - ( - List<pointIndexHit>(1, surfHit), - norm - ); - - const vector& n = norm[0]; + const vector& n = norm[0]; - const scalar normalProtrusionDistance = - (edgeMid - surfHit.hitPoint()) & n; + const scalar normalProtrusionDistance = + (edgeMid - surfHit.hitPoint()) & n; - if (normalProtrusionDistance > maxProtrusionDistance) - { - surfHitLargest = surfHit; - hitSurfaceLargest = hitSurface; + if (normalProtrusionDistance > maxProtrusionDistance) + { + surfHitLargest = surfHit; + hitSurfaceLargest = hitSurface; - maxProtrusionDistance = normalProtrusionDistance; - } + maxProtrusionDistance = normalProtrusionDistance; } } } @@ -1489,9 +1881,9 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion hitSurfaceLargest = -1; std::list<Facet> facets; - incident_facets(vit, std::back_inserter(facets)); + finite_incident_facets(vit, std::back_inserter(facets)); - Foam::point vert(topoint(vit->point())); + const Foam::point vert = topoint(vit->point()); scalar minIncursionDistance = -maxSurfaceProtrusion(vert); @@ -1502,57 +1894,50 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion ++fit ) { - if + const Foam::point edgeMid = + 0.5 + *( + fit->first->dual() + + fit->first->neighbor(fit->second)->dual() + ); + + pointIndexHit surfHit; + label hitSurface; + + geometryToConformTo_.findSurfaceAnyIntersection ( - !is_infinite(fit->first) - && !is_infinite(fit->first->neighbor(fit->second)) - ) - { - Foam::point edgeMid = - 0.5 - *( - topoint(dual(fit->first)) - + topoint(dual(fit->first->neighbor(fit->second))) - ); + vert, + edgeMid, + surfHit, + hitSurface + ); - pointIndexHit surfHit; - label hitSurface; + if (surfHit.hit()) + { + vectorField norm(1); - geometryToConformTo_.findSurfaceAnyIntersection + allGeometry_[hitSurface].getNormal ( - vert, - edgeMid, - surfHit, - hitSurface + List<pointIndexHit>(1, surfHit), + norm ); - if (surfHit.hit()) - { - vectorField norm(1); - - allGeometry_[hitSurface].getNormal - ( - List<pointIndexHit>(1, surfHit), - norm - ); - - const vector& n = norm[0]; + const vector& n = norm[0]; - scalar normalIncursionDistance = - (edgeMid - surfHit.hitPoint()) & n; + scalar normalIncursionDistance = + (edgeMid - surfHit.hitPoint()) & n; - if (normalIncursionDistance < minIncursionDistance) - { - surfHitLargest = surfHit; - hitSurfaceLargest = hitSurface; + if (normalIncursionDistance < minIncursionDistance) + { + surfHitLargest = surfHit; + hitSurfaceLargest = hitSurface; - minIncursionDistance = normalIncursionDistance; + minIncursionDistance = normalIncursionDistance; - // Info<< nl << "# Incursion: " << endl; - // meshTools::writeOBJ(Info, vert); - // meshTools::writeOBJ(Info, edgeMid); - // Info<< "l Na Nb" << endl; - } + // Info<< nl << "# Incursion: " << endl; + // meshTools::writeOBJ(Info, vert); + // meshTools::writeOBJ(Info, edgeMid); + // Info<< "l Na Nb" << endl; } } } @@ -1948,6 +2333,35 @@ bool Foam::conformalVoronoiMesh::appendToEdgeLocationTree } +Foam::List<Foam::pointIndexHit> +Foam::conformalVoronoiMesh::nearestFeatureEdgeLocations +( + const Foam::point& pt +) const +{ + const scalar exclusionRangeSqr = featureEdgeExclusionDistanceSqr(pt); + + labelList elems + = edgeLocationTreePtr_().findSphere(pt, exclusionRangeSqr); + + DynamicList<pointIndexHit> dynPointHit; + + forAll(elems, elemI) + { + label index = elems[elemI]; + + const Foam::point& pointI + = edgeLocationTreePtr_().shapes().shapePoints()[index]; + + pointIndexHit nearHit(true, pointI, index); + + dynPointHit.append(nearHit); + } + + return dynPointHit; +} + + bool Foam::conformalVoronoiMesh::pointIsNearFeatureEdgeLocation ( const Foam::point& pt @@ -2009,103 +2423,77 @@ bool Foam::conformalVoronoiMesh::nearFeatureEdgeLocation DynamicList<Foam::point>& existingEdgeLocations ) const { - const Foam::point pt = pHit.hitPoint(); + Foam::point pt = pHit.hitPoint(); const scalar exclusionRangeSqr = featureEdgeExclusionDistanceSqr(pt); - pointIndexHit info; - - bool closeToFeatureEdge = pointIsNearFeatureEdgeLocation(pt, info); + bool closeToFeatureEdge = pointIsNearFeatureEdgeLocation(pt); - if (!closeToFeatureEdge) - { - appendToEdgeLocationTree(pt, existingEdgeLocations); - } - else + if (closeToFeatureEdge) { - // Check if the edge location that the new edge location is near to - // "might" be on a different edge. If so, add it anyway. - pointIndexHit edgeHit; - label featureHit = -1; + List<pointIndexHit> nearHits = nearestFeatureEdgeLocations(pt); - geometryToConformTo_.findEdgeNearest - ( - pt, - exclusionRangeSqr, - edgeHit, - featureHit - ); + forAll(nearHits, elemI) + { + pointIndexHit& info = nearHits[elemI]; - const extendedFeatureEdgeMesh& eMesh - = geometryToConformTo_.features()[featureHit]; + // Check if the edge location that the new edge location is near to + // "might" be on a different edge. If so, add it anyway. + pointIndexHit edgeHit; + label featureHit = -1; - const vector& edgeDir = eMesh.edgeDirections()[edgeHit.index()]; + geometryToConformTo_.findEdgeNearest + ( + pt, + exclusionRangeSqr, + edgeHit, + featureHit + ); - const vector lineBetweenPoints = pt - info.hitPoint(); + const extendedFeatureEdgeMesh& eMesh + = geometryToConformTo_.features()[featureHit]; - const scalar cosAngle = vectorTools::cosPhi(edgeDir, lineBetweenPoints); + const vector& edgeDir = eMesh.edgeDirections()[edgeHit.index()]; - // Allow the point to be added if it is almost at right angles to the - // other point. Also check it is not the same point. -// Info<< cosAngle<< " " -// << radToDeg(acos(cosAngle)) << " " -// << searchConeAngle << " " -// << radToDeg(acos(searchConeAngle)) << endl; - if - ( - mag(cosAngle) < searchConeAngle - && mag(lineBetweenPoints) > SMALL - ) - { - closeToFeatureEdge = false; - appendToEdgeLocationTree(pt, existingEdgeLocations); - } - } + const vector lineBetweenPoints = pt - info.hitPoint(); - return closeToFeatureEdge; + const scalar cosAngle + = vectorTools::cosPhi(edgeDir, lineBetweenPoints); - // Searching for the nearest point in existingEdgeLocations using the - // indexedOctree + // Allow the point to be added if it is almost at right angles to + // the other point. Also check it is not the same point. + // Info<< cosAngle<< " " + // << radToDeg(acos(cosAngle)) << " " + // << searchConeAngle << " " + // << radToDeg(acos(searchConeAngle)) << endl; - // Average the points... -// if (info.hit()) -// { -// Foam::point newPt = 0.5*(info.hitPoint() + pt); -// -// pHit.setPoint(newPt); -// -// //boolList toRemove(existingEdgeLocations.size(), false); -// -// forAll(existingEdgeLocations, pI) -// { -// if (pI == info.index()) -// { -// //toRemove[pI] = true; -// edgeLocationTree.remove(pI); -// } -// } -//// -//// pointField newExistingEdgeLocations(existingEdgeLocations.size()); -//// -//// label count = 0; -//// forAll(existingEdgeLocations, pI) -//// { -//// if (toRemove[pI] == false) -//// { -//// newExistingEdgeLocations[count++] = -//// existingEdgeLocations[pI]; -//// } -//// } -//// -//// newExistingEdgeLocations.resize(count); -//// -//// existingEdgeLocations = newExistingEdgeLocations; -//// -//// existingEdgeLocations.append(newPt); -// -// return !info.hit(); -// } + if + ( + mag(cosAngle) < searchConeAngle + && ( + mag(lineBetweenPoints) + > cvMeshControls().pointPairDistanceCoeff()*targetCellSize(pt) + ) + ) + { + pt = edgeHit.hitPoint(); + pHit.setPoint(pt); + closeToFeatureEdge = false; + } + else + { + closeToFeatureEdge = true; + break; + } + } + } + + if (!closeToFeatureEdge) + { + appendToEdgeLocationTree(pt, existingEdgeLocations); + } + return closeToFeatureEdge; } @@ -2265,12 +2653,6 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits featuresHit ); - // Gather edge locations but do not add them to newEdgeLocations inside - // the loop as they will prevent nearby edge locations of different - // types being conformed to. - - DynamicList<Foam::point> currentEdgeLocations; - forAll(edHitsByFeature, i) { const label featureHit = featuresHit[i]; @@ -2281,39 +2663,43 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits { pointIndexHit& edHit = edHits[eHitI]; - if (!nearFeaturePt(edHit.hitPoint()) && keepSurfacePoint) + if (edHit.hit()) { - if - ( - magSqr(edHit.hitPoint() - surfHitI.hitPoint()) - < surfacePtReplaceDistCoeffSqr*cellSizeSqr - ) + if (!nearFeaturePt(edHit.hitPoint())) { - // If the point is within a given distance of a feature - // edge, give control to edge control points instead, - // this will prevent "pits" forming. + if + ( + magSqr(edHit.hitPoint() - surfHitI.hitPoint()) + < surfacePtReplaceDistCoeffSqr*cellSizeSqr + ) + { + // If the point is within a given distance of a + // feature edge, give control to edge control points + // instead, this will prevent "pits" forming. - keepSurfacePoint = false; + keepSurfacePoint = false; - // NEED TO REMOVE FROM THE SURFACE TREE... - } + // NEED TO REMOVE FROM THE SURFACE TREE... + surfacePtLocationTreePtr_().remove + ( + existingSurfacePtLocations.size() + ); + } - if - ( - !nearFeatureEdgeLocation + if ( - edHit, - existingEdgeLocations + !nearFeatureEdgeLocation + ( + edHit, + existingEdgeLocations + ) ) - ) - { - // Do not place edge control points too close to a - // feature point or existing edge control points - - featureEdgeHits.append(edHit); - featureEdgeFeaturesHit.append(featureHit); - - currentEdgeLocations.append(edHit.hitPoint()); + { + // Do not place edge control points too close to a + // feature point or existing edge control points + featureEdgeHits.append(edHit); + featureEdgeFeaturesHit.append(featureHit); + } } } } @@ -2322,7 +2708,6 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits if (keepSurfacePoint) { surfaceHits.append(surfHitI); - hitSurfaces.append(hitSurfaceI); } } diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C index ab7ce33f8563760f144c6aff33f6893a1a7e0078..89afb87134a98ce7b7c9c5ec37afe4764ed4f4b2 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMeshIO.C @@ -125,7 +125,7 @@ void Foam::conformalVoronoiMesh::drawDelaunayCell os << "# cell index: " << label(c->cellIndex()) << endl; os << "# circumradius " - << mag(topoint(dual(c)) - topoint(c->vertex(0)->point())) + << mag(c->dual() - topoint(c->vertex(0)->point())) << endl; for (int i = 0; i < 4; i++) @@ -144,7 +144,7 @@ void Foam::conformalVoronoiMesh::drawDelaunayCell os << "# cicumcentre " << endl; - meshTools::writeOBJ(os, topoint(dual(c))); + meshTools::writeOBJ(os, c->dual()); os << "l " << 1 + offset << " " << 5 + offset << endl; } @@ -167,7 +167,7 @@ void Foam::conformalVoronoiMesh::writePoints ++vit ) { - if (!internalOnly || vit->internalOrBoundaryPoint()) + if (!internalOnly || vit->internalPoint()) { meshTools::writeOBJ(str, topoint(vit->point())); } @@ -241,7 +241,7 @@ void Foam::conformalVoronoiMesh::writeProcessorInterface { if (!cit->farCell()) { - points[cit->cellIndex()] = topoint(dual(cit)); + points[cit->cellIndex()] = cit->dual(); } } diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H index 7ab4f10853427619285ce87430f1ccf14cd31e42..5fc7e970b1131c78607d13f71c91ff3b90aeb276 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCell.H @@ -51,6 +51,7 @@ SourceFiles #include "Swap.H" #include "InfoProxy.H" #include "tetCell.H" +#include "typeInfo.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -154,6 +155,8 @@ public: inline int cellIndex() const; + inline const Foam::point& dual(); + inline bool farCell() const; inline int& filterCount(); @@ -163,6 +166,11 @@ public: //- Is the Delaunay cell real, i.e. any real vertex inline bool real() const; + //- Does the Delaunay cell have a far point + inline bool hasFarPoint() const; + + inline bool hasInternalPoint() const; + //- Does the Dual vertex form part of a processor patch inline bool parallelDualVertex() const; @@ -190,6 +198,8 @@ public: // least one Delaunay vertex outside and at least one inside inline bool boundaryDualVertex() const; + inline bool nearProcBoundary() const; + // Info diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H index 5fbd378f9d9a220845245127070d9624f2ac9bba..6450b01908a44149dbde6d8abc6d8e927f6083b1 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedCellI.H @@ -86,6 +86,24 @@ int CGAL::indexedCell<Gt, Cb>::cellIndex() const } +template<class Gt, class Cb> +const Foam::point& CGAL::indexedCell<Gt, Cb>::dual() +{ +#ifdef CGAL_INEXACT + return reinterpret_cast<const Foam::point&>(this->circumcenter()); +#else + const typename Gt::Point_3& P = this->circumcenter(); + + return + ( + CGAL::to_double(P.x()), + CGAL::to_double(P.y()), + CGAL::to_double(P.z()) + ); +#endif +} + + template<class Gt, class Cb> inline bool CGAL::indexedCell<Gt, Cb>::farCell() const { @@ -112,10 +130,45 @@ inline bool CGAL::indexedCell<Gt, Cb>::real() const { return ( - this->vertex(0)->real() - || this->vertex(1)->real() - || this->vertex(2)->real() - || this->vertex(3)->real() + ( + this->vertex(0)->real() + || this->vertex(1)->real() + || this->vertex(2)->real() + || this->vertex(3)->real() + ) + && + !( + this->vertex(0)->farPoint() + || this->vertex(1)->farPoint() + || this->vertex(2)->farPoint() + || this->vertex(3)->farPoint() + ) + ); +} + + +template<class Gt, class Cb> +inline bool CGAL::indexedCell<Gt, Cb>::hasFarPoint() const +{ + return + ( + this->vertex(0)->farPoint() + || this->vertex(1)->farPoint() + || this->vertex(2)->farPoint() + || this->vertex(3)->farPoint() + ); +} + + +template<class Gt, class Cb> +inline bool CGAL::indexedCell<Gt, Cb>::hasInternalPoint() const +{ + return + ( + this->vertex(0)->internalPoint() + || this->vertex(1)->internalPoint() + || this->vertex(2)->internalPoint() + || this->vertex(3)->internalPoint() ); } @@ -285,4 +338,17 @@ inline bool CGAL::indexedCell<Gt, Cb>::boundaryDualVertex() const } +template<class Gt, class Cb> +inline bool CGAL::indexedCell<Gt, Cb>::nearProcBoundary() const +{ + return + ( + this->vertex(0)->nearProcBoundary() + || this->vertex(1)->nearProcBoundary() + || this->vertex(2)->nearProcBoundary() + || this->vertex(3)->nearProcBoundary() + ); +} + + // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C index 9ad21f92feade712950e9aed5d5cb6d1a21a3eaf..2173e7f5fa7b6be6a0469b004a46e9148f4195f7 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.C @@ -29,7 +29,6 @@ License \*---------------------------------------------------------------------------*/ #include "indexedVertex.H" -//#include "conformalVoronoiMesh.H" #include "point.H" // * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * // diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H index 246020fd172bbeb127089dc9bcc085c0aa7908e2..525c2156e82b60682ca93eb20d44fc4d34d051d7 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertex.H @@ -45,6 +45,7 @@ SourceFiles #include <CGAL/Triangulation_3.h> #include "tensor.H" #include "InfoProxy.H" +#include "point.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -101,6 +102,8 @@ class indexedVertex //- Specify whether the vertex is fixed or movable. bool vertexFixed_; + bool nearProcBoundary_; + public: @@ -198,6 +201,12 @@ public: //- Set the point to be near the boundary inline void setNearBoundary(); + //- Is point internal and near a proc boundary + inline bool nearProcBoundary() const; + + //- Set the point to be near a proc boundary + inline void setNearProcBoundary(); + //- Either master or slave of pointPair. inline bool pairPoint() const; @@ -227,7 +236,7 @@ public: inline bool isVertexFixed() const; //- Fix the vertex so that it can't be moved - inline void setVertexFixed() const; + inline void setVertexFixed(); // inline void operator=(const Delaunay::Finite_vertices_iterator vit) // { diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H index c02ec4df2009489efa9fe91221a666b9f9ae0050..1e225eaa2ed02a2674b57a713fbc142f05d451b4 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformalVoronoiMesh/indexedVertexI.H @@ -38,7 +38,8 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex() type_(vtInternal), alignment_(), targetCellSize_(0.0), - vertexFixed_(false) + vertexFixed_(false), + nearProcBoundary_(false) {} @@ -50,7 +51,8 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(const Point& p) type_(vtInternal), alignment_(), targetCellSize_(0.0), - vertexFixed_(false) + vertexFixed_(false), + nearProcBoundary_(false) {} @@ -67,7 +69,8 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex type_(type), alignment_(), targetCellSize_(0.0), - vertexFixed_(false) + vertexFixed_(false), + nearProcBoundary_(false) {} @@ -79,7 +82,8 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(const Point& p, Cell_handle f) type_(vtInternal), alignment_(), targetCellSize_(0.0), - vertexFixed_(false) + vertexFixed_(false), + nearProcBoundary_(false) {} @@ -91,7 +95,8 @@ inline CGAL::indexedVertex<Gt, Vb>::indexedVertex(Cell_handle f) type_(vtInternal), alignment_(), targetCellSize_(0.0), - vertexFixed_(false) + vertexFixed_(false), + nearProcBoundary_(false) {} @@ -251,6 +256,20 @@ inline void CGAL::indexedVertex<Gt, Vb>::setNearBoundary() } +template<class Gt, class Vb> +inline bool CGAL::indexedVertex<Gt, Vb>::nearProcBoundary() const +{ + return nearProcBoundary_; +} + + +template<class Gt, class Vb> +inline void CGAL::indexedVertex<Gt, Vb>::setNearProcBoundary() +{ + nearProcBoundary_ = true; +} + + template<class Gt, class Vb> inline bool CGAL::indexedVertex<Gt, Vb>::pairPoint() const { @@ -331,7 +350,7 @@ inline bool CGAL::indexedVertex<Gt, Vb>::isVertexFixed() const template<class Gt, class Vb> -inline void CGAL::indexedVertex<Gt, Vb>::setVertexFixed() const +inline void CGAL::indexedVertex<Gt, Vb>::setVertexFixed() { vertexFixed_ = true; } diff --git a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H index d8e5fd016616633358be21ac667efdac3eab22bf..ce56a977aa8e676c6f30f655a2730a90f2e4c3d8 100644 --- a/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H +++ b/applications/utilities/mesh/generation/cvMesh/conformalVoronoiMesh/conformationSurfaces/conformationSurfaces.H @@ -285,7 +285,9 @@ public: ) const; //- Find the nearest points on each feature edge that is within - // a given distance from the sample point + // a given distance from the sample point. Will need to check for + // a hit or a miss because near edges may not have a nearest point + // on them which is perpendicular to the sample point. void findAllNearestEdges ( const point& sample, diff --git a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C index 17ef34fb6f710730e879bcdc4a2005d7b320bc07..024f7d27ecf4203c1684e3295bc7e20ad52692fc 100644 --- a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C +++ b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C @@ -379,6 +379,124 @@ Foam::label Foam::indexedOctree<Type>::compactContents } +template <class Type> +bool Foam::indexedOctree<Type>::quickCircumsphereRejection +( + const label nodeI, + const point& cc, + const scalar crSqr, + const List<scalar>& nearestDistances +) const +{ + const node& nod = nodes_[nodeI]; + + volumeType nodeType = volumeType(nodeTypes_.get(nodeI<<3)); + + //scalar boxDist = nearestDistances[nodeI] + 0.5*nod.bb_.mag(); + scalar boxDist = crSqr + magSqr(cc - nod.bb_.midpoint()); + + if + ( + nodeType == INSIDE + //&& (crSqr < sqr(boxDist)) + && (boxDist < sqr(nearestDistances[nodeI])) + ) + { + return true; + } + else + { + direction octant = nod.bb_.subOctant(cc); + + labelBits index = nod.subNodes_[octant]; + + if (isNode(index)) + { + return quickCircumsphereRejection + ( + getNode(index), + cc, + crSqr, + nearestDistances + ); + } + else + { + return false; + } + } +} + + +template <class Type> +bool Foam::indexedOctree<Type>::quickCircumsphereRejection +( + const point& cc, + const scalar crSqr, + const List<scalar>& nearestDistances +) const +{ + if (nodes_.size()) + { + return quickCircumsphereRejection + ( + 0, + cc, + crSqr, + nearestDistances + ); + } + + return false; +} + + +template <class Type> +Foam::scalar +Foam::indexedOctree<Type>::calcNearestDistance +( + const label nodeI +) const +{ + const node& nod = nodes_[nodeI]; + + const point& nodeCentre = nod.bb_.midpoint(); + + scalar nearestDistance = 0.0; + + pointIndexHit pHit = findNearest(nodeCentre, sqr(GREAT)); + + if (pHit.hit()) + { + nearestDistance = mag(pHit.hitPoint() - nodeCentre); + } + else + { + WarningIn("Foam::indexedOctree<Type>::calcNearestDistance(const label)") + << "Cannot calculate distance of nearest point on surface from " + << "the midpoint of the octree node. Returning distance of zero." + << endl; + } + + return nearestDistance; +} + + +template <class Type> +Foam::List<Foam::scalar> +Foam::indexedOctree<Type>::calcNearestDistance() const +{ + List<scalar> nearestDistances(nodes_.size()); + + forAll(nearestDistances, nodeI) + { + nearestDistances[nodeI] = calcNearestDistance(nodeI); + } + + return nearestDistances; +} + + // Pre-calculates wherever possible the volume status per node/subnode. // Recurses to determine status of lowest level boxes. Level above is // combination of octants below. @@ -540,6 +658,67 @@ Foam::indexedOctree<Type>::getSide // ~~~~~~~~~~~~~~ // + +//template <class Type> +//bool Foam::indexedOctree<Type>::findAnyOverlap +//( +// const label nodeI, +// const point& sample, +// const scalar nearestDistSqr +//) const +//{ +// const node& nod = nodes_[nodeI]; +// +// // Determine order to walk through octants +// FixedList<direction, 8> octantOrder; +// nod.bb_.searchOrder(sample, octantOrder); +// +// // Go into all suboctants (one containing sample first) and update +// // nearest. +// for (direction i = 0; i < 8; i++) +// { +// direction octant = octantOrder[i]; +// +// labelBits index = nod.subNodes_[octant]; +// +// if (isNode(index)) +// { +// label subNodeI = getNode(index); +// +// const treeBoundBox& subBb = nodes_[subNodeI].bb_; +// +// if (overlaps(subBb.min(), subBb.max(), nearestDistSqr, sample)) +// { +// return findAnyOverlap +// ( +// subNodeI, +// sample, +// nearestDistSqr +// ); +// } +// } +// else if (isContent(index)) +// { +// if +// ( +// overlaps +// ( +// nod.bb_, +// octant, +// nearestDistSqr, +// sample +// ) +// ) +// { +// return true; +// } +// } +// } +// +// return false; +//} + + // Find nearest point starting from nodeI template <class Type> void Foam::indexedOctree<Type>::findNearest @@ -1614,7 +1793,6 @@ void Foam::indexedOctree<Type>::traverseNode } } - const node& nod = nodes_[nodeI]; labelBits index = nod.subNodes_[octant]; @@ -1781,6 +1959,11 @@ Foam::pointIndexHit Foam::indexedOctree<Type>::findLine label i = 0; for (; i < 100000; i++) { +// if (isLineInsideOrOutside(nodeI, treeStart, treeEnd)) +// { +// return hitInfo; +// } + // Ray-trace to end of current node. Updates point (either on triangle // in case of hit or on node bounding box in case of miss) @@ -1935,6 +2118,38 @@ Foam::pointIndexHit Foam::indexedOctree<Type>::findLine } +//template <class Type> +//bool Foam::indexedOctree<Type>::isLineInsideOrOutside +//( +// const label nodeI, +// const point& start, +// const point& end +//) const +//{ +// const node& nod = nodes_[nodeI]; +// +// direction startOctant = nod.bb_.subOctant(start); +// direction endOctant = nod.bb_.subOctant(end); +// +// if (startOctant == endOctant) +// { +// volumeType startOctantType +// = volumeType(nodeTypes_.get((nodeI<<3) + startOctant)); +// +// if +// ( +// startOctantType == INSIDE || startOctantType == OUTSIDE +// ) +// { +// //Info<< nodeI << " | " << start << " " << end << endl; +// return true; +// } +// } +// +// return false; +//} + + // Find first intersection template <class Type> Foam::pointIndexHit Foam::indexedOctree<Type>::findLine @@ -2559,6 +2774,27 @@ Foam::scalar& Foam::indexedOctree<Type>::perturbTol() } +//template <class Type> +//bool Foam::indexedOctree<Type>::findAnyOverlap +//( +// const point& sample, +// const scalar startDistSqr +//) const +//{ +// if (nodes_.size()) +// { +// return findAnyOverlap +// ( +// 0, +// sample, +// startDistSqr +// ); +// } +// +// return false; +//} + + template <class Type> Foam::pointIndexHit Foam::indexedOctree<Type>::findNearest ( diff --git a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H index aa493f34e92c40b7adb599d4a15dac0d0d55af1c..40ee7a8a32cf54d0403a53fd477c4046cecf5cbc 100644 --- a/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H +++ b/src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H @@ -201,6 +201,16 @@ private: label& compactI ); + scalar calcNearestDistance(const label nodeI) const; + + bool quickCircumsphereRejection + ( + const label nodeI, + const point& cc, + const scalar crSqr, + const List<scalar>& nearestDistances + ) const; + //- Determine inside/outside per node (mixed if cannot be // determined). Only valid for closed shapes. volumeType calcVolumeType(const label nodeI) const; @@ -320,6 +330,13 @@ private: const bool verbose = false ) const; +// bool isLineInsideOrOutside +// ( +// const label nodeI, +// const point& start, +// const point& end +// ) const; + //- Find any or nearest intersection of line between start and end. pointIndexHit findLine ( @@ -532,6 +549,19 @@ public: const scalar nearestDistSqr ) const; +// bool findAnyOverlap +// ( +// const point& sample, +// const scalar nearestDistSqr +// ) const; +// +// bool findAnyOverlap +// ( +// const label nodeI, +// const point& sample, +// const scalar nearestDistSqr +// ) const; + //- Low level: calculate nearest starting from subnode. void findNearest ( @@ -628,6 +658,16 @@ public: CompareOp& cop ) const; + //- Return a list containing the nearest distance of nodes to any + // shapes + List<scalar> calcNearestDistance() const; + + bool quickCircumsphereRejection + ( + const point& cc, + const scalar crSqr, + const List<scalar>& nearestDistances + ) const; // Write diff --git a/src/edgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.C b/src/edgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.C index 0ebb7b58ab6d0e54c7bc91092e02a51df9fadaa8..81f853aa417f1b3f2f0b264437bcc49ee47695d5 100644 --- a/src/edgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.C +++ b/src/edgeMesh/extendedFeatureEdgeMesh/extendedFeatureEdgeMesh.C @@ -546,6 +546,49 @@ Foam::extendedFeatureEdgeMesh::extendedFeatureEdgeMesh } featurePointNormals_ = featurePointNormals; + + + // Create featurePointEdges_ + // For each feature point, stores a list of edges which are arranged in + // order according to their connectivity + +// featurePointEdges_.setSize(nonFeatureStart_); +// +// Info<< sFeatEds.size() << " " << surf.pointEdges().size() << " " +// << edges().size() << endl; +// +// forAll(sFeatEds, eI) +// { +// Info<< "Edge " << eI << " " << sFeatEds[eI] << " " +// << edges()[eI] << endl; +// } +// +// const edgeList& edges = eds; +// +// for (label i = 0; i < nonFeatureStart_; i++) +// { +// const labelList& ptEds = surf.pointEdges()[i]; +// +// DynamicList<label> tmpFtEdges; +// +// forAll(ptEds, eI) +// { +// const label edgeI = ptEds[eI]; +// const edge& e = sFeatEds[edgeI]; +// +// Info<< "Edges: " << edgeI << " " << e << endl; +// +// forAll(sFeatEds, fEdgeI) +// { +// if (edges[fEdgeI] == e) +// { +// tmpFtEdges.append(fEdgeI); +// } +// } +// } +// +// featurePointEdges_[i] = tmpFtEdges; +// } } @@ -821,7 +864,7 @@ void Foam::extendedFeatureEdgeMesh::allNearestFeatureEdges if (!hitPoint.hit()) { - nearHit = pointIndexHit(true, hitPoint.missPoint(), hitIndex); + nearHit = pointIndexHit(false, hitPoint.missPoint(), hitIndex); } else {