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 "SortableList.H"
28 #include "dynamicRefineFvMesh.H"
29 #include "addToRunTimeSelectionTable.H"
30 #include "volFields.H"
31 #include "polyTopoChange.H"
32 #include "surfaceFields.H"
34 #include "syncTools.H"
35 #include "ListListOps.H"
36 #include "pointFields.H"
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 defineTypeNameAndDebug(dynamicRefineFvMesh, 0);
47 addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject);
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 label dynamicRefineFvMesh::count(const PackedList<1>& l, const unsigned int val)
66 void dynamicRefineFvMesh::calculateProtectedCells
68 PackedList<1>& unrefineableCell
71 if (protectedCell_.size() == 0)
73 unrefineableCell.clear();
77 const labelList& cellLevel = meshCutter_.cellLevel();
79 unrefineableCell = protectedCell_;
81 // Get neighbouring cell level
82 labelList neiLevel(nFaces()-nInternalFaces());
84 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
86 neiLevel[faceI-nInternalFaces()] = cellLevel[faceOwner()[faceI]];
88 syncTools::swapBoundaryFaceList(*this, neiLevel, false);
93 // Pick up faces on border of protected cells
94 boolList seedFace(nFaces(), false);
96 forAll(faceNeighbour(), faceI)
98 label own = faceOwner()[faceI];
99 bool ownProtected = (unrefineableCell.get(own) == 1);
100 label nei = faceNeighbour()[faceI];
101 bool neiProtected = (unrefineableCell.get(nei) == 1);
103 if (ownProtected && (cellLevel[nei] > cellLevel[own]))
105 seedFace[faceI] = true;
107 else if (neiProtected && (cellLevel[own] > cellLevel[nei]))
109 seedFace[faceI] = true;
112 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
114 label own = faceOwner()[faceI];
115 bool ownProtected = (unrefineableCell.get(own) == 1);
119 && (neiLevel[faceI-nInternalFaces()] > cellLevel[own])
122 seedFace[faceI] = true;
126 syncTools::syncFaceList(*this, seedFace, orEqOp<bool>(), false);
129 // Extend unrefineableCell
130 bool hasExtended = false;
132 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
136 label own = faceOwner()[faceI];
137 if (unrefineableCell.get(own) == 0)
139 unrefineableCell.set(own, 1);
143 label nei = faceNeighbour()[faceI];
144 if (unrefineableCell.get(nei) == 0)
146 unrefineableCell.set(nei, 1);
151 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
155 label own = faceOwner()[faceI];
156 if (unrefineableCell.get(own) == 0)
158 unrefineableCell.set(own, 1);
164 if (!returnReduce(hasExtended, orOp<bool>()))
172 void dynamicRefineFvMesh::readDict()
174 dictionary refineDict
187 ).subDict(typeName + "Coeffs")
190 correctFluxes_ = List<Pair<word> >(refineDict.lookup("correctFluxes"));
192 dumpLevel_ = Switch(refineDict.lookup("dumpLevel"));
196 // Refines cells, maps fields and recalculates (an approximate) flux
197 autoPtr<mapPolyMesh> dynamicRefineFvMesh::refine
199 const labelList& cellsToRefine
202 // Mesh changing engine.
203 polyTopoChange meshMod(*this);
205 // Play refinement commands into mesh changer.
206 meshCutter_.setRefinement(cellsToRefine, meshMod);
208 // Create mesh (with inflation), return map from old to new mesh.
209 //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
210 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
212 Info<< "Refined from "
213 << returnReduce(map().nOldCells(), sumOp<label>())
214 << " to " << globalData().nTotalCells() << " cells." << endl;
219 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
221 label oldFaceI = map().faceMap()[faceI];
223 if (oldFaceI >= nInternalFaces())
225 FatalErrorIn("dynamicRefineFvMesh::refine")
226 << "New internal face:" << faceI
227 << " fc:" << faceCentres()[faceI]
228 << " originates from boundary oldFace:" << oldFaceI
229 << abort(FatalError);
240 pointField newPoints;
241 if (map().hasMotionPoints())
243 newPoints = map().preMotionPoints();
247 newPoints = points();
249 movePoints(newPoints);
252 // Correct the flux for modified/added faces. All the faces which only
253 // have been renumbered will already have been handled by the mapping.
255 const labelList& faceMap = map().faceMap();
256 const labelList& reverseFaceMap = map().reverseFaceMap();
258 // Storage for any master faces. These will be the original faces
259 // on the coarse cell that get split into four (or rather the
260 // master face gets modified and three faces get added from the master)
261 labelHashSet masterFaces(4*cellsToRefine.size());
263 forAll(faceMap, faceI)
265 label oldFaceI = faceMap[faceI];
269 label masterFaceI = reverseFaceMap[oldFaceI];
275 "dynamicRefineFvMesh::refine(const labelList&)"
276 ) << "Problem: should not have removed faces"
278 << nl << "face:" << faceI << abort(FatalError);
280 else if (masterFaceI != faceI)
282 masterFaces.insert(masterFaceI);
288 Info<< "Found " << returnReduce(masterFaces.size(), sumOp<label>())
289 << " split faces " << endl;
292 forAll(correctFluxes_, i)
296 Info<< "Mapping flux " << correctFluxes_[i][0]
297 << " using interpolated flux " << correctFluxes_[i][1]
300 surfaceScalarField& phi = const_cast<surfaceScalarField&>
302 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
304 surfaceScalarField phiU =
307 lookupObject<volVectorField>(correctFluxes_[i][1])
311 // Recalculate new internal faces.
312 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
314 label oldFaceI = faceMap[faceI];
319 phi[faceI] = phiU[faceI];
321 else if (reverseFaceMap[oldFaceI] != faceI)
323 // face-from-masterface
324 phi[faceI] = phiU[faceI];
328 // Recalculate new boundary faces.
329 forAll(phi.boundaryField(), patchI)
331 fvsPatchScalarField& patchPhi = phi.boundaryField()[patchI];
332 const fvsPatchScalarField& patchPhiU =
333 phiU.boundaryField()[patchI];
335 label faceI = patchPhi.patch().patch().start();
339 label oldFaceI = faceMap[faceI];
344 patchPhi[i] = patchPhiU[i];
346 else if (reverseFaceMap[oldFaceI] != faceI)
348 // face-from-masterface
349 patchPhi[i] = patchPhiU[i];
356 // Update master faces
357 forAllConstIter(labelHashSet, masterFaces, iter)
359 label faceI = iter.key();
361 if (isInternalFace(faceI))
363 phi[faceI] = phiU[faceI];
367 label patchI = boundaryMesh().whichPatch(faceI);
368 label i = faceI - boundaryMesh()[patchI].start();
370 const fvsPatchScalarField& patchPhiU =
371 phiU.boundaryField()[patchI];
373 fvsPatchScalarField& patchPhi =
374 phi.boundaryField()[patchI];
376 patchPhi[i] = patchPhiU[i];
384 // Update numbering of cells/vertices.
385 meshCutter_.updateMesh(map);
387 // Update numbering of protectedCell_
388 if (protectedCell_.size() > 0)
390 PackedList<1> newProtectedCell(nCells(), 0);
392 forAll(newProtectedCell, cellI)
394 label oldCellI = map().cellMap()[cellI];
395 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
397 protectedCell_.transfer(newProtectedCell);
400 // Debug: Check refinement levels (across faces only)
401 meshCutter_.checkRefinementLevels(-1, labelList(0));
407 // Combines previously split cells, maps fields and recalculates
408 // (an approximate) flux
409 autoPtr<mapPolyMesh> dynamicRefineFvMesh::unrefine
411 const labelList& splitPoints
414 polyTopoChange meshMod(*this);
416 // Play refinement commands into mesh changer.
417 meshCutter_.setUnrefinement(splitPoints, meshMod);
420 // Save information on faces that will be combined
421 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423 // Find the faceMidPoints on cells to be combined.
424 // for each face resulting of split of face into four store the
426 Map<label> faceToSplitPoint(3*splitPoints.size());
429 forAll(splitPoints, i)
431 label pointI = splitPoints[i];
433 const labelList& pEdges = pointEdges()[pointI];
437 label otherPointI = edges()[pEdges[j]].otherVertex(pointI);
439 const labelList& pFaces = pointFaces()[otherPointI];
441 forAll(pFaces, pFaceI)
443 faceToSplitPoint.insert(pFaces[pFaceI], otherPointI);
450 // Change mesh and generate mesh.
451 //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
452 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
454 Info<< "Unrefined from "
455 << returnReduce(map().nOldCells(), sumOp<label>())
456 << " to " << globalData().nTotalCells() << " cells."
465 pointField newPoints;
466 if (map().hasMotionPoints())
468 newPoints = map().preMotionPoints();
472 newPoints = points();
474 movePoints(newPoints);
477 // Correct the flux for modified faces.
479 const labelList& reversePointMap = map().reversePointMap();
480 const labelList& reverseFaceMap = map().reverseFaceMap();
482 forAll(correctFluxes_, i)
486 Info<< "Mapping flux " << correctFluxes_[i][0]
487 << " using interpolated flux " << correctFluxes_[i][1]
490 surfaceScalarField& phi = const_cast<surfaceScalarField&>
492 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
494 surfaceScalarField phiU =
497 lookupObject<volVectorField>(correctFluxes_[i][1])
501 forAllConstIter(Map<label>, faceToSplitPoint, iter)
503 label oldFaceI = iter.key();
504 label oldPointI = iter();
506 if (reversePointMap[oldPointI] < 0)
508 // midpoint was removed. See if face still exists.
509 label faceI = reverseFaceMap[oldFaceI];
513 if (isInternalFace(faceI))
515 phi[faceI] = phiU[faceI];
519 label patchI = boundaryMesh().whichPatch(faceI);
520 label i = faceI - boundaryMesh()[patchI].start();
522 const fvsPatchScalarField& patchPhiU =
523 phiU.boundaryField()[patchI];
525 fvsPatchScalarField& patchPhi =
526 phi.boundaryField()[patchI];
528 patchPhi[i] = patchPhiU[i];
537 // Update numbering of cells/vertices.
538 meshCutter_.updateMesh(map);
540 // Update numbering of protectedCell_
541 if (protectedCell_.size() > 0)
543 PackedList<1> newProtectedCell(nCells(), 0);
545 forAll(newProtectedCell, cellI)
547 label oldCellI = map().cellMap()[cellI];
550 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
553 protectedCell_.transfer(newProtectedCell);
556 // Debug: Check refinement levels (across faces only)
557 meshCutter_.checkRefinementLevels(-1, labelList(0));
563 // Get max of connected point
564 scalarField dynamicRefineFvMesh::maxPointField(const scalarField& pFld) const
566 scalarField vFld(nCells(), -GREAT);
568 forAll(pointCells(), pointI)
570 const labelList& pCells = pointCells()[pointI];
574 vFld[pCells[i]] = max(vFld[pCells[i]], pFld[pointI]);
581 // Get min of connected cell
582 scalarField dynamicRefineFvMesh::minCellField(const volScalarField& vFld) const
584 scalarField pFld(nPoints(), GREAT);
586 forAll(pointCells(), pointI)
588 const labelList& pCells = pointCells()[pointI];
592 pFld[pointI] = min(pFld[pointI], vFld[pCells[i]]);
599 // Simple (non-parallel) interpolation by averaging.
600 scalarField dynamicRefineFvMesh::cellToPoint(const scalarField& vFld) const
602 scalarField pFld(nPoints());
604 forAll(pointCells(), pointI)
606 const labelList& pCells = pointCells()[pointI];
611 sum += vFld[pCells[i]];
613 pFld[pointI] = sum/pCells.size();
619 // Calculate error. Is < 0 or distance from inbetween levels
620 scalarField dynamicRefineFvMesh::error
622 const scalarField& fld,
623 const scalar minLevel,
624 const scalar maxLevel
627 const scalar halfLevel = 0.5*(minLevel + maxLevel);
629 scalarField c(fld.size(), -1);
633 if (fld[i] >= minLevel && fld[i] < maxLevel)
635 c[i] = mag(fld[i] - halfLevel);
642 void dynamicRefineFvMesh::selectRefineCandidates
644 const scalar lowerRefineLevel,
645 const scalar upperRefineLevel,
646 const scalarField& vFld,
647 PackedList<1>& candidateCell
650 // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
651 // higher more desirable to be refined).
652 scalarField cellError
665 // Mark cells that are candidates for refinement.
666 forAll(cellError, cellI)
668 if (cellError[cellI] > 0)
670 candidateCell.set(cellI, 1);
676 labelList dynamicRefineFvMesh::selectRefineCells
678 const label maxCells,
679 const label maxRefinement,
680 const PackedList<1>& candidateCell
683 // Every refined cell causes 7 extra cells
684 label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
686 const labelList& cellLevel = meshCutter_.cellLevel();
688 // Mark cells that cannot be refined since they would trigger refinement
689 // of protected cells (since 2:1 cascade)
690 PackedList<1> unrefineableCell;
691 calculateProtectedCells(unrefineableCell);
693 // Count current selection
694 label nCandidates = returnReduce(count(candidateCell, 1), sumOp<label>());
697 DynamicList<label> candidates(nCells());
699 if (nCandidates < nTotToRefine)
701 forAll(candidateCell, cellI)
705 cellLevel[cellI] < maxRefinement
706 && candidateCell.get(cellI) == 1
708 unrefineableCell.size() == 0
709 || unrefineableCell.get(cellI) == 0
713 candidates.append(cellI);
719 // Sort by error? For now just truncate.
720 for (label level = 0; level < maxRefinement; level++)
722 forAll(candidateCell, cellI)
726 cellLevel[cellI] == level
727 && candidateCell.get(cellI) == 1
729 unrefineableCell.size() == 0
730 || unrefineableCell.get(cellI) == 0
734 candidates.append(cellI);
738 if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
745 // Guarantee 2:1 refinement after refinement
746 labelList consistentSet
748 meshCutter_.consistentRefinement
751 true // Add to set to guarantee 2:1
755 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
756 << " cells for refinement out of " << globalData().nTotalCells()
759 return consistentSet;
763 labelList dynamicRefineFvMesh::selectUnrefinePoints
765 const scalar unrefineLevel,
766 const PackedList<1>& markedCell,
767 const scalarField& pFld
770 // All points that can be unrefined
771 const labelList splitPoints(meshCutter_.getSplitPoints());
773 DynamicList<label> newSplitPoints(splitPoints.size());
775 forAll(splitPoints, i)
777 label pointI = splitPoints[i];
779 if (pFld[pointI] < unrefineLevel)
781 // Check that all cells are not marked
782 const labelList& pCells = pointCells()[pointI];
784 bool hasMarked = false;
786 forAll(pCells, pCellI)
788 if (markedCell.get(pCells[pCellI]) == 1)
797 newSplitPoints.append(pointI);
803 newSplitPoints.shrink();
805 // Guarantee 2:1 refinement after unrefinement
806 labelList consistentSet
808 meshCutter_.consistentUnrefinement
814 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
815 << " split points out of a possible "
816 << returnReduce(splitPoints.size(), sumOp<label>())
819 return consistentSet;
823 void dynamicRefineFvMesh::extendMarkedCells(PackedList<1>& markedCell) const
825 // Mark faces using any marked cell
826 boolList markedFace(nFaces(), false);
828 forAll(markedCell, cellI)
830 if (markedCell.get(cellI) == 1)
832 const cell& cFaces = cells()[cellI];
836 markedFace[cFaces[i]] = true;
841 syncTools::syncFaceList(*this, markedFace, orEqOp<bool>(), false);
843 // Update cells using any markedFace
844 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
846 if (markedFace[faceI])
848 markedCell.set(faceOwner()[faceI], 1);
849 markedCell.set(faceNeighbour()[faceI], 1);
852 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
854 if (markedFace[faceI])
856 markedCell.set(faceOwner()[faceI], 1);
862 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
864 dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
869 nRefinementIterations_(0),
870 protectedCell_(nCells(), 0)
872 const labelList& cellLevel = meshCutter_.cellLevel();
873 const labelList& pointLevel = meshCutter_.pointLevel();
875 // Set cells that should not be refined.
876 // This is currently any cell which does not have 8 anchor points or
877 // uses any face which does not have 4 anchor points.
878 // Note: do not use cellPoint addressing
880 // Count number of points <= cellLevel
881 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
883 labelList nAnchors(nCells(), 0);
885 label nProtected = 0;
887 forAll(pointCells(), pointI)
889 const labelList& pCells = pointCells()[pointI];
893 label cellI = pCells[i];
895 if (protectedCell_.get(cellI) == 0)
897 if (pointLevel[pointI] <= cellLevel[cellI])
901 if (nAnchors[cellI] > 8)
903 protectedCell_.set(cellI, 1);
912 // Count number of points <= faceLevel
913 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
914 // Bit tricky since proc face might be one more refined than the owner since
915 // the coupled one is refined.
918 labelList neiLevel(nFaces());
920 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
922 neiLevel[faceI] = cellLevel[faceOwner()[faceI]];
924 syncTools::swapFaceList(*this, neiLevel, false);
927 boolList protectedFace(nFaces(), false);
929 forAll(faceOwner(), faceI)
931 label faceLevel = max
933 cellLevel[faceOwner()[faceI]],
937 const face& f = faces()[faceI];
943 if (pointLevel[f[fp]] <= faceLevel)
949 protectedFace[faceI] = true;
956 syncTools::syncFaceList
964 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
966 if (protectedFace[faceI])
968 protectedCell_.set(faceOwner()[faceI], 1);
970 protectedCell_.set(faceNeighbour()[faceI], 1);
974 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
976 if (protectedFace[faceI])
978 protectedCell_.set(faceOwner()[faceI], 1);
984 if (returnReduce(nProtected, sumOp<label>()) == 0)
986 protectedCell_.clear();
991 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
993 dynamicRefineFvMesh::~dynamicRefineFvMesh()
997 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
999 bool dynamicRefineFvMesh::update()
1001 // Re-read dictionary. Choosen since usually -small so trivial amount
1002 // of time compared to actual refinement. Also very useful to be able
1003 // to modify on-the-fly.
1004 dictionary refineDict
1013 IOobject::MUST_READ,
1017 ).subDict(typeName + "Coeffs")
1020 label refineInterval = readLabel(refineDict.lookup("refineInterval"));
1022 bool hasChanged = false;
1024 if (refineInterval == 0)
1026 changing(hasChanged);
1030 else if (refineInterval < 0)
1032 FatalErrorIn("dynamicRefineFvMesh::update()")
1033 << "Illegal refineInterval " << refineInterval << nl
1034 << "The refineInterval setting in the dynamicMeshDict should"
1035 << " be >= 1." << nl
1036 << exit(FatalError);
1042 // Note: cannot refine at time 0 since no V0 present since mesh not
1045 if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
1047 label maxCells = readLabel(refineDict.lookup("maxCells"));
1051 FatalErrorIn("dynamicRefineFvMesh::update()")
1052 << "Illegal maximum number of cells " << maxCells << nl
1053 << "The maxCells setting in the dynamicMeshDict should"
1055 << exit(FatalError);
1058 label maxRefinement = readLabel(refineDict.lookup("maxRefinement"));
1060 if (maxRefinement <= 0)
1062 FatalErrorIn("dynamicRefineFvMesh::update()")
1063 << "Illegal maximum refinement level " << maxRefinement << nl
1064 << "The maxCells setting in the dynamicMeshDict should"
1066 << exit(FatalError);
1069 word field(refineDict.lookup("field"));
1071 const volScalarField& vFld = lookupObject<volScalarField>(field);
1073 const scalar lowerRefineLevel =
1074 readScalar(refineDict.lookup("lowerRefineLevel"));
1075 const scalar upperRefineLevel =
1076 readScalar(refineDict.lookup("upperRefineLevel"));
1077 const scalar unrefineLevel =
1078 readScalar(refineDict.lookup("unrefineLevel"));
1079 const label nBufferLayers =
1080 readLabel(refineDict.lookup("nBufferLayers"));
1082 // Cells marked for refinement or otherwise protected from unrefinement.
1083 PackedList<1> refineCell(nCells(), 0);
1085 if (globalData().nTotalCells() < maxCells)
1087 // Determine candidates for refinement (looking at field only)
1088 selectRefineCandidates
1096 // Select subset of candidates. Take into account max allowable
1097 // cells, refinement level, protected cells.
1098 labelList cellsToRefine
1108 label nCellsToRefine = returnReduce
1110 cellsToRefine.size(), sumOp<label>()
1113 if (nCellsToRefine > 0)
1115 // Refine/update mesh and map fields
1116 autoPtr<mapPolyMesh> map = refine(cellsToRefine);
1118 // Update refineCell. Note that some of the marked ones have
1119 // not been refined due to constraints.
1121 const labelList& cellMap = map().cellMap();
1122 const labelList& reverseCellMap = map().reverseCellMap();
1124 PackedList<1> newRefineCell(cellMap.size());
1126 forAll(cellMap, cellI)
1128 label oldCellI = cellMap[cellI];
1132 newRefineCell.set(cellI, 1);
1134 else if (reverseCellMap[oldCellI] != cellI)
1136 newRefineCell.set(cellI, 1);
1140 newRefineCell.set(cellI, refineCell.get(oldCellI));
1143 refineCell.transfer(newRefineCell);
1146 // Extend with a buffer layer to prevent neighbouring points
1148 for (label i = 0; i < nBufferLayers; i++)
1150 extendMarkedCells(refineCell);
1159 // Select unrefineable points that are not marked in refineCell
1160 labelList pointsToUnrefine
1162 selectUnrefinePoints
1170 label nSplitPoints = returnReduce
1172 pointsToUnrefine.size(),
1176 if (nSplitPoints > 0)
1178 // Refine/update mesh
1179 unrefine(pointsToUnrefine);
1186 if ((nRefinementIterations_ % 10) == 0)
1188 // Compact refinement history occassionally (how often?).
1189 // Unrefinement causes holes in the refinementHistory.
1190 const_cast<refinementHistory&>(meshCutter().history()).compact();
1192 nRefinementIterations_++;
1195 changing(hasChanged);
1201 bool dynamicRefineFvMesh::writeObject
1203 IOstream::streamFormat fmt,
1204 IOstream::versionNumber ver,
1205 IOstream::compressionType cmp
1208 // Force refinement data to go to the current time directory.
1209 const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
1212 dynamicFvMesh::writeObjects(fmt, ver, cmp)
1213 && meshCutter_.write();
1217 volScalarField scalarCellLevel
1225 IOobject::AUTO_WRITE,
1229 dimensionedScalar("level", dimless, 0)
1232 const labelList& cellLevel = meshCutter_.cellLevel();
1234 forAll(cellLevel, cellI)
1236 scalarCellLevel[cellI] = cellLevel[cellI];
1239 writeOk = writeOk && scalarCellLevel.write();
1246 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1248 } // End namespace Foam
1250 // ************************************************************************* //