1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 "dynamicRefineFvMesh.H"
28 #include "addToRunTimeSelectionTable.H"
29 #include "volFields.H"
30 #include "surfaceFields.H"
32 #include "syncTools.H"
33 #include "pointFields.H"
34 #include "directTopoChange.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(dynamicRefineFvMesh, 0);
45 addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject);
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 label dynamicRefineFvMesh::count
52 const PackedBoolList& l,
53 const unsigned int val
68 void dynamicRefineFvMesh::calculateProtectedCells
70 PackedBoolList& unrefineableCell
73 if (protectedCell_.empty())
75 unrefineableCell.clear();
79 const labelList& cellLevel = meshCutter_.cellLevel();
81 unrefineableCell = protectedCell_;
83 // Get neighbouring cell level
84 labelList neiLevel(nFaces()-nInternalFaces());
86 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
88 neiLevel[faceI-nInternalFaces()] = cellLevel[faceOwner()[faceI]];
90 syncTools::swapBoundaryFaceList(*this, neiLevel, false);
95 // Pick up faces on border of protected cells
96 boolList seedFace(nFaces(), false);
98 forAll(faceNeighbour(), faceI)
100 label own = faceOwner()[faceI];
101 bool ownProtected = (unrefineableCell.get(own) == 1);
102 label nei = faceNeighbour()[faceI];
103 bool neiProtected = (unrefineableCell.get(nei) == 1);
105 if (ownProtected && (cellLevel[nei] > cellLevel[own]))
107 seedFace[faceI] = true;
109 else if (neiProtected && (cellLevel[own] > cellLevel[nei]))
111 seedFace[faceI] = true;
114 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
116 label own = faceOwner()[faceI];
117 bool ownProtected = (unrefineableCell.get(own) == 1);
121 && (neiLevel[faceI-nInternalFaces()] > cellLevel[own])
124 seedFace[faceI] = true;
128 syncTools::syncFaceList(*this, seedFace, orEqOp<bool>(), false);
131 // Extend unrefineableCell
132 bool hasExtended = false;
134 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
138 label own = faceOwner()[faceI];
139 if (unrefineableCell.get(own) == 0)
141 unrefineableCell.set(own, 1);
145 label nei = faceNeighbour()[faceI];
146 if (unrefineableCell.get(nei) == 0)
148 unrefineableCell.set(nei, 1);
153 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
157 label own = faceOwner()[faceI];
158 if (unrefineableCell.get(own) == 0)
160 unrefineableCell.set(own, 1);
166 if (!returnReduce(hasExtended, orOp<bool>()))
174 void dynamicRefineFvMesh::readDict()
176 dictionary refineDict
189 ).subDict(typeName + "Coeffs")
192 correctFluxes_ = List<Pair<word> >(refineDict.lookup("correctFluxes"));
194 dumpLevel_ = Switch(refineDict.lookup("dumpLevel"));
198 // Refines cells, maps fields and recalculates (an approximate) flux
199 autoPtr<mapPolyMesh> dynamicRefineFvMesh::refine
201 const labelList& cellsToRefine
204 // Mesh changing engine.
205 directTopoChange meshMod(*this);
207 // Play refinement commands into mesh changer.
208 meshCutter_.setRefinement(cellsToRefine, meshMod);
210 // Create mesh (with inflation), return map from old to new mesh.
211 //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
212 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
214 Info<< "Refined from "
215 << returnReduce(map().nOldCells(), sumOp<label>())
216 << " to " << globalData().nTotalCells() << " cells." << endl;
221 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
223 label oldFaceI = map().faceMap()[faceI];
225 if (oldFaceI >= nInternalFaces())
227 FatalErrorIn("dynamicRefineFvMesh::refine(const labelList&)")
228 << "New internal face:" << faceI
229 << " fc:" << faceCentres()[faceI]
230 << " originates from boundary oldFace:" << oldFaceI
231 << abort(FatalError);
242 pointField newPoints;
243 if (map().hasMotionPoints())
245 newPoints = map().preMotionPoints();
249 newPoints = points();
251 movePoints(newPoints);
254 // Correct the flux for modified/added faces. All the faces which only
255 // have been renumbered will already have been handled by the mapping.
257 const labelList& faceMap = map().faceMap();
258 const labelList& reverseFaceMap = map().reverseFaceMap();
260 // Storage for any master faces. These will be the original faces
261 // on the coarse cell that get split into four (or rather the
262 // master face gets modified and three faces get added from the master)
263 labelHashSet masterFaces(4*cellsToRefine.size());
265 forAll(faceMap, faceI)
267 label oldFaceI = faceMap[faceI];
271 label masterFaceI = reverseFaceMap[oldFaceI];
277 "dynamicRefineFvMesh::refine(const labelList&)"
278 ) << "Problem: should not have removed faces"
280 << nl << "face:" << faceI << abort(FatalError);
282 else if (masterFaceI != faceI)
284 masterFaces.insert(masterFaceI);
290 Info<< "Found " << returnReduce(masterFaces.size(), sumOp<label>())
291 << " split faces " << endl;
294 forAll(correctFluxes_, i)
298 Info<< "Mapping flux " << correctFluxes_[i][0]
299 << " using interpolated flux " << correctFluxes_[i][1]
302 surfaceScalarField& phi = const_cast<surfaceScalarField&>
304 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
306 surfaceScalarField phiU =
309 lookupObject<volVectorField>(correctFluxes_[i][1])
313 // Recalculate new internal faces.
314 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
316 label oldFaceI = faceMap[faceI];
321 phi[faceI] = phiU[faceI];
323 else if (reverseFaceMap[oldFaceI] != faceI)
325 // face-from-masterface
326 phi[faceI] = phiU[faceI];
330 // Recalculate new boundary faces.
331 forAll(phi.boundaryField(), patchI)
333 fvsPatchScalarField& patchPhi = phi.boundaryField()[patchI];
334 const fvsPatchScalarField& patchPhiU =
335 phiU.boundaryField()[patchI];
337 label faceI = patchPhi.patch().patch().start();
341 label oldFaceI = faceMap[faceI];
346 patchPhi[i] = patchPhiU[i];
348 else if (reverseFaceMap[oldFaceI] != faceI)
350 // face-from-masterface
351 patchPhi[i] = patchPhiU[i];
358 // Update master faces
359 forAllConstIter(labelHashSet, masterFaces, iter)
361 label faceI = iter.key();
363 if (isInternalFace(faceI))
365 phi[faceI] = phiU[faceI];
369 label patchI = boundaryMesh().whichPatch(faceI);
370 label i = faceI - boundaryMesh()[patchI].start();
372 const fvsPatchScalarField& patchPhiU =
373 phiU.boundaryField()[patchI];
375 fvsPatchScalarField& patchPhi =
376 phi.boundaryField()[patchI];
378 patchPhi[i] = patchPhiU[i];
386 // Update numbering of cells/vertices.
387 meshCutter_.updateMesh(map);
389 // Update numbering of protectedCell_
390 if (protectedCell_.size())
392 PackedBoolList newProtectedCell(nCells());
394 forAll(newProtectedCell, cellI)
396 label oldCellI = map().cellMap()[cellI];
397 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
399 protectedCell_.transfer(newProtectedCell);
402 // Debug: Check refinement levels (across faces only)
403 meshCutter_.checkRefinementLevels(-1, labelList(0));
409 // Combines previously split cells, maps fields and recalculates
410 // (an approximate) flux
411 autoPtr<mapPolyMesh> dynamicRefineFvMesh::unrefine
413 const labelList& splitPoints
416 directTopoChange meshMod(*this);
418 // Play refinement commands into mesh changer.
419 meshCutter_.setUnrefinement(splitPoints, meshMod);
422 // Save information on faces that will be combined
423 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
425 // Find the faceMidPoints on cells to be combined.
426 // for each face resulting of split of face into four store the
428 Map<label> faceToSplitPoint(3*splitPoints.size());
431 forAll(splitPoints, i)
433 label pointI = splitPoints[i];
435 const labelList& pEdges = pointEdges()[pointI];
439 label otherPointI = edges()[pEdges[j]].otherVertex(pointI);
441 const labelList& pFaces = pointFaces()[otherPointI];
443 forAll(pFaces, pFaceI)
445 faceToSplitPoint.insert(pFaces[pFaceI], otherPointI);
452 // Change mesh and generate map.
453 //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
454 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
456 Info<< "Unrefined from "
457 << returnReduce(map().nOldCells(), sumOp<label>())
458 << " to " << globalData().nTotalCells() << " cells."
467 pointField newPoints;
468 if (map().hasMotionPoints())
470 newPoints = map().preMotionPoints();
474 newPoints = points();
476 movePoints(newPoints);
479 // Correct the flux for modified faces.
481 const labelList& reversePointMap = map().reversePointMap();
482 const labelList& reverseFaceMap = map().reverseFaceMap();
484 forAll(correctFluxes_, i)
488 Info<< "Mapping flux " << correctFluxes_[i][0]
489 << " using interpolated flux " << correctFluxes_[i][1]
492 surfaceScalarField& phi = const_cast<surfaceScalarField&>
494 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
496 surfaceScalarField phiU =
499 lookupObject<volVectorField>(correctFluxes_[i][1])
503 forAllConstIter(Map<label>, faceToSplitPoint, iter)
505 label oldFaceI = iter.key();
506 label oldPointI = iter();
508 if (reversePointMap[oldPointI] < 0)
510 // midpoint was removed. See if face still exists.
511 label faceI = reverseFaceMap[oldFaceI];
515 if (isInternalFace(faceI))
517 phi[faceI] = phiU[faceI];
521 label patchI = boundaryMesh().whichPatch(faceI);
522 label i = faceI - boundaryMesh()[patchI].start();
524 const fvsPatchScalarField& patchPhiU =
525 phiU.boundaryField()[patchI];
527 fvsPatchScalarField& patchPhi =
528 phi.boundaryField()[patchI];
530 patchPhi[i] = patchPhiU[i];
539 // Update numbering of cells/vertices.
540 meshCutter_.updateMesh(map);
542 // Update numbering of protectedCell_
543 if (protectedCell_.size())
545 PackedBoolList newProtectedCell(nCells());
547 forAll(newProtectedCell, cellI)
549 label oldCellI = map().cellMap()[cellI];
552 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
555 protectedCell_.transfer(newProtectedCell);
558 // Debug: Check refinement levels (across faces only)
559 meshCutter_.checkRefinementLevels(-1, labelList(0));
565 // Get max of connected point
566 scalarField dynamicRefineFvMesh::maxPointField(const scalarField& pFld) const
568 scalarField vFld(nCells(), -GREAT);
570 forAll(pointCells(), pointI)
572 const labelList& pCells = pointCells()[pointI];
576 vFld[pCells[i]] = max(vFld[pCells[i]], pFld[pointI]);
583 // Get min of connected cell
584 scalarField dynamicRefineFvMesh::minCellField(const volScalarField& vFld) const
586 scalarField pFld(nPoints(), GREAT);
588 forAll(pointCells(), pointI)
590 const labelList& pCells = pointCells()[pointI];
594 pFld[pointI] = min(pFld[pointI], vFld[pCells[i]]);
601 // Simple (non-parallel) interpolation by averaging.
602 scalarField dynamicRefineFvMesh::cellToPoint(const scalarField& vFld) const
604 scalarField pFld(nPoints());
606 forAll(pointCells(), pointI)
608 const labelList& pCells = pointCells()[pointI];
613 sum += vFld[pCells[i]];
615 pFld[pointI] = sum/pCells.size();
621 // Calculate error. Is < 0 or distance from inbetween levels
622 scalarField dynamicRefineFvMesh::error
624 const scalarField& fld,
625 const scalar minLevel,
626 const scalar maxLevel
629 const scalar halfLevel = 0.5*(minLevel + maxLevel);
631 scalarField c(fld.size(), -1);
635 if (fld[i] >= minLevel && fld[i] < maxLevel)
637 c[i] = mag(fld[i] - halfLevel);
644 void dynamicRefineFvMesh::selectRefineCandidates
646 const scalar lowerRefineLevel,
647 const scalar upperRefineLevel,
648 const scalarField& vFld,
649 PackedBoolList& candidateCell
652 // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
653 // higher more desirable to be refined).
654 scalarField cellError
667 // Mark cells that are candidates for refinement.
668 forAll(cellError, cellI)
670 if (cellError[cellI] > 0)
672 candidateCell.set(cellI, 1);
678 labelList dynamicRefineFvMesh::selectRefineCells
680 const label maxCells,
681 const label maxRefinement,
682 const PackedBoolList& candidateCell
685 // Every refined cell causes 7 extra cells
686 label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
688 const labelList& cellLevel = meshCutter_.cellLevel();
690 // Mark cells that cannot be refined since they would trigger refinement
691 // of protected cells (since 2:1 cascade)
692 PackedBoolList unrefineableCell;
693 calculateProtectedCells(unrefineableCell);
695 // Count current selection
696 label nCandidates = returnReduce(count(candidateCell, 1), sumOp<label>());
699 DynamicList<label> candidates(nCells());
701 if (nCandidates < nTotToRefine)
703 forAll(candidateCell, cellI)
707 cellLevel[cellI] < maxRefinement
708 && candidateCell.get(cellI) == 1
710 unrefineableCell.empty()
711 || unrefineableCell.get(cellI) == 0
715 candidates.append(cellI);
721 // Sort by error? For now just truncate.
722 for (label level = 0; level < maxRefinement; level++)
724 forAll(candidateCell, cellI)
728 cellLevel[cellI] == level
729 && candidateCell.get(cellI) == 1
731 unrefineableCell.empty()
732 || unrefineableCell.get(cellI) == 0
736 candidates.append(cellI);
740 if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
747 // Guarantee 2:1 refinement after refinement
748 labelList consistentSet
750 meshCutter_.consistentRefinement
753 true // Add to set to guarantee 2:1
757 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
758 << " cells for refinement out of " << globalData().nTotalCells()
761 return consistentSet;
765 labelList dynamicRefineFvMesh::selectUnrefinePoints
767 const scalar unrefineLevel,
768 const PackedBoolList& markedCell,
769 const scalarField& pFld
772 // All points that can be unrefined
773 const labelList splitPoints(meshCutter_.getSplitPoints());
775 DynamicList<label> newSplitPoints(splitPoints.size());
777 forAll(splitPoints, i)
779 label pointI = splitPoints[i];
781 if (pFld[pointI] < unrefineLevel)
783 // Check that all cells are not marked
784 const labelList& pCells = pointCells()[pointI];
786 bool hasMarked = false;
788 forAll(pCells, pCellI)
790 if (markedCell.get(pCells[pCellI]) == 1)
799 newSplitPoints.append(pointI);
805 newSplitPoints.shrink();
807 // Guarantee 2:1 refinement after unrefinement
808 labelList consistentSet
810 meshCutter_.consistentUnrefinement
816 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
817 << " split points out of a possible "
818 << returnReduce(splitPoints.size(), sumOp<label>())
821 return consistentSet;
825 void dynamicRefineFvMesh::extendMarkedCells(PackedBoolList& markedCell) const
827 // Mark faces using any marked cell
828 boolList markedFace(nFaces(), false);
830 forAll(markedCell, cellI)
832 if (markedCell.get(cellI) == 1)
834 const cell& cFaces = cells()[cellI];
838 markedFace[cFaces[i]] = true;
843 syncTools::syncFaceList(*this, markedFace, orEqOp<bool>(), false);
845 // Update cells using any markedFace
846 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
848 if (markedFace[faceI])
850 markedCell.set(faceOwner()[faceI], 1);
851 markedCell.set(faceNeighbour()[faceI], 1);
854 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
856 if (markedFace[faceI])
858 markedCell.set(faceOwner()[faceI], 1);
864 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
866 dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
871 nRefinementIterations_(0),
872 protectedCell_(nCells(), 0)
874 const labelList& cellLevel = meshCutter_.cellLevel();
875 const labelList& pointLevel = meshCutter_.pointLevel();
877 // Set cells that should not be refined.
878 // This is currently any cell which does not have 8 anchor points or
879 // uses any face which does not have 4 anchor points.
880 // Note: do not use cellPoint addressing
882 // Count number of points <= cellLevel
883 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
885 labelList nAnchors(nCells(), 0);
887 label nProtected = 0;
889 forAll(pointCells(), pointI)
891 const labelList& pCells = pointCells()[pointI];
895 label cellI = pCells[i];
897 if (protectedCell_.get(cellI) == 0)
899 if (pointLevel[pointI] <= cellLevel[cellI])
903 if (nAnchors[cellI] > 8)
905 protectedCell_.set(cellI, 1);
914 // Count number of points <= faceLevel
915 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
916 // Bit tricky since proc face might be one more refined than the owner since
917 // the coupled one is refined.
920 labelList neiLevel(nFaces());
922 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
924 neiLevel[faceI] = cellLevel[faceNeighbour()[faceI]];
926 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
928 neiLevel[faceI] = cellLevel[faceOwner()[faceI]];
930 syncTools::swapFaceList(*this, neiLevel, false);
933 boolList protectedFace(nFaces(), false);
935 forAll(faceOwner(), faceI)
937 label faceLevel = max
939 cellLevel[faceOwner()[faceI]],
943 const face& f = faces()[faceI];
949 if (pointLevel[f[fp]] <= faceLevel)
955 protectedFace[faceI] = true;
962 syncTools::syncFaceList
970 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
972 if (protectedFace[faceI])
974 protectedCell_.set(faceOwner()[faceI], 1);
976 protectedCell_.set(faceNeighbour()[faceI], 1);
980 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
982 if (protectedFace[faceI])
984 protectedCell_.set(faceOwner()[faceI], 1);
990 if (returnReduce(nProtected, sumOp<label>()) == 0)
992 protectedCell_.clear();
997 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
999 dynamicRefineFvMesh::~dynamicRefineFvMesh()
1003 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1005 bool dynamicRefineFvMesh::update()
1007 // Re-read dictionary. Choosen since usually -small so trivial amount
1008 // of time compared to actual refinement. Also very useful to be able
1009 // to modify on-the-fly.
1010 dictionary refineDict
1019 IOobject::MUST_READ,
1023 ).subDict(typeName + "Coeffs")
1026 label refineInterval = readLabel(refineDict.lookup("refineInterval"));
1028 bool hasChanged = false;
1030 if (refineInterval == 0)
1032 changing(hasChanged);
1036 else if (refineInterval < 0)
1038 FatalErrorIn("dynamicRefineFvMesh::update()")
1039 << "Illegal refineInterval " << refineInterval << nl
1040 << "The refineInterval setting in the dynamicMeshDict should"
1041 << " be >= 1." << nl
1042 << exit(FatalError);
1048 // Note: cannot refine at time 0 since no V0 present since mesh not
1051 if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
1053 label maxCells = readLabel(refineDict.lookup("maxCells"));
1057 FatalErrorIn("dynamicRefineFvMesh::update()")
1058 << "Illegal maximum number of cells " << maxCells << nl
1059 << "The maxCells setting in the dynamicMeshDict should"
1061 << exit(FatalError);
1064 label maxRefinement = readLabel(refineDict.lookup("maxRefinement"));
1066 if (maxRefinement <= 0)
1068 FatalErrorIn("dynamicRefineFvMesh::update()")
1069 << "Illegal maximum refinement level " << maxRefinement << nl
1070 << "The maxCells setting in the dynamicMeshDict should"
1072 << exit(FatalError);
1075 word field(refineDict.lookup("field"));
1077 const volScalarField& vFld = lookupObject<volScalarField>(field);
1079 const scalar lowerRefineLevel =
1080 readScalar(refineDict.lookup("lowerRefineLevel"));
1081 const scalar upperRefineLevel =
1082 readScalar(refineDict.lookup("upperRefineLevel"));
1083 const scalar unrefineLevel =
1084 readScalar(refineDict.lookup("unrefineLevel"));
1085 const label nBufferLayers =
1086 readLabel(refineDict.lookup("nBufferLayers"));
1088 // Cells marked for refinement or otherwise protected from unrefinement.
1089 PackedBoolList refineCell(nCells());
1091 if (globalData().nTotalCells() < maxCells)
1093 // Determine candidates for refinement (looking at field only)
1094 selectRefineCandidates
1102 // Select subset of candidates. Take into account max allowable
1103 // cells, refinement level, protected cells.
1104 labelList cellsToRefine
1114 label nCellsToRefine = returnReduce
1116 cellsToRefine.size(), sumOp<label>()
1119 if (nCellsToRefine > 0)
1121 // Refine/update mesh and map fields
1122 autoPtr<mapPolyMesh> map = refine(cellsToRefine);
1124 // Update refineCell. Note that some of the marked ones have
1125 // not been refined due to constraints.
1127 const labelList& cellMap = map().cellMap();
1128 const labelList& reverseCellMap = map().reverseCellMap();
1130 PackedBoolList newRefineCell(cellMap.size());
1132 forAll(cellMap, cellI)
1134 label oldCellI = cellMap[cellI];
1138 newRefineCell.set(cellI, 1);
1140 else if (reverseCellMap[oldCellI] != cellI)
1142 newRefineCell.set(cellI, 1);
1146 newRefineCell.set(cellI, refineCell.get(oldCellI));
1149 refineCell.transfer(newRefineCell);
1152 // Extend with a buffer layer to prevent neighbouring points
1154 for (label i = 0; i < nBufferLayers; i++)
1156 extendMarkedCells(refineCell);
1165 // Select unrefineable points that are not marked in refineCell
1166 labelList pointsToUnrefine
1168 selectUnrefinePoints
1176 label nSplitPoints = returnReduce
1178 pointsToUnrefine.size(),
1182 if (nSplitPoints > 0)
1184 // Refine/update mesh
1185 unrefine(pointsToUnrefine);
1192 if ((nRefinementIterations_ % 10) == 0)
1194 // Compact refinement history occassionally (how often?).
1195 // Unrefinement causes holes in the refinementHistory.
1196 const_cast<refinementHistory&>(meshCutter().history()).compact();
1198 nRefinementIterations_++;
1201 changing(hasChanged);
1207 bool dynamicRefineFvMesh::writeObject
1209 IOstream::streamFormat fmt,
1210 IOstream::versionNumber ver,
1211 IOstream::compressionType cmp
1214 // Force refinement data to go to the current time directory.
1215 const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
1218 dynamicFvMesh::writeObjects(fmt, ver, cmp)
1219 && meshCutter_.write();
1223 volScalarField scalarCellLevel
1231 IOobject::AUTO_WRITE,
1235 dimensionedScalar("level", dimless, 0)
1238 const labelList& cellLevel = meshCutter_.cellLevel();
1240 forAll(cellLevel, cellI)
1242 scalarCellLevel[cellI] = cellLevel[cellI];
1245 writeOk = writeOk && scalarCellLevel.write();
1252 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1254 } // End namespace Foam
1256 // ************************************************************************* //