Skip to content
Snippets Groups Projects
meshOctreeCreatorAdjustOctreeToSurface.C 35.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • franjo's avatar
    franjo committed
    /*---------------------------------------------------------------------------*\
      =========                 |
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
      \\      /  F ield         | cfMesh: A library for mesh generation
    
    franjo's avatar
    franjo committed
       \\    /   O peration     |
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        \\  /    A nd           | Author: Franjo Juretic (franjo.juretic@c-fields.com)
         \\/     M anipulation  | Copyright (C) Creative Fields, Ltd.
    
    franjo's avatar
    franjo committed
    -------------------------------------------------------------------------------
    License
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        This file is part of cfMesh.
    
    franjo's avatar
    franjo committed
    
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        cfMesh is free software; you can redistribute it and/or modify it
    
    franjo's avatar
    franjo committed
        under the terms of the GNU General Public License as published by the
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        Free Software Foundation; either version 3 of the License, or (at your
    
    franjo's avatar
    franjo committed
        option) any later version.
    
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        cfMesh is distributed in the hope that it will be useful, but WITHOUT
    
    franjo's avatar
    franjo committed
        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
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        along with cfMesh.  If not, see <http://www.gnu.org/licenses/>.
    
    franjo's avatar
    franjo committed
    
    Description
    
    \*---------------------------------------------------------------------------*/
    
    #include "meshOctreeCreator.H"
    #include "triSurf.H"
    
    #include "edgeMesh.H"
    
    franjo's avatar
    franjo committed
    #include "boundBox.H"
    #include "demandDrivenData.H"
    #include "objectRefinementList.H"
    #include "VRWGraph.H"
    #include "meshOctreeModifier.H"
    
    Franjo's avatar
    Franjo committed
    #include "helperFunctions.H"
    
    franjo's avatar
    franjo committed
    #include "HashSet.H"
    
    
    #include "coordinateModifier.H"
    
    #include "surfaceMeshGeometryModification.H"
    
    Franjo's avatar
    Franjo committed
    #include "edgeMeshGeometryModification.H"
    
    franjo's avatar
    franjo committed
    #include <omp.h>
    
    franjo's avatar
    franjo committed
    
    //#define OCTREETiming
    //#define DEBUGSearch
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    namespace Foam
    {
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    void meshOctreeCreator::refineBoundary()
    {
        meshOctreeModifier octreeModifier(octree_);
        const LongList<meshOctreeCube*>& leaves = octreeModifier.leavesAccess();
    
        //- refine DATA boxes to the given level
    
        Info << "Refining boundary boxes to the given size" << endl;
    
    franjo's avatar
    franjo committed
    
    
    franjo's avatar
    franjo committed
        do
        {
    
    franjo's avatar
    franjo committed
    
            # ifdef OCTREETiming
            const scalar startIter = omp_get_wtime();
            # endif
    
    
            labelList refineCubes(leaves.size(), 0);
    
            scalarList rThickness(leaves.size(), 0.0);
    
            bool useNLayers(false);
    
    franjo's avatar
    franjo committed
    
            //- select boxes which need to be refined
    
            # pragma omp parallel for schedule(dynamic, 100)
    
    franjo's avatar
    franjo committed
            forAll(leaves, leafI)
            {
                const meshOctreeCube& oc = *leaves[leafI];
                # ifdef DEBUGSearch
                Info << "Checking leaf " << oc << endl;
                Info << "Leaf has elements " << oc.hasContainedElements() << endl;
                # endif
    
                if( oc.hasContainedElements() )
                {
                    const label elRowI = oc.containedElements();
                    const VRWGraph& containedTriangles =
                        oc.slotPtr()->containedTriangles_;
    
    
                    bool refine(false);
    
    franjo's avatar
    franjo committed
                    forAllRow(containedTriangles, elRowI, tI)
                    {
                        const label triI = containedTriangles(elRowI, tI);
    
                        if( surfRefLevel_[triI] > oc.level() )
                        {
    
                            refine = true;
                        }
    
                        if( surfRefThickness_[triI] > VSMALL )
                        {
                            useNLayers = true;
    
    Franjo's avatar
    Franjo committed
    
    
                                    rThickness[leafI],
                                    surfRefThickness_[triI]
    
    franjo's avatar
    franjo committed
                        }
                    }
    
    
                    if( refine )
                    {
                        refineCubes[leafI] = 1;
    
            //- mark additional boxes for refinement to achieve
            //- correct refinement distance
            reduce(useNLayers, maxOp<label>());
    
            reduce(changed, maxOp<bool>());
            if( useNLayers && changed )
    
                octreeModifier.refineSelectedBoxesAndAdditionalLayers
                (
                    refineCubes,
    
    Franjo's avatar
    Franjo committed
                    rThickness
    
                );
            }
            else if( changed )
            {
                //- refine boxes
                octreeModifier.refineSelectedBoxes(refineCubes, hexRefinement_);
    
    franjo's avatar
    franjo committed
    
            # ifdef OCTREETiming
            const scalar refTime = omp_get_wtime();
            Info << "Time for refinement " << (refTime-startIter) << endl;
            # endif
    
            if( Pstream::parRun() )
            {
    
    franjo's avatar
    franjo committed
                {
                    octreeModifier.distributeLeavesToProcessors();
    
                    # ifdef OCTREETiming
                    const scalar distTime = omp_get_wtime();
                    Info << "Time for distributing data to processors "
                         << (distTime-refTime) << endl;
                    # endif
    
                    loadDistribution();
    
                    # ifdef OCTREETiming
                    Info << "Time for load distribution "
                        << (omp_get_wtime()-distTime) << endl;
                    # endif
                }
            }
    
    
    franjo's avatar
    franjo committed
    
    
        Info << "Finished refining boundary boxes" << endl;
    
    franjo's avatar
    franjo committed
    }
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    void meshOctreeCreator::refineBoxesContainedInObjects()
    {
        if( !meshDictPtr_ || !meshDictPtr_->found("objectRefinements") )
        {
            return;
        }
    
        Info << "Refining boxes inside objects" << endl;
        objectRefinementList refObjects;
    
    
    Franjo's avatar
    Franjo committed
        // Read objects
    
        if( meshDictPtr_->isDict("objectRefinements") )
        {
            const dictionary& dict = meshDictPtr_->subDict("objectRefinements");
            const wordList objectNames = dict.toc();
    
    franjo's avatar
    franjo committed
    
    
            refObjects.setSize(objectNames.size());
    
    franjo's avatar
    franjo committed
    
    
            forAll(refObjects, objectI)
            {
                const entry& objectEntry =
                    dict.lookupEntry(objectNames[objectI], false, false);
    
                refObjects.set
    
    franjo's avatar
    franjo committed
                (
    
                    objectI,
                    objectRefinement::New
                    (
                        objectEntry.keyword(),
                        objectEntry.dict()
                    )
                );
            }
    
    franjo's avatar
    franjo committed
        }
    
        else
        {
            Istream& is = meshDictPtr_->lookup("objectRefinements");
    
    franjo's avatar
    franjo committed
    
    
            PtrList<entry> objectEntries(is);
            refObjects.setSize(objectEntries.size());
    
            forAll(refObjects, objectI)
            {
                refObjects.set
                (
                    objectI,
                    objectRefinement::New
                    (
                        objectEntries[objectI].keyword(),
                        objectEntries[objectI].dict()
                    )
                );
            }
    
            objectEntries.clear();
        }
    
    franjo's avatar
    franjo committed
    
    
        coordinateModifier* cModPtr = NULL;
    
        if( meshDictPtr_->found("anisotropicSources") )
        {
            cModPtr =
                new coordinateModifier
                (
                    meshDictPtr_->subDict("anisotropicSources")
                );
        }
    
    
    Franjo's avatar
    Franjo committed
        //- calculate refinement levels
        const scalar s(readScalar(meshDictPtr_->lookup("maxCellSize")));
    
    franjo's avatar
    franjo committed
        List<direction> refLevels(refObjects.size(), globalRefLevel_);
    
    Franjo's avatar
    Franjo committed
        forAll(refObjects, oI)
    
    franjo's avatar
    franjo committed
        {
    
    Franjo's avatar
    Franjo committed
            //- calculate additional refinement levels from cell size
            refObjects[oI].calculateAdditionalRefLevels(s);
    
    franjo's avatar
    franjo committed
    
    
    Franjo's avatar
    Franjo committed
            refLevels[oI] += refObjects[oI].additionalRefinementLevels();
        }
    
    franjo's avatar
    franjo committed
    
    
    Franjo's avatar
    Franjo committed
        //- read refinement thickness
        scalarList refThickness(refObjects.size(), 0.0);
    
        forAll(refThickness, oI)
            refThickness[oI] = refObjects[oI].refinementThickness();
    
    franjo's avatar
    franjo committed
    
        forAll(refLevels, i)
            Info << "Ref level for object " << refObjects[i].name()
    
    Franjo's avatar
    Franjo committed
                << " is " << label(refLevels[i])
                << " refinement thickness " << refThickness[i] << endl;
    
    franjo's avatar
    franjo committed
    
        if( octree_.neiProcs().size() )
            forAll(refObjects, oI)
            {
                label l = refLevels[oI];
                reduce(l, maxOp<label>());
                refLevels[oI] = l;
            }
    
        //- start refining boxes inside the objects
        const boundBox& rootBox = octree_.rootBox();
        meshOctreeModifier octreeModifier(octree_);
        const LongList<meshOctreeCube*>& leaves = octreeModifier.leavesAccess();
    
    
    franjo's avatar
    franjo committed
        do
        {
            # ifdef OCTREETiming
            const scalar startIter = omp_get_wtime();
            # endif
    
    
    franjo's avatar
    franjo committed
    
    
            labelList refineCubes(leaves.size(), 0);
    
            scalarList rThickness(leaves.size(), 0.0);
    
            bool useNLayers(false);
    
    franjo's avatar
    franjo committed
    
            //- select boxes which need to be refined
    
    franjo's avatar
    franjo committed
            # pragma omp parallel for if( leaves.size() > 1000 ) \
    
    franjo's avatar
    franjo committed
            forAll(leaves, leafI)
            {
                const meshOctreeCube& oc = *leaves[leafI];
    
                if( oc.cubeType() & meshOctreeCubeBasic::OUTSIDE )
                    continue;
    
                boundBox bb;
                oc.cubeBox(rootBox, bb.min(), bb.max());
    
    
                if( cModPtr )
                {
                    //- transform bounding boxes into non-modified coordinates
                    bb.min() = cModPtr->backwardModifiedPoint(bb.min());
                    bb.max() = cModPtr->backwardModifiedPoint(bb.max());
                }
    
    
                bool refine(false);
    
    franjo's avatar
    franjo committed
                forAll(refObjects, oI)
    
    Franjo's avatar
    Franjo committed
                    if( refObjects[oI].intersectsObject(bb) )
    
    franjo's avatar
    franjo committed
                    {
                        # ifdef DEBUGSearch
                        Info << "Marking leaf " << leafI
                            << " for refinement" << endl;
                        # endif
    
    
    Franjo's avatar
    Franjo committed
                        if( oc.level() < refLevels[oI] )
                            refine = true;
    
    
                        if( refThickness[oI] > VSMALL )
                        {
    
                            rThickness[leafI] =
                                Foam::max(rThickness[leafI], refThickness[oI]);
    
    
                            useNLayers = true;
                        }
    
    franjo's avatar
    franjo committed
                    }
    
                }
    
                if( refine )
                {
                    refineCubes[leafI] = 1;
    
                }
            }
    
            //- mark additional boxes for refinement to achieve
            //- correct refinement distance
            reduce(useNLayers, maxOp<label>());
    
            reduce(changed, maxOp<bool>());
            if( useNLayers && changed )
    
                octreeModifier.refineSelectedBoxesAndAdditionalLayers
                (
                    refineCubes,
    
    Franjo's avatar
    Franjo committed
                    rThickness
    
                );
            }
            else if( changed )
            {
                //- refine boxes
                octreeModifier.refineSelectedBoxes(refineCubes, hexRefinement_);
    
    franjo's avatar
    franjo committed
            }
    
            # ifdef OCTREETiming
            const scalar refTime = omp_get_wtime();
            Info << "Time for refinement " << (refTime-startIter) << endl;
            # endif
    
            if( octree_.neiProcs().size() != 0 )
            {
    
    franjo's avatar
    franjo committed
                {
                    octreeModifier.distributeLeavesToProcessors();
    
                    # ifdef OCTREETiming
                    const scalar distTime = omp_get_wtime();
                    Info << "Time for distributing data to processors "
                    << (distTime-refTime) << endl;
                    # endif
    
                    loadDistribution(false);
    
                    # ifdef OCTREETiming
                    Info << "Time for load distribution "
                    << (omp_get_wtime()-distTime) << endl;
                    # endif
                }
            }
    
    
    franjo's avatar
    franjo committed
    
    
        //- delete coordinate modifier if it exists
        deleteDemandDrivenData(cModPtr);
    
    
    franjo's avatar
    franjo committed
        Info << "Finished refinement of boxes inside objects" << endl;
    
        //- set up inside-outside information
        createInsideOutsideInformation();
    }
    
    
    Franjo's avatar
    Franjo committed
    void meshOctreeCreator::refineBoxesIntersectingSurfaces()
    {
        if( !meshDictPtr_ || !meshDictPtr_->found("surfaceMeshRefinement") )
        {
            return;
        }
    
        Info << "Refining boxes intersecting surface meshes" << endl;
    
        label nMarked;
    
        //- read surface meshes and calculate the refinement level for each
        //- surface mesh
        const dictionary& surfDict = meshDictPtr_->subDict("surfaceMeshRefinement");
        const wordList surfaces = surfDict.toc();
    
        PtrList<const triSurf> surfaceMeshesPtr(surfaces.size());
    
    Franjo's avatar
    Franjo committed
        List<direction> refLevels(surfaces.size(), globalRefLevel_);
    
        scalarList refThickness(surfaces.size(), 0.0);
    
    Franjo's avatar
    Franjo committed
    
        //- load surface meshes into memory
    
    Franjo's avatar
    Franjo committed
        {
            const dictionary& dict = surfDict.subDict(surfaces[surfI]);
    
            const fileName fName(dict.lookup("surfaceFile"));
    
    
            if( meshDictPtr_->found("anisotropicSources") )
            {
                triSurf origSurf(fName);
                surfaceMeshGeometryModification surfMod(origSurf, *meshDictPtr_);
    
                surfaceMeshesPtr.set(surfI, surfMod.modifyGeometry());
            }
            else
            {
                surfaceMeshesPtr.set(surfI, new triSurf(fName));
            }
    
    Franjo's avatar
    Franjo committed
    
            direction addLevel(0);
            if( dict.found("cellSize") )
            {
                scalar s(readScalar(meshDictPtr_->lookup("maxCellSize")));
    
                const scalar cs = readScalar(dict.lookup("cellSize"));
    
                do
                {
                    nMarked = 0;
                    if( cs <= s * (1.+SMALL) )
                    {
                        ++nMarked;
                        ++addLevel;
                    }
    
                    s /= 2.0;
    
                } while( nMarked != 0 );
            }
            else if( dict.found("additionalRefinementLevels") )
            {
                addLevel =
                    readLabel(dict.lookup("additionalRefinementLevels"));
            }
    
    
            if( dict.found("refinementThickness") )
            {
                refThickness[surfI] =
                    readScalar(dict.lookup("refinementThickness"));
            }
    
    
    Franjo's avatar
    Franjo committed
            //- set the refinement level for the current surface
            refLevels[surfI] += addLevel;
        }
    
        if( octree_.neiProcs().size() )
            forAll(refLevels, oI)
            {
                label l = refLevels[oI];
                reduce(l, maxOp<label>());
                refLevels[oI] = l;
            }
    
        //- start refining boxes intersecting triangles in each refinement surface
        const boundBox& rootBox = octree_.rootBox();
        const vector tol = SMALL * rootBox.span();
        meshOctreeModifier octreeModifier(octree_);
        const LongList<meshOctreeCube*>& leaves = octreeModifier.leavesAccess();
    
        DynList<label> leavesInBox;
    
        bool changed;
    
    Franjo's avatar
    Franjo committed
        do
        {
            # ifdef OCTREETiming
            const scalar startIter = omp_get_wtime();
            # endif
    
    
            changed = false;
    
            labelList refineCubes(leaves.size(), 0);
    
            labelList nLayers(leaves.size(), 0);
    
            scalarField rThickness(leaves.size(), 0.0);
    
            bool useNLayers(false);
    
            //- select boxes that need to be refined
    
    Franjo's avatar
    Franjo committed
            forAll(surfaceMeshesPtr, surfI)
            {
                const triSurf& surf = surfaceMeshesPtr[surfI];
                const pointField& points = surf.points();
    
    
                const direction surfLevel = refLevels[surfI];
                const scalar sThickness = refThickness[surfI];
    
    
    Franjo's avatar
    Franjo committed
                # ifdef USE_OMP
                # pragma omp parallel for \
    
                reduction( + : nMarked) schedule(dynamic, 10) private(leavesInBox)
    
    Franjo's avatar
    Franjo committed
                # endif
                forAll(surf, triI)
                {
                    //- find the bounding box of the current triangle
                    const labelledTri& tri = surf[triI];
    
    Franjo's avatar
    Franjo committed
                    boundBox triBB(points[tri[0]], points[tri[0]]);
                    for(label pI=1;pI<3;++pI)
                    {
                        triBB.min() = Foam::min(triBB.min(), points[tri[pI]]);
                        triBB.max() = Foam::max(triBB.max(), points[tri[pI]]);
                    }
    
                    triBB.min() -= tol;
                    triBB.max() += tol;
    
                    //- find octree leaves inside the bounding box
                    leavesInBox.clear();
                    octree_.findLeavesContainedInBox(triBB, leavesInBox);
    
                    //- check which of the leaves are intersected by the triangle
                    forAll(leavesInBox, i)
                    {
                        const label leafI = leavesInBox[i];
    
                        const meshOctreeCube& oc = *leaves[leafI];
    
    
                        if( oc.intersectsTriangleExact(surf, rootBox, triI) )
    
                            # ifdef DEBUGSearch
                            Info << "Marking leaf " << leafI
                                << " with coordinates " << oc
                                << " for refinement" << endl;
                            # endif
    
                            if( oc.level() < surfLevel )
                            {
                                //- mark boxes for refinement
    
                                changed = true;
    
                                refineCubes[leafI] = 1;
    
                            if( sThickness > VSMALL )
                            {
                                useNLayers = true;
    
                                const scalar cs = oc.size(rootBox);
                                const label numLayers =
                                    ceil(sThickness / cs);
    
                                nLayers[leafI] =
                                    Foam::max
                                    (
                                        nLayers[leafI],
                                        Foam::max(numLayers, 1)
                                    );
    
    
    Franjo's avatar
    Franjo committed
                                rThickness[leafI] =
                                    max(rThickness[leafI], sThickness);
    
            //- mark additional boxes for refinement to achieve
            //- correct refinement distance
            reduce(useNLayers, maxOp<label>());
    
            reduce(changed, maxOp<bool>());
    
                octreeModifier.refineSelectedBoxesAndAdditionalLayers
    
                (
                    refineCubes,
    
    Franjo's avatar
    Franjo committed
                    rThickness
    
            }
            else if( changed )
            {
                //- refine boxes
                octreeModifier.refineSelectedBoxes(refineCubes, hexRefinement_);
            }
    
    
            # ifdef OCTREETiming
            const scalar refTime = omp_get_wtime();
            Info << "Time for refinement " << (refTime-startIter) << endl;
            # endif
    
            if( octree_.neiProcs().size() != 0 )
            {
    
                reduce(changed, maxOp<bool>());
                if( changed )
    
                {
                    octreeModifier.distributeLeavesToProcessors();
    
                    # ifdef OCTREETiming
                    const scalar distTime = omp_get_wtime();
                    Info << "Time for distributing data to processors "
                    << (distTime-refTime) << endl;
                    # endif
    
                    loadDistribution(false);
    
                    # ifdef OCTREETiming
                    Info << "Time for load distribution "
                    << (omp_get_wtime()-distTime) << endl;
                    # endif
                }
            }
    
        } while( changed );
    
    
        Info << "Finished refinement of boxes intersecting surface meshes" << endl;
    }
    
    void meshOctreeCreator::refineBoxesIntersectingEdgeMeshes()
    {
        if( !meshDictPtr_ || !meshDictPtr_->found("edgeMeshRefinement") )
        {
            return;
        }
    
        Info << "Refining boxes intersecting edge meshes" << endl;
    
        //- read edge meshes and calculate the refinement level for each
        //- edge mesh
        const dictionary& edgeDict = meshDictPtr_->subDict("edgeMeshRefinement");
        const wordList edgeMeshNames = edgeDict.toc();
    
    Franjo's avatar
    Franjo committed
    
    
        PtrList<const edgeMesh> edgeMeshesPtr(edgeMeshNames.size());
        List<direction> refLevels(edgeMeshNames.size(), globalRefLevel_);
        scalarList refThickness(edgeMeshNames.size(), 0.0);
    
        //- load edge meshes into memory
    
    Franjo's avatar
    Franjo committed
        forAll(edgeMeshNames, emI)
    
        {
            const dictionary& dict = edgeDict.subDict(edgeMeshNames[emI]);
    
            const fileName fName(dict.lookup("edgeFile"));
    
            if( meshDictPtr_->found("anisotropicSources") )
            {
    
    Franjo's avatar
    Franjo committed
                edgeMesh origEdgeMesh(fName);
                edgeMeshGeometryModification edgeMod(origEdgeMesh, *meshDictPtr_);
    
    Franjo's avatar
    Franjo committed
                edgeMeshesPtr.set(emI, edgeMod.modifyGeometry());
    
            }
            else
            {
                edgeMeshesPtr.set(emI, new edgeMesh(fName));
            }
    
    
            direction addLevel(0);
            if( dict.found("cellSize") )
            {
                scalar s(readScalar(meshDictPtr_->lookup("maxCellSize")));
    
                const scalar cs = readScalar(dict.lookup("cellSize"));
    
                do
                {
                    nMarked = 0;
                    if( cs <= s * (1.+SMALL) )
                    {
                        ++nMarked;
                        ++addLevel;
                    }
    
                    s /= 2.0;
    
                } while( nMarked != 0 );
            }
            else if( dict.found("additionalRefinementLevels") )
            {
                addLevel =
                    readLabel(dict.lookup("additionalRefinementLevels"));
            }
    
            if( dict.found("refinementThickness") )
            {
                refThickness[emI] =
                    readScalar(dict.lookup("refinementThickness"));
            }
    
            //- set the refinement level for the current mesh
            refLevels[emI] += addLevel;
        }
    
        if( octree_.neiProcs().size() )
            forAll(refLevels, oI)
            {
                label l = refLevels[oI];
                reduce(l, maxOp<label>());
                refLevels[oI] = l;
            }
    
        //- start refining boxes intersecting triangles in each refinement surface
        const boundBox& rootBox = octree_.rootBox();
        const vector tol = SMALL * rootBox.span();
        meshOctreeModifier octreeModifier(octree_);
        const LongList<meshOctreeCube*>& leaves = octreeModifier.leavesAccess();
        DynList<label> leavesInBox, intersectedLeaves;
    
    
            # ifdef OCTREETiming
            const scalar startIter = omp_get_wtime();
            # endif
    
    
            labelList refineCubes(leaves.size(), 0);
    
            scalarList rThickness(leaves.size(), 0.0);
    
            bool useNLayers(false);
    
            //- select boxes which need to be refined
    
    Franjo's avatar
    Franjo committed
            forAll(edgeMeshNames, emI)
    
            {
                const edgeMesh& edgeMesh = edgeMeshesPtr[emI];
                const pointField& points = edgeMesh.points();
                const edgeList& edges = edgeMesh.edges();
    
                # ifdef USE_OMP
    
                # pragma omp parallel for schedule(dynamic, 10) \
    
                private(leavesInBox,intersectedLeaves)
                # endif
                forAll(edges, edgeI)
                {
                    //- find the bounding box of the current triangle
                    const edge& e = edges[edgeI];
    
                    const point& sp = points[e.start()];
                    const point& ep = points[e.end()];
    
                    boundBox edgeBB(sp, ep);
    
                    edgeBB.min() -= tol;
                    edgeBB.max() += tol;
    
                    //- find octree leaves inside the bounding box
                    leavesInBox.clear();
                    octree_.findLeavesContainedInBox(edgeBB, leavesInBox);
    
                    //- check which of the leaves are intersected by the triangle
                    intersectedLeaves.clear();
                    forAll(leavesInBox, i)
                    {
                        const label leafI = leavesInBox[i];
    
                        const meshOctreeCube& oc = *leaves[leafI];
    
                        if( oc.intersectsLine(rootBox, sp, ep) )
                        {
                            intersectedLeaves.append(leafI);
    
                            if( oc.level() < refLevels[emI] )
                            {
                                # ifdef DEBUGSearch
                                Info << "Marking leaf " << leafI
                                    << " with coordinates " << oc
                                    << " for refinement" << endl;
                                # endif
    
                                refineCubes[leafI] = 1;
    
                            }
                        }
                    }
    
                    if( refThickness[emI] > VSMALL )
                    {
                        useNLayers = true;
    
                        forAll(intersectedLeaves, i)
                        {
                            const label leafI = intersectedLeaves[i];
    
    
                            rThickness[leafI] =
                                Foam::max(rThickness[leafI], refThickness[emI]);
    
                        }
                    }
                }
            }
    
            //- mark additional boxes for refinement to achieve
            //- correct refinement distance
            reduce(useNLayers, maxOp<label>());
    
            reduce(changed, maxOp<bool>());
            if( useNLayers && changed )
    
                octreeModifier.refineSelectedBoxesAndAdditionalLayers
                (
                    refineCubes,
    
    Franjo's avatar
    Franjo committed
                    rThickness
    
                );
            }
            else if( changed )
            {
                //- refine boxes
                octreeModifier.refineSelectedBoxes(refineCubes, hexRefinement_);
    
    Franjo's avatar
    Franjo committed
    
            # ifdef OCTREETiming
            const scalar refTime = omp_get_wtime();
            Info << "Time for refinement " << (refTime-startIter) << endl;
            # endif
    
            if( octree_.neiProcs().size() != 0 )
            {
    
    Franjo's avatar
    Franjo committed
                {
                    octreeModifier.distributeLeavesToProcessors();
    
                    # ifdef OCTREETiming
                    const scalar distTime = omp_get_wtime();
                    Info << "Time for distributing data to processors "
                    << (distTime-refTime) << endl;
                    # endif
    
                    loadDistribution(false);
    
                    # ifdef OCTREETiming
                    Info << "Time for load distribution "
                    << (omp_get_wtime()-distTime) << endl;
                    # endif
                }
            }
    
    Franjo's avatar
    Franjo committed
        Info << "Finished refinement of boxes intersecting edge meshes" << endl;
    
    void meshOctreeCreator::refineBoxesNearDataBoxes(const label nLayers)
    
    franjo's avatar
    franjo committed
    {
        # ifdef OCTREETiming
        const scalar startTime = omp_get_wtime();
        # endif
    
        const FixedList<meshOctreeCubeCoordinates, 26>& rp =
            octree_.regularityPositions();
    
        Info << "Refining boxes near DATA boxes" << endl;
    
        //- ensure one to one matching with unknown boxes
        meshOctreeModifier octreeModifier(octree_);
        const LongList<meshOctreeCube*>& leaves = octreeModifier.leavesAccess();
    
        # ifdef DEBUGSearch
        forAll(leaves, leafI)
            Info << "Leaf " << leafI << " is " << *leaves[leafI]
                << " type " << label(leaves[leafI]->cubeType()) << endl;
        # endif
    
    
        labelList refineBox(leaves.size(), 0);
    
    franjo's avatar
    franjo committed
    
        labelHashSet transferCoordinates;
        LongList<meshOctreeCubeCoordinates> checkCoordinates;
    
    
    franjo's avatar
    franjo committed
        # pragma omp parallel for if( leaves.size() > 1000 ) \
        schedule(dynamic, 20)
    
    franjo's avatar
    franjo committed
        forAll(leaves, leafI)
        {
            if( leaves[leafI]->hasContainedElements() )
            {
                const meshOctreeCube& oc = *leaves[leafI];
    
                # ifdef DEBUGSearch
                Info << "Refining boxes near box " << leafI
                    << " with coordinates " << oc << endl;
                # endif
    
                for(label k=0;k<26;++k)
                {
                    const label neiLabel =
                        octree_.findLeafLabelForPosition
                        (
                            oc.coordinates() + rp[k]
                        );
    
                    if( neiLabel == meshOctreeCube::OTHERPROC )
                    {
    
    franjo's avatar
    franjo committed
                        # pragma omp critical
    
    franjo's avatar
    franjo committed
                        {
                            if( !transferCoordinates.found(leafI) )
                            {
                                transferCoordinates.insert(leafI);
                                checkCoordinates.append(oc.coordinates());
                            }
                        }
    
                        continue;
                    }
    
    franjo's avatar
    franjo committed
                    if( neiLabel == -1 )
                        continue;
    
                    const meshOctreeCube* nei = leaves[neiLabel];
                    if( nei->level() == oc.level() )
                        continue;
                    if( nei->cubeType() & meshOctreeCubeBasic::OUTSIDE )
                        continue;
    
                    # ifdef DEBUGSearch
                    Info << "Adding neighbour " << *nei << " of type"
                        << label(nei->cubeType()) << endl;
                    # endif
    
                    refineBox[nei->cubeLabel()] = 1;
                }
            }
        }
    
        if( octree_.neiProcs().size() )
        {
            LongList<meshOctreeCubeCoordinates> receivedCoordinates;
            octree_.exchangeRequestsWithNeighbourProcessors
            (
                checkCoordinates,
                receivedCoordinates
            );
    
    
    franjo's avatar
    franjo committed
            # pragma omp parallel for if( receivedCoordinates.size() > 1000 ) \
            schedule(dynamic, 20)
    
    franjo's avatar
    franjo committed
            forAll(receivedCoordinates, ccI)
            {
                const meshOctreeCubeCoordinates& cc = receivedCoordinates[ccI];
                for(label k=0;k<26;++k)
                {
                    const label neiLabel =
                        octree_.findLeafLabelForPosition(cc + rp[k]);
    
                    if( neiLabel < 0 )
                        continue;
    
                    const meshOctreeCube* nei = leaves[neiLabel];
                    if( nei->level() == cc.level() )
                        continue;
                    if( nei->cubeType() & meshOctreeCubeBasic::OUTSIDE )
                        continue;
    
                    # ifdef DEBUGSearch
                    Info << "Adding neighbour " << *nei << " of type"
                        << label(nei->cubeType()) << endl;
                    # endif
    
                    refineBox[nei->cubeLabel()] = 1;
                }
            }
        }
    
    
        for(label i=1;i<nLayers;i++)
    
    franjo's avatar
    franjo committed
        {
            if( Pstream::parRun() )
            {
                checkCoordinates.clear();
                transferCoordinates.clear();
            }
    
    
    franjo's avatar
    franjo committed
            # pragma omp parallel for if( leaves.size() > 1000 ) \
            schedule(dynamic, 20)
    
    franjo's avatar
    franjo committed
            forAll(leaves, leafI)
            {
                if( refineBox[leafI] == i )
                {
                    const meshOctreeCube& oc = *leaves[leafI];
    
                    # ifdef DEBUGSearch
                    Info << "Refining boxes near box " << leafI
                        << " with coordinates " << oc << endl;
                    # endif
    
                    for(label k=0;k<26;++k)