1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 cfMesh is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "meshOctreeModifier.H"
38 //#define OCTREETiming
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 void meshOctreeModifier::markAdditionalLayers
50 List<direction>& refineBox,
51 const direction nLayers
54 const FixedList<meshOctreeCubeCoordinates, 26>& rp =
55 octree_.regularityPositions_;
56 const LongList<meshOctreeCube*>& leaves = octree_.leaves_;
58 //- this is needed for parallel runs to reduce the bandwidth
59 labelHashSet transferCoordinates;
61 FixedList<meshOctreeCube*, 26> neighbours;
63 for(direction i=1;i<=nLayers;++i)
65 LongList<meshOctreeCubeCoordinates> processorChecks;
68 # pragma omp parallel for if( leaves.size() > 1000 ) \
69 private(neighbours) schedule(dynamic, 20)
73 if( refineBox[leafI] != i )
76 const meshOctreeCube* oc = leaves[leafI];
80 const meshOctreeCubeCoordinates cc
82 oc->coordinates() + rp[posI]
85 const label neiLabel = octree_.findLeafLabelForPosition(cc);
89 neighbours[posI] = leaves[neiLabel];
91 else if( neiLabel == -1 )
93 neighbours[posI] = NULL;
95 else if( neiLabel == meshOctreeCubeBasic::OTHERPROC )
97 neighbours[posI] = NULL;
100 # pragma omp critical
103 if( !transferCoordinates.found(leafI) )
105 processorChecks.append(oc->coordinates());
106 transferCoordinates.insert(leafI);
112 forAll(neighbours, neiI)
114 const meshOctreeCube* nei = neighbours[neiI];
116 if( !nei->isLeaf() ) continue;
117 if( nei->level() > oc->level() ) continue;
119 if( !refineBox[nei->cubeLabel()] )
121 refineBox[nei->cubeLabel()] = i+1;
126 if( octree_.neiProcs().size() )
128 LongList<meshOctreeCubeCoordinates> receivedCoords;
129 octree_.exchangeRequestsWithNeighbourProcessors
135 //- check consistency with received cube coordinates
137 # pragma omp parallel for if( receivedCoords.size() > 1000 ) \
138 schedule(dynamic, 20)
140 forAll(receivedCoords, ccI)
144 const meshOctreeCubeCoordinates cc
146 receivedCoords[ccI] + rp[posI]
149 const meshOctreeCube* nei =
150 octree_.findCubeForPosition(cc);
153 if( !nei->isLeaf() ) continue;
154 if( nei->level() > cc.level() ) continue;
156 if( !refineBox[nei->cubeLabel()] )
158 refineBox[nei->cubeLabel()] = i+1;
166 void meshOctreeModifier::refineSelectedBoxes
168 List<direction>& refineBox,
169 const bool hexRefinement
173 const scalar startTime = omp_get_wtime();
176 //- ensure that refinement will produce 1-irregular octree
179 ensureCorrectRegularity(refineBox);
180 } while( hexRefinement && ensureCorrectRegularitySons(refineBox) );
183 const scalar regTime = omp_get_wtime();
184 Info << "Time for ensuring regularity " << (regTime-startTime) << endl;
187 const triSurf& surface = octree_.surface();
188 const boundBox& rootBox = octree_.rootBox();
189 const LongList<meshOctreeCube*>& leaves = octree_.leaves_;
191 //- this is needed for thread safety
192 //- such solutions make me a sad bunny :(
193 surface.facetEdges();
194 surface.edgeFacets();
198 # pragma omp parallel num_threads(octree_.dataSlots_.size())
202 meshOctreeSlot* slotPtr = &octree_.dataSlots_[omp_get_thread_num()];
204 meshOctreeSlot* slotPtr = &octree_.dataSlots_[0];
207 if( !octree_.isQuadtree() )
210 # pragma omp for schedule(dynamic, 100)
212 forAll(leaves, leafI)
214 if( refineBox[leafI] )
215 leaves[leafI]->refineCube(surface, rootBox, slotPtr);
221 # pragma omp for schedule(dynamic, 100)
223 forAll(leaves, leafI)
225 if( refineBox[leafI] )
226 leaves[leafI]->refineCube2D(surface, rootBox, slotPtr);
231 createListOfLeaves();
234 Info << "Time for actual refinement " << (omp_get_wtime()-regTime) << endl;
238 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
240 } // End namespace Foam
242 // ************************************************************************* //