1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*----------------------------------------------------------------------------*/
26 #include "meshRefinement.H"
27 #include "trackedParticle.H"
28 #include "syncTools.H"
30 #include "refinementSurfaces.H"
31 #include "refinementFeatures.H"
32 #include "shellSurfaces.H"
34 #include "decompositionMethod.H"
35 #include "fvMeshDistribute.H"
36 #include "polyTopoChange.H"
37 #include "mapDistributePolyMesh.H"
38 #include "featureEdgeMesh.H"
40 //#include "globalIndex.H"
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 // Get faces (on the new mesh) that have in some way been affected by the
45 // mesh change. Picks up all faces but those that are between two
46 // unrefined faces. (Note that of an unchanged face the edge still might be
47 // split but that does not change any face centre or cell centre.
48 Foam::labelList Foam::meshRefinement::getChangedFaces
50 const mapPolyMesh& map,
51 const labelList& oldCellsToRefine
54 const polyMesh& mesh = map.mesh();
56 labelList changedFaces;
58 // For reporting: number of masterFaces changed
59 label nMasterChanged = 0;
60 PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
63 // Mark any face on a cell which has been added or changed
64 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65 // Note that refining a face changes the face centre (for a warped face)
66 // which changes the cell centre. This again changes the cellcentre-
67 // cellcentre edge across all faces of the cell.
68 // Note: this does not happen for unwarped faces but unfortunately
69 // we don't have this information.
71 const labelList& faceOwner = mesh.faceOwner();
72 const labelList& faceNeighbour = mesh.faceNeighbour();
73 const cellList& cells = mesh.cells();
74 const label nInternalFaces = mesh.nInternalFaces();
76 // Mark refined cells on old mesh
77 PackedBoolList oldRefineCell(map.nOldCells());
79 forAll(oldCellsToRefine, i)
81 oldRefineCell.set(oldCellsToRefine[i], 1u);
85 PackedBoolList refinedInternalFace(nInternalFaces);
89 for (label faceI = 0; faceI < nInternalFaces; faceI++)
91 label oldOwn = map.cellMap()[faceOwner[faceI]];
92 label oldNei = map.cellMap()[faceNeighbour[faceI]];
97 && oldRefineCell.get(oldOwn) == 0u
99 && oldRefineCell.get(oldNei) == 0u
102 // Unaffected face since both neighbours were not refined.
106 refinedInternalFace.set(faceI, 1u);
113 boolList refinedBoundaryFace(mesh.nFaces()-nInternalFaces, false);
115 forAll(mesh.boundaryMesh(), patchI)
117 const polyPatch& pp = mesh.boundaryMesh()[patchI];
119 label faceI = pp.start();
123 label oldOwn = map.cellMap()[faceOwner[faceI]];
125 if (oldOwn >= 0 && oldRefineCell.get(oldOwn) == 0u)
127 // owner did exist and wasn't refined.
131 refinedBoundaryFace[faceI-nInternalFaces] = true;
137 // Synchronise refined face status
138 syncTools::syncBoundaryFaceList
146 // 3. Mark all faces affected by refinement. Refined faces are in
147 // - refinedInternalFace
148 // - refinedBoundaryFace
149 boolList changedFace(mesh.nFaces(), false);
151 forAll(refinedInternalFace, faceI)
153 if (refinedInternalFace.get(faceI) == 1u)
155 const cell& ownFaces = cells[faceOwner[faceI]];
156 forAll(ownFaces, ownI)
158 changedFace[ownFaces[ownI]] = true;
160 const cell& neiFaces = cells[faceNeighbour[faceI]];
161 forAll(neiFaces, neiI)
163 changedFace[neiFaces[neiI]] = true;
168 forAll(refinedBoundaryFace, i)
170 if (refinedBoundaryFace[i])
172 const cell& ownFaces = cells[faceOwner[i+nInternalFaces]];
173 forAll(ownFaces, ownI)
175 changedFace[ownFaces[ownI]] = true;
180 syncTools::syncFaceList
188 // Now we have in changedFace marked all affected faces. Pack.
189 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191 changedFaces = findIndices(changedFace, true);
193 // Count changed master faces.
196 forAll(changedFace, faceI)
198 if (changedFace[faceI] && isMasterFace[faceI])
208 Pout<< "getChangedFaces : Detected "
209 << " local:" << changedFaces.size()
210 << " global:" << returnReduce(nMasterChanged, sumOp<label>())
211 << " changed faces out of " << mesh.globalData().nTotalFaces()
214 faceSet changedFacesSet(mesh, "changedFaces", changedFaces);
215 Pout<< "getChangedFaces : Writing " << changedFaces.size()
216 << " changed faces to faceSet " << changedFacesSet.name()
218 changedFacesSet.write();
225 // Mark cell for refinement (if not already marked). Return false if
226 // refinelimit hit. Keeps running count (in nRefine) of cells marked for
228 bool Foam::meshRefinement::markForRefine
230 const label markValue,
231 const label nAllowRefine,
239 cellValue = markValue;
243 return nRefine <= nAllowRefine;
247 // Calculates list of cells to refine based on intersection with feature edge.
248 Foam::label Foam::meshRefinement::markFeatureRefinement
250 const point& keepPoint,
251 const label nAllowRefine,
253 labelList& refineCell,
257 // We want to refine all cells containing a feature edge.
258 // - don't want to search over whole mesh
259 // - don't want to build octree for whole mesh
260 // - so use tracking to follow the feature edges
262 // 1. find non-manifold points on feature edges (i.e. start of feature edge
264 // 2. seed particle starting at keepPoint going to this non-manifold point
265 // 3. track particles to their non-manifold point
267 // 4. track particles across their connected feature edges, marking all
268 // visited cells with their level (through trackingData)
269 // 5. do 4 until all edges have been visited.
272 // Find all start cells of features. Is done by tracking from keepPoint.
273 Cloud<trackedParticle> cloud(mesh_, IDLList<trackedParticle>());
275 // Create particles on whichever processor holds the keepPoint.
280 mesh_.findCellFacePt(keepPoint, cellI, tetFaceI, tetPtI);
284 forAll(features_, featI)
286 const featureEdgeMesh& featureMesh = features_[featI];
287 const label featureLevel = features_.levels()[featI];
289 const labelListList& pointEdges = featureMesh.pointEdges();
291 forAll(pointEdges, pointI)
293 if (pointEdges[pointI].size() != 2)
297 Pout<< "Adding particle from point:" << pointI
298 << " coord:" << featureMesh.points()[pointI]
299 << " pEdges:" << pointEdges[pointI]
303 // Non-manifold point. Create particle.
313 featureMesh.points()[pointI], // endpos
314 featureLevel, // level
315 featI, // featureMesh
325 // Largest refinement level of any feature passed through
326 labelList maxFeatureLevel(mesh_.nCells(), -1);
328 // Database to pass into trackedParticle::move
329 trackedParticle::trackingData td(cloud, maxFeatureLevel);
331 // Track all particles to their end position (= starting feature point)
332 cloud.move(td, GREAT);
335 maxFeatureLevel = -1;
337 // Whether edge has been visited.
338 List<PackedBoolList> featureEdgeVisited(features_.size());
340 forAll(features_, featI)
342 featureEdgeVisited[featI].setSize(features_[featI].edges().size());
343 featureEdgeVisited[featI] = 0u;
348 label nParticles = 0;
350 // Make particle follow edge.
351 forAllIter(Cloud<trackedParticle>, cloud, iter)
353 trackedParticle& tp = iter();
355 label featI = tp.i();
356 label pointI = tp.j();
358 const featureEdgeMesh& featureMesh = features_[featI];
359 const labelList& pEdges = featureMesh.pointEdges()[pointI];
361 // Particle now at pointI. Check connected edges to see which one
362 // we have to visit now.
364 bool keepParticle = false;
368 label edgeI = pEdges[i];
370 if (featureEdgeVisited[featI].set(edgeI, 1u))
372 // Unvisited edge. Make the particle go to the other point
375 const edge& e = featureMesh.edges()[edgeI];
376 label otherPointI = e.otherVertex(pointI);
378 tp.end() = featureMesh.points()[otherPointI];
379 tp.j() = otherPointI;
387 // Particle at 'knot' where another particle already has been
388 // seeded. Delete particle.
389 cloud.deleteParticle(tp);
398 reduce(nParticles, sumOp<label>());
404 // Track all particles to their end position.
405 cloud.move(td, GREAT);
409 // See which cells to refine. maxFeatureLevel will hold highest level
410 // of any feature edge that passed through.
412 const labelList& cellLevel = meshCutter_.cellLevel();
414 label oldNRefine = nRefine;
416 forAll(maxFeatureLevel, cellI)
418 if (maxFeatureLevel[cellI] > cellLevel[cellI])
440 returnReduce(nRefine, sumOp<label>())
441 > returnReduce(nAllowRefine, sumOp<label>())
444 Info<< "Reached refinement limit." << endl;
447 return returnReduce(nRefine-oldNRefine, sumOp<label>());
451 // Mark cells for non-surface intersection based refinement.
452 Foam::label Foam::meshRefinement::markInternalRefinement
454 const label nAllowRefine,
456 labelList& refineCell,
460 const labelList& cellLevel = meshCutter_.cellLevel();
461 const pointField& cellCentres = mesh_.cellCentres();
463 label oldNRefine = nRefine;
465 // Collect cells to test
466 pointField testCc(cellLevel.size()-nRefine);
467 labelList testLevels(cellLevel.size()-nRefine);
470 forAll(cellLevel, cellI)
472 if (refineCell[cellI] == -1)
474 testCc[testI] = cellCentres[cellI];
475 testLevels[testI] = cellLevel[cellI];
480 // Do test to see whether cells is inside/outside shell with higher level
482 shells_.findHigherLevel(testCc, testLevels, maxLevel);
484 // Mark for refinement. Note that we didn't store the original cellID so
485 // now just reloop in same order.
487 forAll(cellLevel, cellI)
489 if (refineCell[cellI] == -1)
491 if (maxLevel[testI] > testLevels[testI])
493 bool reachedLimit = !markForRefine
495 maxLevel[testI], // mark with any positive value
505 Pout<< "Stopped refining internal cells"
506 << " since reaching my cell limit of "
507 << mesh_.nCells()+7*nRefine << endl;
518 returnReduce(nRefine, sumOp<label>())
519 > returnReduce(nAllowRefine, sumOp<label>())
522 Info<< "Reached refinement limit." << endl;
525 return returnReduce(nRefine-oldNRefine, sumOp<label>());
529 // Collect faces that are intersected and whose neighbours aren't yet marked
531 Foam::labelList Foam::meshRefinement::getRefineCandidateFaces
533 const labelList& refineCell
536 labelList testFaces(mesh_.nFaces());
540 forAll(surfaceIndex_, faceI)
542 if (surfaceIndex_[faceI] != -1)
544 label own = mesh_.faceOwner()[faceI];
546 if (mesh_.isInternalFace(faceI))
548 label nei = mesh_.faceNeighbour()[faceI];
550 if (refineCell[own] == -1 || refineCell[nei] == -1)
552 testFaces[nTest++] = faceI;
557 if (refineCell[own] == -1)
559 testFaces[nTest++] = faceI;
564 testFaces.setSize(nTest);
570 // Mark cells for surface intersection based refinement.
571 Foam::label Foam::meshRefinement::markSurfaceRefinement
573 const label nAllowRefine,
574 const labelList& neiLevel,
575 const pointField& neiCc,
577 labelList& refineCell,
581 const labelList& cellLevel = meshCutter_.cellLevel();
582 const pointField& cellCentres = mesh_.cellCentres();
584 label oldNRefine = nRefine;
586 // Use cached surfaceIndex_ to detect if any intersection. If so
587 // re-intersect to determine level wanted.
589 // Collect candidate faces
590 // ~~~~~~~~~~~~~~~~~~~~~~~
592 labelList testFaces(getRefineCandidateFaces(refineCell));
597 pointField start(testFaces.size());
598 pointField end(testFaces.size());
599 labelList minLevel(testFaces.size());
603 label faceI = testFaces[i];
605 label own = mesh_.faceOwner()[faceI];
607 if (mesh_.isInternalFace(faceI))
609 label nei = mesh_.faceNeighbour()[faceI];
611 start[i] = cellCentres[own];
612 end[i] = cellCentres[nei];
613 minLevel[i] = min(cellLevel[own], cellLevel[nei]);
617 label bFaceI = faceI - mesh_.nInternalFaces();
619 start[i] = cellCentres[own];
620 end[i] = neiCc[bFaceI];
621 minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
625 // Extend segments a bit
627 const vectorField smallVec(Foam::sqrt(SMALL)*(end-start));
633 // Do test for higher intersections
634 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
636 labelList surfaceHit;
637 labelList surfaceMinLevel;
638 surfaces_.findHigherIntersection
649 // Mark cells for refinement
650 // ~~~~~~~~~~~~~~~~~~~~~~~~~
654 label faceI = testFaces[i];
656 label surfI = surfaceHit[i];
660 // Found intersection with surface with higher wanted
661 // refinement. Check if the level field on that surface
662 // specifies an even higher level. Note:this is weird. Should
663 // do the check with the surfaceMinLevel whilst intersecting the
666 label own = mesh_.faceOwner()[faceI];
668 if (surfaceMinLevel[i] > cellLevel[own])
670 // Owner needs refining
686 if (mesh_.isInternalFace(faceI))
688 label nei = mesh_.faceNeighbour()[faceI];
689 if (surfaceMinLevel[i] > cellLevel[nei])
691 // Neighbour needs refining
712 returnReduce(nRefine, sumOp<label>())
713 > returnReduce(nAllowRefine, sumOp<label>())
716 Info<< "Reached refinement limit." << endl;
719 return returnReduce(nRefine-oldNRefine, sumOp<label>());
723 // Checks if multiple intersections of a cell (by a surface with a higher
724 // max than the cell level) and if so if the normals at these intersections
725 // make a large angle.
726 // Returns false if the nRefine limit has been reached, true otherwise.
727 bool Foam::meshRefinement::checkCurvature
729 const scalar curvature,
730 const label nAllowRefine,
732 const label surfaceLevel, // current intersection max level
733 const vector& surfaceNormal,// current intersection normal
737 label& cellMaxLevel, // cached max surface level for this cell
738 vector& cellMaxNormal, // cached surface normal for this cell
740 labelList& refineCell,
744 const labelList& cellLevel = meshCutter_.cellLevel();
746 // Test if surface applicable
747 if (surfaceLevel > cellLevel[cellI])
749 if (cellMaxLevel == -1)
751 // First visit of cell. Store
752 cellMaxLevel = surfaceLevel;
753 cellMaxNormal = surfaceNormal;
757 // Second or more visit. Check curvature.
758 if ((cellMaxNormal & surfaceNormal) < curvature)
762 surfaceLevel, // mark with any non-neg number.
769 // Set normal to that of highest surface. Not really necessary
770 // over here but we reuse cellMax info when doing coupled faces.
771 if (surfaceLevel > cellMaxLevel)
773 cellMaxLevel = surfaceLevel;
774 cellMaxNormal = surfaceNormal;
779 // Did not reach refinement limit.
784 // Mark cells for surface curvature based refinement.
785 Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
787 const scalar curvature,
788 const label nAllowRefine,
789 const labelList& neiLevel,
790 const pointField& neiCc,
792 labelList& refineCell,
796 const labelList& cellLevel = meshCutter_.cellLevel();
797 const pointField& cellCentres = mesh_.cellCentres();
799 label oldNRefine = nRefine;
801 // 1. local test: any cell on more than one surface gets refined
802 // (if its current level is < max of the surface max level)
804 // 2. 'global' test: any cell on only one surface with a neighbour
805 // on a different surface gets refined (if its current level etc.)
808 // Collect candidate faces (i.e. intersecting any surface and
809 // owner/neighbour not yet refined.
810 labelList testFaces(getRefineCandidateFaces(refineCell));
813 pointField start(testFaces.size());
814 pointField end(testFaces.size());
815 labelList minLevel(testFaces.size());
819 label faceI = testFaces[i];
821 label own = mesh_.faceOwner()[faceI];
823 if (mesh_.isInternalFace(faceI))
825 label nei = mesh_.faceNeighbour()[faceI];
827 start[i] = cellCentres[own];
828 end[i] = cellCentres[nei];
829 minLevel[i] = min(cellLevel[own], cellLevel[nei]);
833 label bFaceI = faceI - mesh_.nInternalFaces();
835 start[i] = cellCentres[own];
836 end[i] = neiCc[bFaceI];
837 minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
841 // Extend segments a bit
843 const vectorField smallVec(Foam::sqrt(SMALL)*(end-start));
849 // Test for all intersections (with surfaces of higher max level than
850 // minLevel) and cache per cell the max surface level and the local normal
852 labelList cellMaxLevel(mesh_.nCells(), -1);
853 vectorField cellMaxNormal(mesh_.nCells(), vector::zero);
856 // Per segment the normals of the surfaces
857 List<vectorList> surfaceNormal;
858 // Per segment the list of levels of the surfaces
859 labelListList surfaceLevel;
861 surfaces_.findAllHigherIntersections
865 minLevel, // max level of surface has to be bigger
866 // than min level of neighbouring cells
870 // Clear out unnecessary data
875 // Extract per cell information on the surface with the highest max
878 label faceI = testFaces[i];
879 label own = mesh_.faceOwner()[faceI];
881 const vectorList& fNormals = surfaceNormal[i];
882 const labelList& fLevels = surfaceLevel[i];
884 forAll(fLevels, hitI)
903 if (mesh_.isInternalFace(faceI))
905 label nei = mesh_.faceNeighbour()[faceI];
907 forAll(fLevels, hitI)
929 // 2. Find out a measure of surface curvature and region edges.
930 // Send over surface region and surface normal to neighbour cell.
932 labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces());
933 vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces());
935 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
937 label bFaceI = faceI-mesh_.nInternalFaces();
938 label own = mesh_.faceOwner()[faceI];
940 neiBndMaxLevel[bFaceI] = cellMaxLevel[own];
941 neiBndMaxNormal[bFaceI] = cellMaxNormal[own];
943 syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel);
944 syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal);
946 // Loop over all faces. Could only be checkFaces.. except if they're coupled
949 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
951 label own = mesh_.faceOwner()[faceI];
952 label nei = mesh_.faceNeighbour()[faceI];
954 if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1)
956 // Have valid data on both sides. Check curvature.
957 if ((cellMaxNormal[own] & cellMaxNormal[nei]) < curvature)
959 // See which side to refine
960 if (cellLevel[own] < cellMaxLevel[own])
975 Pout<< "Stopped refining since reaching my cell"
976 << " limit of " << mesh_.nCells()+7*nRefine
983 if (cellLevel[nei] < cellMaxLevel[nei])
998 Pout<< "Stopped refining since reaching my cell"
999 << " limit of " << mesh_.nCells()+7*nRefine
1009 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
1011 label own = mesh_.faceOwner()[faceI];
1012 label bFaceI = faceI - mesh_.nInternalFaces();
1014 if (cellLevel[own] < cellMaxLevel[own] && neiBndMaxLevel[bFaceI] != -1)
1016 // Have valid data on both sides. Check curvature.
1017 if ((cellMaxNormal[own] & neiBndMaxNormal[bFaceI]) < curvature)
1032 Pout<< "Stopped refining since reaching my cell"
1033 << " limit of " << mesh_.nCells()+7*nRefine
1044 returnReduce(nRefine, sumOp<label>())
1045 > returnReduce(nAllowRefine, sumOp<label>())
1048 Info<< "Reached refinement limit." << endl;
1051 return returnReduce(nRefine-oldNRefine, sumOp<label>());
1055 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1057 // Calculate list of cells to refine. Gets for any edge (start - end)
1058 // whether it intersects the surface. Does more accurate test and checks
1059 // the wanted level on the surface intersected.
1060 // Does approximate precalculation of how many cells can be refined before
1061 // hitting overall limit maxGlobalCells.
1062 Foam::labelList Foam::meshRefinement::refineCandidates
1064 const point& keepPoint,
1065 const scalar curvature,
1067 const bool featureRefinement,
1068 const bool internalRefinement,
1069 const bool surfaceRefinement,
1070 const bool curvatureRefinement,
1071 const label maxGlobalCells,
1072 const label maxLocalCells
1075 label totNCells = mesh_.globalData().nTotalCells();
1077 labelList cellsToRefine;
1079 if (totNCells >= maxGlobalCells)
1081 Info<< "No cells marked for refinement since reached limit "
1082 << maxGlobalCells << '.' << endl;
1086 // Every cell I refine adds 7 cells. Estimate the number of cells
1087 // I am allowed to refine.
1088 // Assume perfect distribution so can only refine as much the fraction
1089 // of the mesh I hold. This prediction step prevents us having to do
1090 // lots of reduces to keep count of the total number of cells selected
1093 //scalar fraction = scalar(mesh_.nCells())/totNCells;
1094 //label myMaxCells = label(maxGlobalCells*fraction);
1095 //label nAllowRefine = (myMaxCells - mesh_.nCells())/7;
1096 ////label nAllowRefine = (maxLocalCells - mesh_.nCells())/7;
1098 //Pout<< "refineCandidates:" << nl
1099 // << " total cells:" << totNCells << nl
1100 // << " local cells:" << mesh_.nCells() << nl
1101 // << " local fraction:" << fraction << nl
1102 // << " local allowable cells:" << myMaxCells << nl
1103 // << " local allowable refinement:" << nAllowRefine << nl
1106 //- Disable refinement shortcut. nAllowRefine is per processor limit.
1107 label nAllowRefine = labelMax / Pstream::nProcs();
1109 // Marked for refinement (>= 0) or not (-1). Actual value is the
1110 // index of the surface it intersects.
1111 labelList refineCell(mesh_.nCells(), -1);
1115 // Swap neighbouring cell centres and cell level
1116 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1117 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
1118 calcNeighbourData(neiLevel, neiCc);
1122 // Cells pierced by feature lines
1123 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1125 if (featureRefinement)
1127 label nFeatures = markFeatureRefinement
1136 Info<< "Marked for refinement due to explicit features : "
1137 << nFeatures << " cells." << endl;
1140 // Inside refinement shells
1141 // ~~~~~~~~~~~~~~~~~~~~~~~~
1143 if (internalRefinement)
1145 label nShell = markInternalRefinement
1152 Info<< "Marked for refinement due to refinement shells : "
1153 << nShell << " cells." << endl;
1156 // Refinement based on intersection of surface
1157 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1159 if (surfaceRefinement)
1161 label nSurf = markSurfaceRefinement
1170 Info<< "Marked for refinement due to surface intersection : "
1171 << nSurf << " cells." << endl;
1174 // Refinement based on curvature of surface
1175 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1180 && (curvature >= -1 && curvature <= 1)
1181 && (surfaces_.minLevel() != surfaces_.maxLevel())
1184 label nCurv = markSurfaceCurvatureRefinement
1194 Info<< "Marked for refinement due to curvature/regions : "
1195 << nCurv << " cells." << endl;
1198 // Pack cells-to-refine
1199 // ~~~~~~~~~~~~~~~~~~~~
1201 cellsToRefine.setSize(nRefine);
1204 forAll(refineCell, cellI)
1206 if (refineCell[cellI] != -1)
1208 cellsToRefine[nRefine++] = cellI;
1213 return cellsToRefine;
1217 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::refine
1219 const labelList& cellsToRefine
1222 // Mesh changing engine.
1223 polyTopoChange meshMod(mesh_);
1225 // Play refinement commands into mesh changer.
1226 meshCutter_.setRefinement(cellsToRefine, meshMod);
1228 // Create mesh (no inflation), return map from old to new mesh.
1229 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false);
1232 mesh_.updateMesh(map);
1234 // Optionally inflate mesh
1235 if (map().hasMotionPoints())
1237 mesh_.movePoints(map().preMotionPoints());
1241 // Delete mesh volumes.
1245 // Reset the instance for if in overwrite mode
1246 mesh_.setInstance(timeName());
1248 // Update intersection info
1249 updateMesh(map, getChangedFaces(map, cellsToRefine));
1255 // Do refinement of consistent set of cells followed by truncation and
1257 Foam::autoPtr<Foam::mapDistributePolyMesh>
1258 Foam::meshRefinement::refineAndBalance
1261 decompositionMethod& decomposer,
1262 fvMeshDistribute& distributor,
1263 const labelList& cellsToRefine,
1264 const scalar maxLoadUnbalance
1267 // Do all refinement
1268 refine(cellsToRefine);
1272 Pout<< "Writing refined but unbalanced " << msg
1273 << " mesh to time " << timeName() << endl;
1280 Pout<< "Dumped debug data in = "
1281 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1283 // test all is still synced across proc patches
1287 Info<< "Refined mesh in = "
1288 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1289 printMeshInfo(debug, "After refinement " + msg);
1295 autoPtr<mapDistributePolyMesh> distMap;
1297 if (Pstream::nProcs() > 1)
1299 scalar nIdealCells =
1300 mesh_.globalData().nTotalCells()
1301 / Pstream::nProcs();
1303 scalar unbalance = returnReduce
1305 mag(1.0-mesh_.nCells()/nIdealCells),
1309 if (unbalance <= maxLoadUnbalance)
1311 Info<< "Skipping balancing since max unbalance " << unbalance
1312 << " is less than allowable " << maxLoadUnbalance
1317 scalarField cellWeights(mesh_.nCells(), 1);
1321 false, //keepZoneFaces
1322 false, //keepBaffles
1328 Info<< "Balanced mesh in = "
1329 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1331 printMeshInfo(debug, "After balancing " + msg);
1336 Pout<< "Writing balanced " << msg
1337 << " mesh to time " << timeName() << endl;
1341 mesh_.time().path()/timeName()
1343 Pout<< "Dumped debug data in = "
1344 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1346 // test all is still synced across proc patches
1356 // Do load balancing followed by refinement of consistent set of cells.
1357 Foam::autoPtr<Foam::mapDistributePolyMesh>
1358 Foam::meshRefinement::balanceAndRefine
1361 decompositionMethod& decomposer,
1362 fvMeshDistribute& distributor,
1363 const labelList& initCellsToRefine,
1364 const scalar maxLoadUnbalance
1367 labelList cellsToRefine(initCellsToRefine);
1370 // globalIndex globalCells(mesh_.nCells());
1372 // Info<< "** Distribution before balancing/refining:" << endl;
1373 // for (label procI = 0; procI < Pstream::nProcs(); procI++)
1375 // Info<< " " << procI << '\t'
1376 // << globalCells.localSize(procI) << endl;
1381 // globalIndex globalCells(cellsToRefine.size());
1383 // Info<< "** Cells to be refined:" << endl;
1384 // for (label procI = 0; procI < Pstream::nProcs(); procI++)
1386 // Info<< " " << procI << '\t'
1387 // << globalCells.localSize(procI) << endl;
1396 autoPtr<mapDistributePolyMesh> distMap;
1398 if (Pstream::nProcs() > 1)
1400 // First check if we need to balance at all. Precalculate number of
1401 // cells after refinement and see what maximum difference is.
1402 scalar nNewCells = scalar(mesh_.nCells() + 7*cellsToRefine.size());
1403 scalar nIdealNewCells =
1404 returnReduce(nNewCells, sumOp<scalar>())
1405 / Pstream::nProcs();
1406 scalar unbalance = returnReduce
1408 mag(1.0-nNewCells/nIdealNewCells),
1412 if (unbalance <= maxLoadUnbalance)
1414 Info<< "Skipping balancing since max unbalance " << unbalance
1415 << " is less than allowable " << maxLoadUnbalance
1420 scalarField cellWeights(mesh_.nCells(), 1);
1421 forAll(cellsToRefine, i)
1423 cellWeights[cellsToRefine[i]] += 7;
1428 false, //keepZoneFaces
1429 false, //keepBaffles
1435 // Update cells to refine
1436 distMap().distributeCellIndices(cellsToRefine);
1438 Info<< "Balanced mesh in = "
1439 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1443 // globalIndex globalCells(mesh_.nCells());
1445 // Info<< "** Distribution after balancing:" << endl;
1446 // for (label procI = 0; procI < Pstream::nProcs(); procI++)
1448 // Info<< " " << procI << '\t'
1449 // << globalCells.localSize(procI) << endl;
1454 printMeshInfo(debug, "After balancing " + msg);
1458 Pout<< "Writing balanced " << msg
1459 << " mesh to time " << timeName() << endl;
1463 mesh_.time().path()/timeName()
1465 Pout<< "Dumped debug data in = "
1466 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1468 // test all is still synced across proc patches
1477 refine(cellsToRefine);
1481 Pout<< "Writing refined " << msg
1482 << " mesh to time " << timeName() << endl;
1489 Pout<< "Dumped debug data in = "
1490 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1492 // test all is still synced across proc patches
1496 Info<< "Refined mesh in = "
1497 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1500 // globalIndex globalCells(mesh_.nCells());
1502 // Info<< "** After refinement distribution:" << endl;
1503 // for (label procI = 0; procI < Pstream::nProcs(); procI++)
1505 // Info<< " " << procI << '\t'
1506 // << globalCells.localSize(procI) << endl;
1511 printMeshInfo(debug, "After refinement " + msg);
1517 // ************************************************************************* //