diff --git a/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C index e3fce9addb..394b952d40 100644 --- a/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C +++ b/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C @@ -70,6 +70,10 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh featureVertices_(), featurePointLocations_(), featurePointTree_(), + sizeAndAlignmentLocations_(), + storedSizes_(), + storedAlignments_(), + sizeAndAlignmentTree_(), initialPointsMethod_ ( initialPointsMethod::New @@ -837,12 +841,66 @@ void Foam::conformalVoronoiMesh::insertInitialPoints() Info<< nl << "Inserting initial points" << endl; - insertPoints(initialPointsMethod_->initialPoints()); + std::vector initPts = initialPointsMethod_->initialPoints(); + + insertPoints(initPts); if(cvMeshControls().objOutput()) { writePoints("initialPoints.obj", true); } + + storeSizesAndAlignments(initPts); + + +} + + +void Foam::conformalVoronoiMesh::storeSizesAndAlignments +( + const std::vector& initPts +) +{ + timeCheck(); + + Info << " Initialise stored data" << endl; + + sizeAndAlignmentLocations_.setSize(initPts.size()); + + storedSizes_.setSize(sizeAndAlignmentLocations_.size()); + + storedAlignments_.setSize(sizeAndAlignmentLocations_.size()); + + forAll(sizeAndAlignmentLocations_, i) + { + sizeAndAlignmentLocations_[i] = topoint(initPts[i]); + + storedSizes_[i] = targetCellSize(sizeAndAlignmentLocations_[i]); + + storedAlignments_[i] = requiredAlignment(sizeAndAlignmentLocations_[i]); + } + + timeCheck(); + + Info<< " Initialise sizeAndAlignmentTree_" << endl; + + buildSizeAndAlignmentTree(); + + timeCheck(); + + Info<< " Initialised" << endl; +} + + +const Foam::indexedOctree& +Foam::conformalVoronoiMesh::sizeAndAlignmentTree() const +{ + if (sizeAndAlignmentTree_.empty()) + { + buildSizeAndAlignmentTree(); + } + + return sizeAndAlignmentTree_(); } @@ -1122,6 +1180,30 @@ void Foam::conformalVoronoiMesh::buildEdgeLocationTree } +void Foam::conformalVoronoiMesh::buildSizeAndAlignmentTree() const +{ + treeBoundBox overallBb(geometryToConformTo_.bounds()); + + Random rndGen(627391); + + overallBb.extend(rndGen, 1E-4); + overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); + + sizeAndAlignmentTree_.reset + ( + new indexedOctree + ( + treeDataPoint(sizeAndAlignmentLocations_), + overallBb, // overall search domain + 10, // max levels + 10.0, // maximum ratio of cubes v.s. cells + 100.0 // max. duplicity; n/a since no bounding boxes. + ) + ); +} + + void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits ( const Triangulation::Finite_vertices_iterator& vit, @@ -1857,6 +1939,8 @@ void Foam::conformalVoronoiMesh::conformToSurface() // Initialise the edgeLocationTree buildEdgeLocationTree(edgeLocationTree, existingEdgeLocations); + label initialTotalHits = 0; + // Initial surface protrusion conformation - nearest surface point { Info<< " EDGE DISTANCE COEFFS HARD-CODED." << endl; @@ -1938,18 +2022,35 @@ void Foam::conformalVoronoiMesh::conformToSurface() featureEdgeFeaturesHit, "edgeConformationLocations_initial.obj" ); + + initialTotalHits = surfaceHits.size() + featureEdgeHits.size(); } label iterationNo = 0; - label maxIterations = 5; - Info << " MAX ITERATIONS HARD CODED TO "<< maxIterations << endl; + label maxIterations = 10; - // Set totalHits to a positive value to enter the while loop on the first - // iteration - label totalHits = 1; + Info<< nl << " MAX ITERATIONS HARD CODED TO "<< maxIterations << endl; - while (totalHits > 0 && iterationNo < maxIterations) + scalar iterationToIntialHitRatioLimit = 0.01; + + label hitLimit = label(iterationToIntialHitRatioLimit*initialTotalHits); + + Info<< " STOPPING ITERATIONS WHEN TOTAL NUMBER OF HITS DROPS BELOW " + << iterationToIntialHitRatioLimit << " (HARD CODED) OF INITIAL HITS (" + << hitLimit << ")" + << endl; + + // Set totalHits to a large enough positive value to enter the while loop on + // the first iteration + label totalHits = initialTotalHits; + + while + ( + totalHits > 0 + && totalHits > hitLimit + && iterationNo < maxIterations + ) { Info<< " EDGE DISTANCE COEFFS HARD-CODED." << endl; scalar edgeSearchDistCoeffSqr = sqr(1.25); @@ -2039,6 +2140,12 @@ void Foam::conformalVoronoiMesh::conformToSurface() << "Maximum surface conformation iterations (" << maxIterations << ") reached." << endl; } + + if (totalHits < hitLimit) + { + Info<< nl << " totalHits (" << totalHits << ") less than limit (" + << hitLimit << "), stopping iterations" << endl; + } } // Info<< nl << " After iterations, check penetrations" << endl; @@ -2116,7 +2223,36 @@ void Foam::conformalVoronoiMesh::move() dualVertices.setSize(dualVerti); - Info<< nl << " Calculating target cell alignment and size" << endl; + timeCheck(); + + // Info<< nl << " Calculating target cell alignment and size" << endl; + + // for + // ( + // Triangulation::Finite_vertices_iterator vit = finite_vertices_begin(); + // vit != finite_vertices_end(); + // vit++ + // ) + // { + // if (vit->internalOrBoundaryPoint()) + // { + // point pt(topoint(vit->point())); + + // vit->alignment() = requiredAlignment(pt); + + // vit->targetCellSize() = targetCellSize(pt); + // } + // } + + // timeCheck(); + + // Info<< " Calculated" << endl; + + Info<< nl << " Looking up target cell alignment and size" << endl; + + scalar spanSqr = cvMeshControls().spanSqr(); + + const indexedOctree& tree = sizeAndAlignmentTree(); for ( @@ -2129,14 +2265,18 @@ void Foam::conformalVoronoiMesh::move() { point pt(topoint(vit->point())); - vit->alignment() = requiredAlignment(pt); + pointIndexHit info = tree.findNearest(pt, spanSqr); - vit->targetCellSize() = targetCellSize(pt); + vit->alignment() = storedAlignments_[info.index()]; + + vit->targetCellSize() = storedSizes_[info.index()]; } } timeCheck(); + Info<< " Looked up" << endl; + Info<< nl << " Looping over all dual faces" << endl; vectorField cartesianDirections(3); diff --git a/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H b/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H index 6568a46b32..41b5453479 100644 --- a/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H +++ b/src/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H @@ -119,6 +119,19 @@ class conformalVoronoiMesh //- Search tree for feature point locations mutable autoPtr > featurePointTree_; + //- Store locations where the cell size and alignments will be + // pre-calculated and looked up + pointField sizeAndAlignmentLocations_; + + //- Stored cell size at sizeAndAlignmentLocations_ + scalarField storedSizes_; + + //- Stored alignments at sizeAndAlignmentLocations_ + tensorField storedAlignments_; + + //- Search tree for size and alignment lookup points + mutable autoPtr > sizeAndAlignmentTree_; + //- Method for inserting initial points. Runtime selectable. autoPtr initialPointsMethod_; @@ -279,6 +292,13 @@ class conformalVoronoiMesh // initialPointsMethod void insertInitialPoints(); + //- Store data for sizeAndAlignmentLocations_, storedSizes_ and + // storedAlignments_ and initialise the sizeAndAlignmentTree_ + void storeSizesAndAlignments(const std::vector& initPts); + + //- Demand driven construction of octree for and alignment points + const indexedOctree& sizeAndAlignmentTree() const; + //- Check to see if dual cell specified by given vertex iterator // intersects the boundary and hence reqires a point-pair. bool dualCellSurfaceAnyIntersection @@ -313,13 +333,16 @@ class conformalVoronoiMesh autoPtr >& edgeLocationTree ) const; - //- build or rebuild the edgeLocationTree + //- Build or rebuild the edgeLocationTree void buildEdgeLocationTree ( autoPtr >& edgeLocationTree, const pointField& existingEdgeLocations ) const; + //- Build or rebuild the sizeAndAlignmentTree + void buildSizeAndAlignmentTree() const; + //- Process the surface conformation locations to decide which surface // and edge conformation locations to add. void addSurfaceAndEdgeHits