00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "dynamicRefineFvMesh.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <finiteVolume/volFields.H>
00029 #include <dynamicMesh/polyTopoChange.H>
00030 #include <finiteVolume/surfaceFields.H>
00031 #include <finiteVolume/fvCFD.H>
00032 #include <OpenFOAM/syncTools.H>
00033 #include <OpenFOAM/pointFields.H>
00034
00035
00036
00037 namespace Foam
00038 {
00039
00040
00041
00042 defineTypeNameAndDebug(dynamicRefineFvMesh, 0);
00043
00044 addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject);
00045
00046
00047
00048
00049 label dynamicRefineFvMesh::count
00050 (
00051 const PackedBoolList& l,
00052 const unsigned int val
00053 )
00054 {
00055 label n = 0;
00056 forAll(l, i)
00057 {
00058 if (l.get(i) == val)
00059 {
00060 n++;
00061 }
00062 }
00063 return n;
00064 }
00065
00066
00067 void dynamicRefineFvMesh::calculateProtectedCells
00068 (
00069 PackedBoolList& unrefineableCell
00070 ) const
00071 {
00072 if (protectedCell_.empty())
00073 {
00074 unrefineableCell.clear();
00075 return;
00076 }
00077
00078 const labelList& cellLevel = meshCutter_.cellLevel();
00079
00080 unrefineableCell = protectedCell_;
00081
00082
00083 labelList neiLevel(nFaces()-nInternalFaces());
00084
00085 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00086 {
00087 neiLevel[faceI-nInternalFaces()] = cellLevel[faceOwner()[faceI]];
00088 }
00089 syncTools::swapBoundaryFaceList(*this, neiLevel, false);
00090
00091
00092 while (true)
00093 {
00094
00095 boolList seedFace(nFaces(), false);
00096
00097 forAll(faceNeighbour(), faceI)
00098 {
00099 label own = faceOwner()[faceI];
00100 bool ownProtected = (unrefineableCell.get(own) == 1);
00101 label nei = faceNeighbour()[faceI];
00102 bool neiProtected = (unrefineableCell.get(nei) == 1);
00103
00104 if (ownProtected && (cellLevel[nei] > cellLevel[own]))
00105 {
00106 seedFace[faceI] = true;
00107 }
00108 else if (neiProtected && (cellLevel[own] > cellLevel[nei]))
00109 {
00110 seedFace[faceI] = true;
00111 }
00112 }
00113 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00114 {
00115 label own = faceOwner()[faceI];
00116 bool ownProtected = (unrefineableCell.get(own) == 1);
00117 if
00118 (
00119 ownProtected
00120 && (neiLevel[faceI-nInternalFaces()] > cellLevel[own])
00121 )
00122 {
00123 seedFace[faceI] = true;
00124 }
00125 }
00126
00127 syncTools::syncFaceList(*this, seedFace, orEqOp<bool>(), false);
00128
00129
00130
00131 bool hasExtended = false;
00132
00133 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00134 {
00135 if (seedFace[faceI])
00136 {
00137 label own = faceOwner()[faceI];
00138 if (unrefineableCell.get(own) == 0)
00139 {
00140 unrefineableCell.set(own, 1);
00141 hasExtended = true;
00142 }
00143
00144 label nei = faceNeighbour()[faceI];
00145 if (unrefineableCell.get(nei) == 0)
00146 {
00147 unrefineableCell.set(nei, 1);
00148 hasExtended = true;
00149 }
00150 }
00151 }
00152 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00153 {
00154 if (seedFace[faceI])
00155 {
00156 label own = faceOwner()[faceI];
00157 if (unrefineableCell.get(own) == 0)
00158 {
00159 unrefineableCell.set(own, 1);
00160 hasExtended = true;
00161 }
00162 }
00163 }
00164
00165 if (!returnReduce(hasExtended, orOp<bool>()))
00166 {
00167 break;
00168 }
00169 }
00170 }
00171
00172
00173 void dynamicRefineFvMesh::readDict()
00174 {
00175 dictionary refineDict
00176 (
00177 IOdictionary
00178 (
00179 IOobject
00180 (
00181 "dynamicMeshDict",
00182 time().constant(),
00183 *this,
00184 IOobject::MUST_READ,
00185 IOobject::NO_WRITE,
00186 false
00187 )
00188 ).subDict(typeName + "Coeffs")
00189 );
00190
00191 correctFluxes_ = List<Pair<word> >(refineDict.lookup("correctFluxes"));
00192
00193 dumpLevel_ = Switch(refineDict.lookup("dumpLevel"));
00194 }
00195
00196
00197
00198 autoPtr<mapPolyMesh> dynamicRefineFvMesh::refine
00199 (
00200 const labelList& cellsToRefine
00201 )
00202 {
00203
00204 polyTopoChange meshMod(*this);
00205
00206
00207 meshCutter_.setRefinement(cellsToRefine, meshMod);
00208
00209
00210
00211 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
00212
00213 Info<< "Refined from "
00214 << returnReduce(map().nOldCells(), sumOp<label>())
00215 << " to " << globalData().nTotalCells() << " cells." << endl;
00216
00217 if (debug)
00218 {
00219
00220 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00221 {
00222 label oldFaceI = map().faceMap()[faceI];
00223
00224 if (oldFaceI >= nInternalFaces())
00225 {
00226 FatalErrorIn("dynamicRefineFvMesh::refine(const labelList&)")
00227 << "New internal face:" << faceI
00228 << " fc:" << faceCentres()[faceI]
00229 << " originates from boundary oldFace:" << oldFaceI
00230 << abort(FatalError);
00231 }
00232 }
00233 }
00234
00235
00236
00237 updateMesh(map);
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 {
00256 const labelList& faceMap = map().faceMap();
00257 const labelList& reverseFaceMap = map().reverseFaceMap();
00258
00259
00260
00261
00262 labelHashSet masterFaces(4*cellsToRefine.size());
00263
00264 forAll(faceMap, faceI)
00265 {
00266 label oldFaceI = faceMap[faceI];
00267
00268 if (oldFaceI >= 0)
00269 {
00270 label masterFaceI = reverseFaceMap[oldFaceI];
00271
00272 if (masterFaceI < 0)
00273 {
00274 FatalErrorIn
00275 (
00276 "dynamicRefineFvMesh::refine(const labelList&)"
00277 ) << "Problem: should not have removed faces"
00278 << " when refining."
00279 << nl << "face:" << faceI << abort(FatalError);
00280 }
00281 else if (masterFaceI != faceI)
00282 {
00283 masterFaces.insert(masterFaceI);
00284 }
00285 }
00286 }
00287 if (debug)
00288 {
00289 Info<< "Found " << returnReduce(masterFaces.size(), sumOp<label>())
00290 << " split faces " << endl;
00291 }
00292
00293 forAll(correctFluxes_, i)
00294 {
00295 if (debug)
00296 {
00297 Info<< "Mapping flux " << correctFluxes_[i][0]
00298 << " using interpolated flux " << correctFluxes_[i][1]
00299 << endl;
00300 }
00301 surfaceScalarField& phi = const_cast<surfaceScalarField&>
00302 (
00303 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
00304 );
00305 surfaceScalarField phiU =
00306 fvc::interpolate
00307 (
00308 lookupObject<volVectorField>(correctFluxes_[i][1])
00309 )
00310 & Sf();
00311
00312
00313 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00314 {
00315 label oldFaceI = faceMap[faceI];
00316
00317 if (oldFaceI == -1)
00318 {
00319
00320 phi[faceI] = phiU[faceI];
00321 }
00322 else if (reverseFaceMap[oldFaceI] != faceI)
00323 {
00324
00325 phi[faceI] = phiU[faceI];
00326 }
00327 }
00328
00329
00330 forAll(phi.boundaryField(), patchI)
00331 {
00332 fvsPatchScalarField& patchPhi = phi.boundaryField()[patchI];
00333 const fvsPatchScalarField& patchPhiU =
00334 phiU.boundaryField()[patchI];
00335
00336 label faceI = patchPhi.patch().patch().start();
00337
00338 forAll(patchPhi, i)
00339 {
00340 label oldFaceI = faceMap[faceI];
00341
00342 if (oldFaceI == -1)
00343 {
00344
00345 patchPhi[i] = patchPhiU[i];
00346 }
00347 else if (reverseFaceMap[oldFaceI] != faceI)
00348 {
00349
00350 patchPhi[i] = patchPhiU[i];
00351 }
00352
00353 faceI++;
00354 }
00355 }
00356
00357
00358 forAllConstIter(labelHashSet, masterFaces, iter)
00359 {
00360 label faceI = iter.key();
00361
00362 if (isInternalFace(faceI))
00363 {
00364 phi[faceI] = phiU[faceI];
00365 }
00366 else
00367 {
00368 label patchI = boundaryMesh().whichPatch(faceI);
00369 label i = faceI - boundaryMesh()[patchI].start();
00370
00371 const fvsPatchScalarField& patchPhiU =
00372 phiU.boundaryField()[patchI];
00373
00374 fvsPatchScalarField& patchPhi =
00375 phi.boundaryField()[patchI];
00376
00377 patchPhi[i] = patchPhiU[i];
00378 }
00379 }
00380 }
00381 }
00382
00383
00384
00385
00386 meshCutter_.updateMesh(map);
00387
00388
00389 if (protectedCell_.size())
00390 {
00391 PackedBoolList newProtectedCell(nCells());
00392
00393 forAll(newProtectedCell, cellI)
00394 {
00395 label oldCellI = map().cellMap()[cellI];
00396 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
00397 }
00398 protectedCell_.transfer(newProtectedCell);
00399 }
00400
00401
00402 meshCutter_.checkRefinementLevels(-1, labelList(0));
00403
00404 return map;
00405 }
00406
00407
00408
00409
00410 autoPtr<mapPolyMesh> dynamicRefineFvMesh::unrefine
00411 (
00412 const labelList& splitPoints
00413 )
00414 {
00415 polyTopoChange meshMod(*this);
00416
00417
00418 meshCutter_.setUnrefinement(splitPoints, meshMod);
00419
00420
00421
00422
00423
00424
00425
00426
00427 Map<label> faceToSplitPoint(3*splitPoints.size());
00428
00429 {
00430 forAll(splitPoints, i)
00431 {
00432 label pointI = splitPoints[i];
00433
00434 const labelList& pEdges = pointEdges()[pointI];
00435
00436 forAll(pEdges, j)
00437 {
00438 label otherPointI = edges()[pEdges[j]].otherVertex(pointI);
00439
00440 const labelList& pFaces = pointFaces()[otherPointI];
00441
00442 forAll(pFaces, pFaceI)
00443 {
00444 faceToSplitPoint.insert(pFaces[pFaceI], otherPointI);
00445 }
00446 }
00447 }
00448 }
00449
00450
00451
00452
00453 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
00454
00455 Info<< "Unrefined from "
00456 << returnReduce(map().nOldCells(), sumOp<label>())
00457 << " to " << globalData().nTotalCells() << " cells."
00458 << endl;
00459
00460
00461 updateMesh(map);
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 {
00480 const labelList& reversePointMap = map().reversePointMap();
00481 const labelList& reverseFaceMap = map().reverseFaceMap();
00482
00483 forAll(correctFluxes_, i)
00484 {
00485 if (debug)
00486 {
00487 Info<< "Mapping flux " << correctFluxes_[i][0]
00488 << " using interpolated flux " << correctFluxes_[i][1]
00489 << endl;
00490 }
00491 surfaceScalarField& phi = const_cast<surfaceScalarField&>
00492 (
00493 lookupObject<surfaceScalarField>(correctFluxes_[i][0])
00494 );
00495 surfaceScalarField phiU =
00496 fvc::interpolate
00497 (
00498 lookupObject<volVectorField>(correctFluxes_[i][1])
00499 )
00500 & Sf();
00501
00502 forAllConstIter(Map<label>, faceToSplitPoint, iter)
00503 {
00504 label oldFaceI = iter.key();
00505 label oldPointI = iter();
00506
00507 if (reversePointMap[oldPointI] < 0)
00508 {
00509
00510 label faceI = reverseFaceMap[oldFaceI];
00511
00512 if (faceI >= 0)
00513 {
00514 if (isInternalFace(faceI))
00515 {
00516 phi[faceI] = phiU[faceI];
00517 }
00518 else
00519 {
00520 label patchI = boundaryMesh().whichPatch(faceI);
00521 label i = faceI - boundaryMesh()[patchI].start();
00522
00523 const fvsPatchScalarField& patchPhiU =
00524 phiU.boundaryField()[patchI];
00525
00526 fvsPatchScalarField& patchPhi =
00527 phi.boundaryField()[patchI];
00528
00529 patchPhi[i] = patchPhiU[i];
00530 }
00531 }
00532 }
00533 }
00534 }
00535 }
00536
00537
00538
00539 meshCutter_.updateMesh(map);
00540
00541
00542 if (protectedCell_.size())
00543 {
00544 PackedBoolList newProtectedCell(nCells());
00545
00546 forAll(newProtectedCell, cellI)
00547 {
00548 label oldCellI = map().cellMap()[cellI];
00549 if (oldCellI >= 0)
00550 {
00551 newProtectedCell.set(cellI, protectedCell_.get(oldCellI));
00552 }
00553 }
00554 protectedCell_.transfer(newProtectedCell);
00555 }
00556
00557
00558 meshCutter_.checkRefinementLevels(-1, labelList(0));
00559
00560 return map;
00561 }
00562
00563
00564
00565 scalarField dynamicRefineFvMesh::maxPointField(const scalarField& pFld) const
00566 {
00567 scalarField vFld(nCells(), -GREAT);
00568
00569 forAll(pointCells(), pointI)
00570 {
00571 const labelList& pCells = pointCells()[pointI];
00572
00573 forAll(pCells, i)
00574 {
00575 vFld[pCells[i]] = max(vFld[pCells[i]], pFld[pointI]);
00576 }
00577 }
00578 return vFld;
00579 }
00580
00581
00582
00583 scalarField dynamicRefineFvMesh::minCellField(const volScalarField& vFld) const
00584 {
00585 scalarField pFld(nPoints(), GREAT);
00586
00587 forAll(pointCells(), pointI)
00588 {
00589 const labelList& pCells = pointCells()[pointI];
00590
00591 forAll(pCells, i)
00592 {
00593 pFld[pointI] = min(pFld[pointI], vFld[pCells[i]]);
00594 }
00595 }
00596 return pFld;
00597 }
00598
00599
00600
00601 scalarField dynamicRefineFvMesh::cellToPoint(const scalarField& vFld) const
00602 {
00603 scalarField pFld(nPoints());
00604
00605 forAll(pointCells(), pointI)
00606 {
00607 const labelList& pCells = pointCells()[pointI];
00608
00609 scalar sum = 0.0;
00610 forAll(pCells, i)
00611 {
00612 sum += vFld[pCells[i]];
00613 }
00614 pFld[pointI] = sum/pCells.size();
00615 }
00616 return pFld;
00617 }
00618
00619
00620
00621 scalarField dynamicRefineFvMesh::error
00622 (
00623 const scalarField& fld,
00624 const scalar minLevel,
00625 const scalar maxLevel
00626 ) const
00627 {
00628 scalarField c(fld.size(), -1);
00629
00630 forAll(fld, i)
00631 {
00632 scalar err = min(fld[i]-minLevel, maxLevel-fld[i]);
00633
00634 if (err >= 0)
00635 {
00636 c[i] = err;
00637 }
00638 }
00639 return c;
00640 }
00641
00642
00643 void dynamicRefineFvMesh::selectRefineCandidates
00644 (
00645 const scalar lowerRefineLevel,
00646 const scalar upperRefineLevel,
00647 const scalarField& vFld,
00648 PackedBoolList& candidateCell
00649 ) const
00650 {
00651
00652
00653 scalarField cellError
00654 (
00655 maxPointField
00656 (
00657 error
00658 (
00659 cellToPoint(vFld),
00660 lowerRefineLevel,
00661 upperRefineLevel
00662 )
00663 )
00664 );
00665
00666
00667 forAll(cellError, cellI)
00668 {
00669 if (cellError[cellI] > 0)
00670 {
00671 candidateCell.set(cellI, 1);
00672 }
00673 }
00674 }
00675
00676
00677 labelList dynamicRefineFvMesh::selectRefineCells
00678 (
00679 const label maxCells,
00680 const label maxRefinement,
00681 const PackedBoolList& candidateCell
00682 ) const
00683 {
00684
00685 label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
00686
00687 const labelList& cellLevel = meshCutter_.cellLevel();
00688
00689
00690
00691 PackedBoolList unrefineableCell;
00692 calculateProtectedCells(unrefineableCell);
00693
00694
00695 label nCandidates = returnReduce(count(candidateCell, 1), sumOp<label>());
00696
00697
00698 DynamicList<label> candidates(nCells());
00699
00700 if (nCandidates < nTotToRefine)
00701 {
00702 forAll(candidateCell, cellI)
00703 {
00704 if
00705 (
00706 cellLevel[cellI] < maxRefinement
00707 && candidateCell.get(cellI) == 1
00708 && (
00709 unrefineableCell.empty()
00710 || unrefineableCell.get(cellI) == 0
00711 )
00712 )
00713 {
00714 candidates.append(cellI);
00715 }
00716 }
00717 }
00718 else
00719 {
00720
00721 for (label level = 0; level < maxRefinement; level++)
00722 {
00723 forAll(candidateCell, cellI)
00724 {
00725 if
00726 (
00727 cellLevel[cellI] == level
00728 && candidateCell.get(cellI) == 1
00729 && (
00730 unrefineableCell.empty()
00731 || unrefineableCell.get(cellI) == 0
00732 )
00733 )
00734 {
00735 candidates.append(cellI);
00736 }
00737 }
00738
00739 if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
00740 {
00741 break;
00742 }
00743 }
00744 }
00745
00746
00747 labelList consistentSet
00748 (
00749 meshCutter_.consistentRefinement
00750 (
00751 candidates.shrink(),
00752 true
00753 )
00754 );
00755
00756 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
00757 << " cells for refinement out of " << globalData().nTotalCells()
00758 << "." << endl;
00759
00760 return consistentSet;
00761 }
00762
00763
00764 labelList dynamicRefineFvMesh::selectUnrefinePoints
00765 (
00766 const scalar unrefineLevel,
00767 const PackedBoolList& markedCell,
00768 const scalarField& pFld
00769 ) const
00770 {
00771
00772 const labelList splitPoints(meshCutter_.getSplitPoints());
00773
00774 DynamicList<label> newSplitPoints(splitPoints.size());
00775
00776 forAll(splitPoints, i)
00777 {
00778 label pointI = splitPoints[i];
00779
00780 if (pFld[pointI] < unrefineLevel)
00781 {
00782
00783 const labelList& pCells = pointCells()[pointI];
00784
00785 bool hasMarked = false;
00786
00787 forAll(pCells, pCellI)
00788 {
00789 if (markedCell.get(pCells[pCellI]) == 1)
00790 {
00791 hasMarked = true;
00792 break;
00793 }
00794 }
00795
00796 if (!hasMarked)
00797 {
00798 newSplitPoints.append(pointI);
00799 }
00800 }
00801 }
00802
00803
00804 newSplitPoints.shrink();
00805
00806
00807 labelList consistentSet
00808 (
00809 meshCutter_.consistentUnrefinement
00810 (
00811 newSplitPoints,
00812 false
00813 )
00814 );
00815 Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
00816 << " split points out of a possible "
00817 << returnReduce(splitPoints.size(), sumOp<label>())
00818 << "." << endl;
00819
00820 return consistentSet;
00821 }
00822
00823
00824 void dynamicRefineFvMesh::extendMarkedCells(PackedBoolList& markedCell) const
00825 {
00826
00827 boolList markedFace(nFaces(), false);
00828
00829 forAll(markedCell, cellI)
00830 {
00831 if (markedCell.get(cellI) == 1)
00832 {
00833 const cell& cFaces = cells()[cellI];
00834
00835 forAll(cFaces, i)
00836 {
00837 markedFace[cFaces[i]] = true;
00838 }
00839 }
00840 }
00841
00842 syncTools::syncFaceList(*this, markedFace, orEqOp<bool>(), false);
00843
00844
00845 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00846 {
00847 if (markedFace[faceI])
00848 {
00849 markedCell.set(faceOwner()[faceI], 1);
00850 markedCell.set(faceNeighbour()[faceI], 1);
00851 }
00852 }
00853 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00854 {
00855 if (markedFace[faceI])
00856 {
00857 markedCell.set(faceOwner()[faceI], 1);
00858 }
00859 }
00860 }
00861
00862
00863
00864
00865 dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
00866 :
00867 dynamicFvMesh(io),
00868 meshCutter_(*this),
00869 dumpLevel_(false),
00870 nRefinementIterations_(0),
00871 protectedCell_(nCells(), 0)
00872 {
00873
00874 readDict();
00875
00876
00877 const labelList& cellLevel = meshCutter_.cellLevel();
00878 const labelList& pointLevel = meshCutter_.pointLevel();
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 label nProtected = 0;
00889
00890 forAll(cellLevel, cellI)
00891 {
00892 const labelList& cPoints = cellPoints(cellI);
00893
00894 label nAnchors = 0;
00895 forAll(cPoints, cPointI)
00896 {
00897 label pointI = cPoints[cPointI];
00898 if (pointLevel[pointI] <= cellLevel[cellI])
00899 {
00900 nAnchors++;
00901 }
00902 }
00903 if (nAnchors != 8)
00904 {
00905 protectedCell_.set(cellI, 1);
00906 nProtected++;
00907 }
00908 }
00909
00910
00911
00912
00913
00914
00915
00916 {
00917 labelList neiLevel(nFaces());
00918
00919 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00920 {
00921 neiLevel[faceI] = cellLevel[faceNeighbour()[faceI]];
00922 }
00923 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00924 {
00925 neiLevel[faceI] = cellLevel[faceOwner()[faceI]];
00926 }
00927 syncTools::swapFaceList(*this, neiLevel, false);
00928
00929
00930 boolList protectedFace(nFaces(), false);
00931
00932 forAll(faceOwner(), faceI)
00933 {
00934 label faceLevel = max
00935 (
00936 cellLevel[faceOwner()[faceI]],
00937 neiLevel[faceI]
00938 );
00939
00940 const face& f = faces()[faceI];
00941
00942 label nAnchors = 0;
00943
00944 forAll(f, fp)
00945 {
00946 if (pointLevel[f[fp]] <= faceLevel)
00947 {
00948 nAnchors++;
00949 }
00950 }
00951
00952 if (nAnchors != 4)
00953 {
00954 protectedFace[faceI] = true;
00955 }
00956 }
00957
00958 syncTools::syncFaceList
00959 (
00960 *this,
00961 protectedFace,
00962 orEqOp<bool>(),
00963 false
00964 );
00965
00966 for (label faceI = 0; faceI < nInternalFaces(); faceI++)
00967 {
00968 if (protectedFace[faceI])
00969 {
00970 if (protectedCell_.set(faceOwner()[faceI], 1))
00971 {
00972 nProtected++;
00973 }
00974 if (protectedCell_.set(faceNeighbour()[faceI], 1))
00975 {
00976 nProtected++;
00977 }
00978 }
00979 }
00980 for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++)
00981 {
00982 if (protectedFace[faceI])
00983 {
00984 if (protectedCell_.set(faceOwner()[faceI], 1))
00985 {
00986 nProtected++;
00987 }
00988 }
00989 }
00990 }
00991
00992 reduce(nProtected, sumOp<label>());
00993
00994
00995
00996
00997
00998
00999
01000 if (nProtected == 0)
01001 {
01002 protectedCell_.clear();
01003 }
01004 }
01005
01006
01007
01008
01009 dynamicRefineFvMesh::~dynamicRefineFvMesh()
01010 {}
01011
01012
01013
01014
01015 bool dynamicRefineFvMesh::update()
01016 {
01017
01018
01019
01020 dictionary refineDict
01021 (
01022 IOdictionary
01023 (
01024 IOobject
01025 (
01026 "dynamicMeshDict",
01027 time().constant(),
01028 *this,
01029 IOobject::MUST_READ,
01030 IOobject::NO_WRITE,
01031 false
01032 )
01033 ).subDict(typeName + "Coeffs")
01034 );
01035
01036 label refineInterval = readLabel(refineDict.lookup("refineInterval"));
01037
01038 bool hasChanged = false;
01039
01040 if (refineInterval == 0)
01041 {
01042 changing(hasChanged);
01043
01044 return false;
01045 }
01046 else if (refineInterval < 0)
01047 {
01048 FatalErrorIn("dynamicRefineFvMesh::update()")
01049 << "Illegal refineInterval " << refineInterval << nl
01050 << "The refineInterval setting in the dynamicMeshDict should"
01051 << " be >= 1." << nl
01052 << exit(FatalError);
01053 }
01054
01055
01056
01057
01058
01059
01060
01061 if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
01062 {
01063 label maxCells = readLabel(refineDict.lookup("maxCells"));
01064
01065 if (maxCells <= 0)
01066 {
01067 FatalErrorIn("dynamicRefineFvMesh::update()")
01068 << "Illegal maximum number of cells " << maxCells << nl
01069 << "The maxCells setting in the dynamicMeshDict should"
01070 << " be > 0." << nl
01071 << exit(FatalError);
01072 }
01073
01074 label maxRefinement = readLabel(refineDict.lookup("maxRefinement"));
01075
01076 if (maxRefinement <= 0)
01077 {
01078 FatalErrorIn("dynamicRefineFvMesh::update()")
01079 << "Illegal maximum refinement level " << maxRefinement << nl
01080 << "The maxCells setting in the dynamicMeshDict should"
01081 << " be > 0." << nl
01082 << exit(FatalError);
01083 }
01084
01085 word field(refineDict.lookup("field"));
01086
01087 const volScalarField& vFld = lookupObject<volScalarField>(field);
01088
01089 const scalar lowerRefineLevel =
01090 readScalar(refineDict.lookup("lowerRefineLevel"));
01091 const scalar upperRefineLevel =
01092 readScalar(refineDict.lookup("upperRefineLevel"));
01093 const scalar unrefineLevel =
01094 readScalar(refineDict.lookup("unrefineLevel"));
01095 const label nBufferLayers =
01096 readLabel(refineDict.lookup("nBufferLayers"));
01097
01098
01099 PackedBoolList refineCell(nCells());
01100
01101 if (globalData().nTotalCells() < maxCells)
01102 {
01103
01104 selectRefineCandidates
01105 (
01106 lowerRefineLevel,
01107 upperRefineLevel,
01108 vFld,
01109 refineCell
01110 );
01111
01112
01113
01114 labelList cellsToRefine
01115 (
01116 selectRefineCells
01117 (
01118 maxCells,
01119 maxRefinement,
01120 refineCell
01121 )
01122 );
01123
01124 label nCellsToRefine = returnReduce
01125 (
01126 cellsToRefine.size(), sumOp<label>()
01127 );
01128
01129 if (nCellsToRefine > 0)
01130 {
01131
01132 autoPtr<mapPolyMesh> map = refine(cellsToRefine);
01133
01134
01135
01136 {
01137 const labelList& cellMap = map().cellMap();
01138 const labelList& reverseCellMap = map().reverseCellMap();
01139
01140 PackedBoolList newRefineCell(cellMap.size());
01141
01142 forAll(cellMap, cellI)
01143 {
01144 label oldCellI = cellMap[cellI];
01145
01146 if (oldCellI < 0)
01147 {
01148 newRefineCell.set(cellI, 1);
01149 }
01150 else if (reverseCellMap[oldCellI] != cellI)
01151 {
01152 newRefineCell.set(cellI, 1);
01153 }
01154 else
01155 {
01156 newRefineCell.set(cellI, refineCell.get(oldCellI));
01157 }
01158 }
01159 refineCell.transfer(newRefineCell);
01160 }
01161
01162
01163
01164 for (label i = 0; i < nBufferLayers; i++)
01165 {
01166 extendMarkedCells(refineCell);
01167 }
01168
01169 hasChanged = true;
01170 }
01171 }
01172
01173
01174 {
01175
01176 labelList pointsToUnrefine
01177 (
01178 selectUnrefinePoints
01179 (
01180 unrefineLevel,
01181 refineCell,
01182 minCellField(vFld)
01183 )
01184 );
01185
01186 label nSplitPoints = returnReduce
01187 (
01188 pointsToUnrefine.size(),
01189 sumOp<label>()
01190 );
01191
01192 if (nSplitPoints > 0)
01193 {
01194
01195 unrefine(pointsToUnrefine);
01196
01197 hasChanged = true;
01198 }
01199 }
01200
01201
01202 if ((nRefinementIterations_ % 10) == 0)
01203 {
01204
01205
01206 const_cast<refinementHistory&>(meshCutter().history()).compact();
01207 }
01208 nRefinementIterations_++;
01209 }
01210
01211 changing(hasChanged);
01212
01213 return hasChanged;
01214 }
01215
01216
01217 bool dynamicRefineFvMesh::writeObject
01218 (
01219 IOstream::streamFormat fmt,
01220 IOstream::versionNumber ver,
01221 IOstream::compressionType cmp
01222 ) const
01223 {
01224
01225 const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
01226
01227 bool writeOk =
01228 dynamicFvMesh::writeObjects(fmt, ver, cmp)
01229 && meshCutter_.write();
01230
01231 if (dumpLevel_)
01232 {
01233 volScalarField scalarCellLevel
01234 (
01235 IOobject
01236 (
01237 "cellLevel",
01238 time().timeName(),
01239 *this,
01240 IOobject::NO_READ,
01241 IOobject::AUTO_WRITE,
01242 false
01243 ),
01244 *this,
01245 dimensionedScalar("level", dimless, 0)
01246 );
01247
01248 const labelList& cellLevel = meshCutter_.cellLevel();
01249
01250 forAll(cellLevel, cellI)
01251 {
01252 scalarCellLevel[cellI] = cellLevel[cellI];
01253 }
01254
01255 writeOk = writeOk && scalarCellLevel.write();
01256 }
01257
01258 return writeOk;
01259 }
01260
01261
01262
01263
01264 }
01265
01266