1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*----------------------------------------------------------------------------*/
27 #include "meshRefinement.H"
28 #include "trackedParticle.H"
29 #include "syncTools.H"
31 #include "refinementSurfaces.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"
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 // Get faces (on the new mesh) that have in some way been affected by the
44 // mesh change. Picks up all faces but those that are between two
45 // unrefined faces. (Note that of an unchanged face the edge still might be
46 // split but that does not change any face centre or cell centre.
47 Foam::labelList Foam::meshRefinement::getChangedFaces
49 const mapPolyMesh& map,
50 const labelList& oldCellsToRefine
53 const polyMesh& mesh = map.mesh();
55 labelList changedFaces;
57 // Mark any face on a cell which has been added or changed
58 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59 // Note that refining a face changes the face centre (for a warped face)
60 // which changes the cell centre. This again changes the cellcentre-
61 // cellcentre edge across all faces of the cell.
62 // Note: this does not happen for unwarped faces but unfortunately
63 // we don't have this information.
65 const labelList& faceOwner = mesh.faceOwner();
66 const labelList& faceNeighbour = mesh.faceNeighbour();
67 const cellList& cells = mesh.cells();
68 const label nInternalFaces = mesh.nInternalFaces();
70 // Mark refined cells on old mesh
71 PackedList<1> oldRefineCell(map.nOldCells(), 0u);
73 forAll(oldCellsToRefine, i)
75 oldRefineCell.set(oldCellsToRefine[i], 1u);
79 PackedList<1> refinedInternalFace(nInternalFaces, 0u);
83 for (label faceI = 0; faceI < nInternalFaces; faceI++)
85 label oldOwn = map.cellMap()[faceOwner[faceI]];
86 label oldNei = map.cellMap()[faceNeighbour[faceI]];
91 && oldRefineCell.get(oldOwn) == 0u
93 && oldRefineCell.get(oldNei) == 0u
96 // Unaffected face since both neighbours were not refined.
100 refinedInternalFace.set(faceI, 1u);
107 boolList refinedBoundaryFace(mesh.nFaces()-nInternalFaces, false);
109 forAll(mesh.boundaryMesh(), patchI)
111 const polyPatch& pp = mesh.boundaryMesh()[patchI];
113 label faceI = pp.start();
117 label oldOwn = map.cellMap()[faceOwner[faceI]];
119 if (oldOwn >= 0 && oldRefineCell.get(oldOwn) == 0u)
121 // owner did exist and wasn't refined.
125 refinedBoundaryFace[faceI-nInternalFaces] = true;
131 // Synchronise refined face status
132 syncTools::syncBoundaryFaceList
141 // 3. Mark all faces affected by refinement. Refined faces are in
142 // - refinedInternalFace
143 // - refinedBoundaryFace
144 boolList changedFace(mesh.nFaces(), false);
146 forAll(refinedInternalFace, faceI)
148 if (refinedInternalFace.get(faceI) == 1u)
150 const cell& ownFaces = cells[faceOwner[faceI]];
151 forAll(ownFaces, ownI)
153 changedFace[ownFaces[ownI]] = true;
155 const cell& neiFaces = cells[faceNeighbour[faceI]];
156 forAll(neiFaces, neiI)
158 changedFace[neiFaces[neiI]] = true;
163 forAll(refinedBoundaryFace, i)
165 if (refinedBoundaryFace[i])
167 const cell& ownFaces = cells[faceOwner[i+nInternalFaces]];
168 forAll(ownFaces, ownI)
170 changedFace[ownFaces[ownI]] = true;
175 syncTools::syncFaceList
184 // Now we have in changedFace marked all affected faces. Pack.
185 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189 forAll(changedFace, faceI)
191 if (changedFace[faceI])
197 changedFaces.setSize(nChanged);
200 forAll(changedFace, faceI)
202 if (changedFace[faceI])
204 changedFaces[nChanged++] = faceI;
209 label nChangedFaces = changedFaces.size();
210 reduce(nChangedFaces, sumOp<label>());
214 Pout<< "getChangedFaces : Detected "
215 << " local:" << changedFaces.size()
216 << " global:" << nChangedFaces
217 << " changed faces out of " << mesh.globalData().nTotalFaces()
220 faceSet changedFacesSet(mesh, "changedFaces", changedFaces);
221 Pout<< "getChangedFaces : Writing " << changedFaces.size()
222 << " changed faces to faceSet " << changedFacesSet.name()
224 changedFacesSet.write();
231 // Mark cell for refinement (if not already marked). Return false if
232 // refinelimit hit. Keeps running count (in nRefine) of cells marked for
234 bool Foam::meshRefinement::markForRefine
236 const label markValue,
237 const label nAllowRefine,
245 cellValue = markValue;
249 return nRefine <= nAllowRefine;
253 // Calculates list of cells to refine based on intersection with feature edge.
254 Foam::label Foam::meshRefinement::markFeatureRefinement
256 const point& keepPoint,
257 const PtrList<featureEdgeMesh>& featureMeshes,
258 const labelList& featureLevels,
259 const label nAllowRefine,
261 labelList& refineCell,
265 // We want to refine all cells containing a feature edge.
266 // - don't want to search over whole mesh
267 // - don't want to build octree for whole mesh
268 // - so use tracking to follow the feature edges
270 // 1. find non-manifold points on feature edges (i.e. start of feature edge
272 // 2. seed particle starting at keepPoint going to this non-manifold point
273 // 3. track particles to their non-manifold point
275 // 4. track particles across their connected feature edges, marking all
276 // visited cells with their level (through trackingData)
277 // 5. do 4 until all edges have been visited.
280 // Find all start cells of features. Is done by tracking from keepPoint.
281 Cloud<trackedParticle> cloud(mesh_, IDLList<trackedParticle>());
283 // Create particles on whichever processor holds the keepPoint.
284 label cellI = mesh_.findCell(keepPoint);
288 forAll(featureMeshes, featI)
290 const featureEdgeMesh& featureMesh = featureMeshes[featI];
291 const labelListList& pointEdges = featureMesh.pointEdges();
293 forAll(pointEdges, pointI)
295 if (pointEdges[pointI].size() != 2)
299 Pout<< "Adding particle from point:" << pointI
300 << " coord:" << featureMesh.points()[pointI]
301 << " pEdges:" << pointEdges[pointI]
305 // Non-manifold point. Create particle.
313 featureMesh.points()[pointI], // endpos
314 featureLevels[featI], // 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::trackData td(cloud, maxFeatureLevel);
331 // Track all particles to their end position.
335 maxFeatureLevel = -1;
337 // Whether edge has been visited.
338 List<PackedList<1> > featureEdgeVisited(featureMeshes.size());
340 forAll(featureMeshes, featI)
342 featureEdgeVisited[featI].setSize(featureMeshes[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 = featureMeshes[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.
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_.nCells());
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]);
626 // Do test for higher intersections
627 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
629 labelList surfaceHit;
630 labelList surfaceMinLevel;
631 surfaces_.findHigherIntersection
642 // Mark cells for refinement
643 // ~~~~~~~~~~~~~~~~~~~~~~~~~
647 label faceI = testFaces[i];
649 label surfI = surfaceHit[i];
653 // Found intersection with surface with higher wanted
654 // refinement. Check if the level field on that surface
655 // specifies an even higher level. Note:this is weird. Should
656 // do the check with the surfaceMinLevel whilst intersecting the
659 label own = mesh_.faceOwner()[faceI];
661 if (surfaceMinLevel[i] > cellLevel[own])
663 // Owner needs refining
679 if (mesh_.isInternalFace(faceI))
681 label nei = mesh_.faceNeighbour()[faceI];
682 if (surfaceMinLevel[i] > cellLevel[nei])
684 // Neighbour needs refining
705 returnReduce(nRefine, sumOp<label>())
706 > returnReduce(nAllowRefine, sumOp<label>())
709 Info<< "Reached refinement limit." << endl;
712 return returnReduce(nRefine-oldNRefine, sumOp<label>());
716 // Checks if multiple intersections of a cell (by a surface with a higher
717 // max than the cell level) and if so if the normals at these intersections
718 // make a large angle.
719 // Returns false if the nRefine limit has been reached, true otherwise.
720 bool Foam::meshRefinement::checkCurvature
722 const scalar curvature,
723 const label nAllowRefine,
725 const label surfaceLevel, // current intersection max level
726 const vector& surfaceNormal,// current intersection normal
730 label& cellMaxLevel, // cached max surface level for this cell
731 vector& cellMaxNormal, // cached surface normal for this cell
733 labelList& refineCell,
737 const labelList& cellLevel = meshCutter_.cellLevel();
739 // Test if surface applicable
740 if (surfaceLevel > cellLevel[cellI])
742 if (cellMaxLevel == -1)
744 // First visit of cell. Store
745 cellMaxLevel = surfaceLevel;
746 cellMaxNormal = surfaceNormal;
750 // Second or more visit. Check curvature.
751 if ((cellMaxNormal & surfaceNormal) < curvature)
755 surfaceLevel, // mark with any non-neg number.
762 // Set normal to that of highest surface. Not really necessary
763 // over here but we reuse cellMax info when doing coupled faces.
764 if (surfaceLevel > cellMaxLevel)
766 cellMaxLevel = surfaceLevel;
767 cellMaxNormal = surfaceNormal;
772 // Did not reach refinement limit.
777 // Mark cells for surface curvature based refinement.
778 Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
780 const scalar curvature,
781 const label nAllowRefine,
782 const labelList& neiLevel,
783 const pointField& neiCc,
785 labelList& refineCell,
789 const labelList& cellLevel = meshCutter_.cellLevel();
790 const pointField& cellCentres = mesh_.cellCentres();
792 label oldNRefine = nRefine;
794 // 1. local test: any cell on more than one surface gets refined
795 // (if its current level is < max of the surface max level)
797 // 2. 'global' test: any cell on only one surface with a neighbour
798 // on a different surface gets refined (if its current level etc.)
801 // Collect candidate faces (i.e. intersecting any surface and
802 // owner/neighbour not yet refined.
803 labelList testFaces(getRefineCandidateFaces(refineCell));
806 pointField start(testFaces.size());
807 pointField end(testFaces.size());
808 labelList minLevel(testFaces.size());
812 label faceI = testFaces[i];
814 label own = mesh_.faceOwner()[faceI];
816 if (mesh_.isInternalFace(faceI))
818 label nei = mesh_.faceNeighbour()[faceI];
820 start[i] = cellCentres[own];
821 end[i] = cellCentres[nei];
822 minLevel[i] = min(cellLevel[own], cellLevel[nei]);
826 label bFaceI = faceI - mesh_.nInternalFaces();
828 start[i] = cellCentres[own];
829 end[i] = neiCc[bFaceI];
830 minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
834 // Test for all intersections (with surfaces of higher max level than
835 // minLevel) and cache per cell the max surface level and the local normal
837 labelList cellMaxLevel(mesh_.nCells(), -1);
838 vectorField cellMaxNormal(mesh_.nCells());
841 // Per segment the normals of the surfaces
842 List<vectorList> surfaceNormal;
843 // Per segment the list of levels of the surfaces
844 labelListList surfaceLevel;
846 surfaces_.findAllHigherIntersections
850 minLevel, // max level of surface has to be bigger
851 // than min level of neighbouring cells
855 // Clear out unnecessary data
860 // Extract per cell information on the surface with the highest max
863 label faceI = testFaces[i];
864 label own = mesh_.faceOwner()[faceI];
866 const vectorList& fNormals = surfaceNormal[i];
867 const labelList& fLevels = surfaceLevel[i];
869 forAll(fLevels, hitI)
888 if (mesh_.isInternalFace(faceI))
890 label nei = mesh_.faceNeighbour()[faceI];
892 forAll(fLevels, hitI)
914 // 2. Find out a measure of surface curvature and region edges.
915 // Send over surface region and surface normal to neighbour cell.
917 labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces());
918 vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces());
920 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
922 label bFaceI = faceI-mesh_.nInternalFaces();
923 label own = mesh_.faceOwner()[faceI];
925 neiBndMaxLevel[bFaceI] = cellMaxLevel[own];
926 neiBndMaxNormal[bFaceI] = cellMaxNormal[own];
928 syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel, false);
929 syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal, false);
931 // Loop over all faces. Could only be checkFaces.. except if they're coupled
934 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
936 label own = mesh_.faceOwner()[faceI];
937 label nei = mesh_.faceNeighbour()[faceI];
939 if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1)
941 // Have valid data on both sides. Check curvature.
942 if ((cellMaxNormal[own] & cellMaxNormal[nei]) < curvature)
944 // See which side to refine
945 if (cellLevel[own] < cellMaxLevel[own])
960 Pout<< "Stopped refining since reaching my cell"
961 << " limit of " << mesh_.nCells()+7*nRefine
968 if (cellLevel[nei] < cellMaxLevel[nei])
983 Pout<< "Stopped refining since reaching my cell"
984 << " limit of " << mesh_.nCells()+7*nRefine
994 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
996 label own = mesh_.faceOwner()[faceI];
997 label bFaceI = faceI - mesh_.nInternalFaces();
999 if (cellLevel[own] < cellMaxLevel[own] && neiBndMaxLevel[bFaceI] != -1)
1001 // Have valid data on both sides. Check curvature.
1002 if ((cellMaxNormal[own] & neiBndMaxNormal[bFaceI]) < curvature)
1017 Pout<< "Stopped refining since reaching my cell"
1018 << " limit of " << mesh_.nCells()+7*nRefine
1029 returnReduce(nRefine, sumOp<label>())
1030 > returnReduce(nAllowRefine, sumOp<label>())
1033 Info<< "Reached refinement limit." << endl;
1036 return returnReduce(nRefine-oldNRefine, sumOp<label>());
1040 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1042 // Calculate list of cells to refine. Gets for any edge (start - end)
1043 // whether it intersects the surface. Does more accurate test and checks
1044 // the wanted level on the surface intersected.
1045 // Does approximate precalculation of how many cells can be refined before
1046 // hitting overall limit maxGlobalCells.
1047 Foam::labelList Foam::meshRefinement::refineCandidates
1049 const point& keepPoint,
1050 const scalar curvature,
1052 const PtrList<featureEdgeMesh>& featureMeshes,
1053 const labelList& featureLevels,
1055 const bool featureRefinement,
1056 const bool internalRefinement,
1057 const bool surfaceRefinement,
1058 const bool curvatureRefinement,
1059 const label maxGlobalCells,
1060 const label maxLocalCells
1063 label totNCells = mesh_.globalData().nTotalCells();
1065 labelList cellsToRefine;
1067 if (totNCells >= maxGlobalCells)
1069 Info<< "No cells marked for refinement since reached limit "
1070 << maxGlobalCells << '.' << endl;
1074 // Every cell I refine adds 7 cells. Estimate the number of cells
1075 // I am allowed to refine.
1076 // Assume perfect distribution so can only refine as much the fraction
1077 // of the mesh I hold. This prediction step prevents us having to do
1078 // lots of reduces to keep count of the total number of cells selected
1081 //scalar fraction = scalar(mesh_.nCells())/totNCells;
1082 //label myMaxCells = label(maxGlobalCells*fraction);
1083 //label nAllowRefine = (myMaxCells - mesh_.nCells())/7;
1084 ////label nAllowRefine = (maxLocalCells - mesh_.nCells())/7;
1086 //Pout<< "refineCandidates:" << nl
1087 // << " total cells:" << totNCells << nl
1088 // << " local cells:" << mesh_.nCells() << nl
1089 // << " local fraction:" << fraction << nl
1090 // << " local allowable cells:" << myMaxCells << nl
1091 // << " local allowable refinement:" << nAllowRefine << nl
1094 //- Disable refinement shortcut
1095 label nAllowRefine = labelMax;
1097 // Marked for refinement (>= 0) or not (-1). Actual value is the
1098 // index of the surface it intersects.
1099 labelList refineCell(mesh_.nCells(), -1);
1103 // Swap neighbouring cell centres and cell level
1104 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1105 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
1106 calcNeighbourData(neiLevel, neiCc);
1110 // Cells pierced by feature lines
1111 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1113 if (featureRefinement)
1115 label nFeatures = markFeatureRefinement
1126 Info<< "Marked for refinement due to explicit features : "
1127 << nFeatures << " cells." << endl;
1130 // Inside refinement shells
1131 // ~~~~~~~~~~~~~~~~~~~~~~~~
1133 if (internalRefinement)
1135 label nShell = markInternalRefinement
1142 Info<< "Marked for refinement due to refinement shells : "
1143 << nShell << " cells." << endl;
1146 // Refinement based on intersection of surface
1147 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1149 if (surfaceRefinement)
1151 label nSurf = markSurfaceRefinement
1160 Info<< "Marked for refinement due to surface intersection : "
1161 << nSurf << " cells." << endl;
1164 // Refinement based on curvature of surface
1165 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1167 if (curvatureRefinement && (curvature >= -1 && curvature <= 1))
1169 label nCurv = markSurfaceCurvatureRefinement
1179 Info<< "Marked for refinement due to curvature/regions : "
1180 << nCurv << " cells." << endl;
1183 // Pack cells-to-refine
1184 // ~~~~~~~~~~~~~~~~~~~~
1186 cellsToRefine.setSize(nRefine);
1189 forAll(refineCell, cellI)
1191 if (refineCell[cellI] != -1)
1193 cellsToRefine[nRefine++] = cellI;
1198 return cellsToRefine;
1202 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::refine
1204 const labelList& cellsToRefine
1207 // Mesh changing engine.
1208 polyTopoChange meshMod(mesh_);
1210 // Play refinement commands into mesh changer.
1211 meshCutter_.setRefinement(cellsToRefine, meshMod);
1213 // Create mesh (no inflation), return map from old to new mesh.
1214 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false);
1217 mesh_.updateMesh(map);
1219 // Optionally inflate mesh
1220 if (map().hasMotionPoints())
1222 mesh_.movePoints(map().preMotionPoints());
1225 // Update intersection info
1226 updateMesh(map, getChangedFaces(map, cellsToRefine));
1232 // Do refinement of consistent set of cells followed by truncation and
1234 Foam::autoPtr<Foam::mapDistributePolyMesh>
1235 Foam::meshRefinement::refineAndBalance
1238 decompositionMethod& decomposer,
1239 fvMeshDistribute& distributor,
1240 const labelList& cellsToRefine
1243 // Do all refinement
1244 refine(cellsToRefine);
1248 Pout<< "Writing refined but unbalanced " << msg
1249 << " mesh to time " << mesh_.time().timeName() << endl;
1254 /mesh_.time().timeName()
1256 Pout<< "Dumped debug data in = "
1257 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1259 // test all is still synced across proc patches
1263 Info<< "Refined mesh in = "
1264 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1265 printMeshInfo(debug, "After refinement " + msg);
1271 autoPtr<mapDistributePolyMesh> distMap;
1273 if (Pstream::nProcs() > 1)
1275 labelList distribution(decomposer.decompose(mesh_.cellCentres()));
1276 // Get distribution such that baffle faces stay internal to the
1278 //labelList distribution(decomposePreserveBaffles(decomposer));
1282 Pout<< "Wanted distribution:"
1283 << distributor.countCells(distribution)
1286 // Do actual sending/receiving of mesh
1287 distMap = distributor.distribute(distribution);
1289 // Update numbering of meshRefiner
1290 distribute(distMap);
1292 Info<< "Balanced mesh in = "
1293 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1295 printMeshInfo(debug, "After balancing " + msg);
1300 Pout<< "Writing " << msg
1301 << " mesh to time " << mesh_.time().timeName() << endl;
1306 /mesh_.time().timeName()
1308 Pout<< "Dumped debug data in = "
1309 << mesh_.time().cpuTimeIncrement() << " s" << endl;
1311 // test all is still synced across proc patches
1320 // ************************************************************************* //