39 #include <IOdictionary.H> 41 #include <ReadFields.H> 48 #include <mapPolyMesh.H> 49 #include <motionSolver.H> 50 #include <pointFields.H> 51 #include <pointMesh.H> 53 #include <polyTopoChange.H> 55 #include <surfaceFields.H> 56 #include <surfaceInterpolate.H> 57 #include <syncTools.H> 63 : dynamicFvMesh(iomesh),
66 nRefinementIterations_(0),
67 protectedCell_(nCells()) {
74 dictionary refineDict(IOdictionary(
75 IOobject(
"dynamicMeshDict", time().constant(), *
this,
76 IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE,
false)));
78 word subType = word(refineDict.lookup(
"dynamicFvMesh"));
79 if (subType ==
"dynamicMotionSolverFvMesh") {
enableMotion =
true; }
87 const labelList &cellLevel =
meshCutter_.cellLevel();
88 const labelList &pointLevel =
meshCutter_.pointLevel();
98 labelList nAnchors(nCells(), Zero);
100 label nProtected = 0;
102 forAll (pointCells(), pointi) {
103 const labelList &pCells = pointCells()[pointi];
105 for (
const label celli : pCells) {
107 if (pointLevel[pointi] <= cellLevel[celli]) {
110 if (nAnchors[celli] > 8) {
125 labelList neiLevel(nFaces());
127 for (label facei = 0; facei < nInternalFaces(); ++facei) {
128 neiLevel[facei] = cellLevel[faceNeighbour()[facei]];
130 for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
131 neiLevel[facei] = cellLevel[faceOwner()[facei]];
133 syncTools::swapFaceList(*
this, neiLevel);
135 bitSet protectedFace(nFaces());
137 forAll (faceOwner(), facei) {
138 const label faceLevel =
139 max(cellLevel[faceOwner()[facei]], neiLevel[facei]);
141 const face &f = faces()[facei];
145 for (
const label pointi : f) {
146 if (pointLevel[pointi] <= faceLevel) {
150 protectedFace.set(facei);
157 syncTools::syncFaceList(*
this, protectedFace, orEqOp<unsigned int>());
159 for (label facei = 0; facei < nInternalFaces(); ++facei) {
160 if (protectedFace.test(facei)) {
167 for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
168 if (protectedFace.test(facei)) {
175 forAll (cells(), celli) {
176 const cell &cFaces = cells()[celli];
178 if (cFaces.size() < 6) {
182 for (
const label cfacei : cFaces) {
183 if (faces()[cfacei].size() < 4) {
196 const polyBoundaryMesh &patches = boundaryMesh();
197 wordList ptchTypes = patches.types();
199 labelList assignedScore(nCells(), 0);
201 forAll (patches, patchI) {
202 if (ptchTypes[patchI] !=
"empty") {
203 auto allCells = patches[patchI].faceCells();
204 forAll (allCells, cellI) {
205 assignedScore[allCells[cellI]] += 1;
207 auto neiCells = cellCells()[allCells[cellI]];
208 forAll (neiCells, nCellI) { assignedScore[neiCells[nCellI]] += 1; }
213 forAll (assignedScore, scoreI) {
222 cellSet protectedCells(*
this,
"protectedCells",
224 Info <<
"Detected " << returnReduce(protectedCells.size(), sumOp<label>())
225 <<
" cells that are protected from refinement." 226 <<
" Writing these to cellSet " << protectedCells.name() <<
"." 229 protectedCells.write();
237 dictionary refineDict(
238 IOdictionary(IOobject(
"dynamicMeshDict", time().constant(), *
this,
239 IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE,
241 .optionalSubDict(
"dynamicRefineMotionFvMeshCoeffs"));
243 auto fluxVelocities = refineDict.get<List<Pair<word>>>(
"correctFluxes");
247 for (
const auto &pr : fluxVelocities) {
251 refineDict.readEntry(
"dumpLevel",
dumpLevel_);
252 const label refineInterval = refineDict.get<label>(
"refineInterval");
254 bool hasChanged =
false;
256 if (refineInterval == 0) {
257 polyMesh::topoChanging(hasChanged);
259 }
else if (refineInterval < 0) {
260 FatalErrorInFunction <<
"Illegal refineInterval " << refineInterval << nl
261 <<
"The refineInterval value should" 262 <<
" be >= 1." << nl << exit(FatalError);
265 if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0) {
266 label maxCells = refineDict.get<label>(
"maxCells");
268 if (maxCells < 0) maxCells = 500000;
272 <<
"Illegal maximum number of cells " << maxCells << nl
273 <<
"The maxCells setting in the dynamicMeshDict should" 274 <<
" be > 0." << nl << exit(FatalError);
277 const label maxRefinement = refineDict.get<label>(
"maxRefinement");
279 if (maxRefinement <= 0) {
281 <<
"Illegal maximum refinement level " << maxRefinement << nl
282 <<
"The maxCells setting in the dynamicMeshDict should" 283 <<
" be > 0." << nl << exit(FatalError);
286 const word fieldName(refineDict.get<word>(
"field"));
288 const volScalarField &vFld = lookupObject<volScalarField>(fieldName);
290 const scalar lowerRefineLevel = refineDict.get<scalar>(
"lowerRefineLevel");
291 const scalar upperRefineLevel = refineDict.get<scalar>(
"upperRefineLevel");
292 const scalar unrefineBelow =
293 refineDict.getOrDefault<scalar>(
"unrefineLevel", GREAT);
294 const scalar unrefineAbove =
295 refineDict.getOrDefault<scalar>(
"unrefineAbove", 50000);
296 const label nBufferLayers = refineDict.get<label>(
"nBufferLayers");
299 bitSet refineCell(nCells());
305 if (globalData().nTotalCells() < maxCells) {
311 const label nCellsToRefine =
312 returnReduce(cellsToRefine.size(), sumOp<label>());
314 if (nCellsToRefine > 0) {
316 autoPtr<mapPolyMesh> map =
refine(cellsToRefine);
321 const labelList &cellMap = map().cellMap();
322 const labelList &reverseCellMap = map().reverseCellMap();
324 bitSet newRefineCell(cellMap.size());
326 forAll (cellMap, celli) {
327 const label oldCelli = cellMap[celli];
328 if ((oldCelli < 0) || (reverseCellMap[oldCelli] != celli) ||
329 (refineCell.test(oldCelli))) {
330 newRefineCell.set(celli);
333 refineCell.transfer(newRefineCell);
338 for (label i = 0; i < nBufferLayers; ++i) {
349 unrefineAbove, unrefineBelow, refineCell,
maxCellField(vFld)));
351 const label nSplitPoints =
352 returnReduce(pointsToUnrefine.size(), sumOp<label>());
354 if (nSplitPoints > 0) {
365 const_cast<refinementHistory &
>(
meshCutter().history()).compact();
374 topoChanging(hasChanged);
387 volScalarField &vFld,
const double &lowerRefineLevel,
388 const double &upperRefineLevel,
389 const double &unrefineAbove,
390 const double &unrefineBelow,
const int &nBufferLayers,
391 const int &maxCells) {
392 bool hasChanged =
false;
394 if (refineInterval == 0) {
395 polyMesh::topoChanging(hasChanged);
397 }
else if (refineInterval < 0) {
398 FatalErrorInFunction <<
"Illegal refineInterval " << refineInterval << nl
399 <<
"The refineInterval value should" 400 <<
" be >= 1." << nl << exit(FatalError);
403 if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0) {
406 <<
"Illegal maximum number of cells " << maxCells << nl
407 <<
"The maxCells setting in the dynamicMeshDict should" 408 <<
" be > 0." << nl << exit(FatalError);
411 if (maxRefinement <= 0) {
413 <<
"Illegal maximum refinement level " << maxRefinement << nl
414 <<
"The maxCells setting in the dynamicMeshDict should" 415 <<
" be > 0." << nl << exit(FatalError);
419 bitSet refineCell(nCells());
425 if (globalData().nTotalCells() < maxCells) {
431 const label nCellsToRefine =
432 returnReduce(cellsToRefine.size(), sumOp<label>());
434 if (nCellsToRefine > 0) {
436 autoPtr<mapPolyMesh> map =
refine(cellsToRefine);
441 const labelList &cellMap = map().cellMap();
442 const labelList &reverseCellMap = map().reverseCellMap();
444 bitSet newRefineCell(cellMap.size());
446 forAll (cellMap, celli) {
447 const label oldCelli = cellMap[celli];
448 if ((oldCelli < 0) || (reverseCellMap[oldCelli] != celli) ||
449 (refineCell.test(oldCelli))) {
450 newRefineCell.set(celli);
453 refineCell.transfer(newRefineCell);
458 for (label i = 0; i < nBufferLayers; ++i) {
469 unrefineAbove, unrefineBelow, refineCell,
maxCellField(vFld)));
471 const label nSplitPoints =
472 returnReduce(pointsToUnrefine.size(), sumOp<label>());
474 if (nSplitPoints > 0) {
485 const_cast<refinementHistory &
>(
meshCutter().history()).compact();
490 topoChanging(hasChanged);
511 const int &nBufferLayers,
const int &maxCells,
512 volScalarField &vFld) {
513 bool hasChanged =
false;
514 if (refineInterval == 0) {
515 polyMesh::topoChanging(hasChanged);
517 }
else if (refineInterval < 0) {
518 FatalErrorInFunction <<
"Illegal refineInterval " << refineInterval << nl
519 <<
"The refineInterval value should" 520 <<
" be >= 1." << nl << exit(FatalError);
527 if (fvMesh::time().timeIndex() > 0 &&
528 fvMesh::time().timeIndex() % refineInterval == 0) {
530 FatalErrorInFunction <<
"Illegal maximum number of cells " << maxCells
531 << nl <<
"The maxCells value should" 532 <<
" be > 0." << nl << exit(FatalError);
535 if (maxRefinement <= 0) {
536 FatalErrorInFunction <<
"Illegal maximum refinement level " 537 << maxRefinement << nl <<
"The maxCells value should" 538 <<
" be > 0." << nl << exit(FatalError);
542 bitSet refineCell(primitiveMesh::nCells());
549 if (polyMesh::globalData().nTotalCells() < maxCells) {
555 label nCellsToRefine = returnReduce(cellsToRefine.size(), sumOp<label>());
557 if (nCellsToRefine > 0) {
559 autoPtr<mapPolyMesh> map =
refine(cellsToRefine);
563 const labelList &cellMap = map().cellMap();
564 const labelList &reverseCellMap = map().reverseCellMap();
566 bitSet newRefineCell(cellMap.size());
568 forAll (cellMap, celli) {
569 label oldCelli = cellMap[celli];
572 newRefineCell.set(celli, 1);
573 else if (reverseCellMap[oldCelli] != celli)
574 newRefineCell.set(celli, 1);
576 newRefineCell.set(celli, refineCell.get(oldCelli));
578 refineCell.transfer(newRefineCell);
582 for (label i = 0; i < nBufferLayers; i++) {
591 labelList pointsToUnrefine(
594 label nSplitPoints = returnReduce(pointsToUnrefine.size(), sumOp<label>());
595 autoPtr<mapPolyMesh> mapUnrefine;
597 if (nSplitPoints > 0) {
605 const_cast<refinementHistory &
>(
meshCutter().history()).compact();
610 polyMesh::topoChanging(hasChanged);
611 if (hasChanged) { polyMesh::moving(
false); }
617 const scalar unrefineBelow,
618 const bitSet &markedCell,
619 const scalarField &pFld)
const {
621 const labelList splitPoints(
meshCutter_.getSplitPoints());
623 const labelListList &pointCells = this->pointCells();
628 bitSet protectedPoint(nPoints());
632 forAll (pointCells, pointi) {
633 for (
const label celli : pointCells[pointi]) {
635 protectedPoint.set(pointi);
641 syncTools::syncPointList(*
this, protectedPoint, orEqOp<unsigned int>(), 0u);
643 DebugInfo <<
"From " << returnReduce(
protectedCell_.count(), sumOp<label>())
644 <<
" protected cells found " 645 << returnReduce(protectedPoint.count(), sumOp<label>())
646 <<
" protected points." << endl;
649 DynamicList<label> newSplitPoints(splitPoints.size());
651 for (
const label pointi : splitPoints) {
652 if ((!protectedPoint[pointi] && pFld[pointi] < unrefineBelow) ||
653 (!protectedPoint[pointi] && pFld[pointi] > unrefineAbove)) {
655 bool hasMarked =
false;
657 for (
const label celli : pointCells[pointi]) {
658 if (markedCell.test(celli)) {
664 if (!hasMarked) { newSplitPoints.append(pointi); }
668 newSplitPoints.shrink();
671 labelList consistentSet(
672 meshCutter_.consistentUnrefinement(newSplitPoints,
false));
673 Info <<
"Selected " << returnReduce(consistentSet.size(), sumOp<label>())
674 <<
" split points out of a possible " 675 << returnReduce(splitPoints.size(), sumOp<label>()) <<
"." << endl;
677 return consistentSet;
681 scalarField pFld(nPoints());
683 forAll (pointCells(), pointi) {
684 const labelList &pCells = pointCells()[pointi];
688 sum += vFld[pCells[i]];
690 pFld[pointi] = sum / pCells.size();
698 const_cast<hexRef8 &
>(
meshCutter_).setInstance(time().timeName());
710 for (
int i = 0; i < inField.size(); i++) {
711 if (inField[i] < 0) {
713 }
else if (inField[i] > maxNum) {
720 for (
int i = 0; i < inField.size(); i++) inField[i] = inField[i] / maxNum;
724 const std::string &outName) {
725 std::cout <<
" - Parsing Input file ... " << std::endl;
726 std::ifstream inFld(inName);
727 if (inFld.is_open()) {
728 std::string linesOut;
729 std::vector<std::string> myLines;
730 while (std::getline(inFld, linesOut)) myLines.push_back(linesOut);
735 for (
int i = 0; i < (int)myLines.size(); i++)
741 for (
int i = 0; i < returnFld.size(); i++) returnFld[i] =
incomingField[i];
745 std::cerr <<
"Cannot open/find " << inName <<
" file!" << std::endl;
752 for (
int i = 0; i < (int)vec.size(); i++) vFld[i] = vec[i];
757 const std::string &outName) {
758 std::cout <<
" - Parsing Input file ... " << std::endl;
759 std::ifstream inFld(inName);
760 if (inFld.is_open()) {
761 std::string linesOut;
762 std::vector<std::string> myLines;
763 while (std::getline(inFld, linesOut)) myLines.push_back(linesOut);
768 for (
int i = 0; i < (int)myLines.size(); i++) {
775 for (
int i = 0; i < returnFld.size(); i++) returnFld[i] =
incomingField[i];
779 std::cerr <<
"Cannot open/find " << inName <<
" file!" << std::endl;
785 volScalarField meshFieldXY(IOobject(fldName, time().timeName(), *
this,
786 IOobject::NO_READ, IOobject::AUTO_WRITE),
793 const std::string &outName) {
799 volScalarField emptyScalar(IOobject(fldName, time().timeName(), *
this,
800 IOobject::NO_READ, IOobject::AUTO_WRITE),
801 *
this, dimensionedScalar(
"scalar", dimLength, 0));
807 volScalarField emptyScalar(IOobject(fldName, time().timeName(), *
this,
808 IOobject::NO_READ, IOobject::AUTO_WRITE),
809 *
this, dimensionedScalar(
"scalar", dimless, 0));
816 pointMesh pMesh(*
this);
820 pointScalarField initFieldZero(
821 IOobject(fldName, time().timeName(), *
this, IOobject::NO_READ,
822 IOobject::AUTO_WRITE),
823 pMesh, dimensionedScalar(
"scalar", dimLength, 0));
825 return initFieldZero;
835 volVectorField returnGrad(IOobject(
"fldName", time().timeName(), *
this,
836 IOobject::NO_READ, IOobject::NO_WRITE),
837 *
this, dimensionedVector(
"vector", dimless, Zero));
839 returnGrad = Foam::fvc::grad(fldGrd);
842 returnScalar = mag(returnGrad);
849 unrefineableCell.clear();
853 const labelList &cellLevel =
meshCutter_.cellLevel();
858 labelList neiLevel(nFaces() - nInternalFaces());
860 for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
861 neiLevel[facei - nInternalFaces()] = cellLevel[faceOwner()[facei]];
863 syncTools::swapBoundaryFaceList(*
this, neiLevel);
870 seedFace.resize(nFaces());
872 for (label facei = 0; facei < nInternalFaces(); ++facei) {
873 const label own = faceOwner()[facei];
874 const label nei = faceNeighbour()[facei];
878 (unrefineableCell.test(own) && (cellLevel[nei] > cellLevel[own])) ||
880 (unrefineableCell.test(nei) && (cellLevel[own] > cellLevel[nei]))) {
884 for (label facei = nInternalFaces(); facei < nFaces(); facei++) {
885 const label own = faceOwner()[facei];
889 (unrefineableCell.test(own) &&
890 (neiLevel[facei - nInternalFaces()] > cellLevel[own]))) {
895 syncTools::syncFaceList(*
this, seedFace, orEqOp<unsigned int>());
898 bool hasExtended =
false;
900 for (label facei = 0; facei < nInternalFaces(); ++facei) {
901 if (seedFace.test(facei)) {
902 if (unrefineableCell.set(faceOwner()[facei])) { hasExtended =
true; }
903 if (unrefineableCell.set(faceNeighbour()[facei])) {
908 for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
909 if (seedFace.test(facei)) {
910 const label own = faceOwner()[facei];
912 if (unrefineableCell.set(own)) { hasExtended =
true; }
916 if (!returnReduce(hasExtended, orOp<bool>())) {
break; }
921 dictionary refineDict(
922 IOdictionary(IOobject(
"dynamicMeshDict", time().constant(), *
this,
923 IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE,
925 .optionalSubDict(
"dynamicRefineMotionFvMeshCoeffs"));
927 List<Pair<word>> fluxVelocities =
928 List<Pair<word>>(refineDict.lookup(
"correctFluxes"));
931 forAll (fluxVelocities, i)
932 correctFluxes_.insert(fluxVelocities[i][0], fluxVelocities[i][1]);
934 dumpLevel_ = Switch(refineDict.lookup(
"dumpLevel"));
938 dynamicFvMesh::mapFields(mpm);
943 const labelList &faceMap = mpm.faceMap();
944 const labelList &reverseFaceMap = mpm.reverseFaceMap();
951 bitSet masterFaces(nFaces());
953 forAll (faceMap, facei) {
954 const label oldFacei = faceMap[facei];
957 const label masterFacei = reverseFaceMap[oldFacei];
959 if (masterFacei < 0) {
960 FatalErrorInFunction <<
"Problem: should not have removed faces" 961 <<
" when refining." << nl <<
"face:" << facei
963 << abort(FatalError);
964 }
else if (masterFacei != facei) {
965 masterFaces.set(masterFacei);
971 Pout <<
"Found " << masterFaces.count() <<
" split faces " << endl;
974 HashTable<surfaceScalarField *> fluxes(lookupClass<surfaceScalarField>());
975 forAllIters(fluxes, iter) {
978 <<
"Cannot find surfaceScalarField " << iter.key()
979 <<
" in user-provided flux mapping table " <<
correctFluxes_ << endl
980 <<
" The flux mapping table is used to recreate the" 981 <<
" flux on newly created faces." << endl
982 <<
" Either add the entry if it is a flux or use (" << iter.key()
983 <<
" none) to suppress this warning." << endl;
989 if (UName ==
"none") {
continue; }
991 surfaceScalarField &phi = *iter();
993 if (UName ==
"NaN") {
994 Pout <<
"Setting surfaceScalarField " << iter.key() <<
" to NaN" 997 sigFpe::fillNan(phi.primitiveFieldRef());
1003 Pout <<
"Mapping flux " << iter.key() <<
" using interpolated flux " 1007 const surfaceScalarField phiU(
1008 fvc::interpolate(lookupObject<volVectorField>(UName)) & Sf());
1011 for (label facei = 0; facei < nInternalFaces(); ++facei) {
1012 const label oldFacei = faceMap[facei];
1014 if (oldFacei == -1) {
1016 phi[facei] = phiU[facei];
1017 }
else if (reverseFaceMap[oldFacei] != facei) {
1019 phi[facei] = phiU[facei];
1024 surfaceScalarField::Boundary &phiBf = phi.boundaryFieldRef();
1026 forAll (phiBf, patchi) {
1027 fvsPatchScalarField &patchPhi = phiBf[patchi];
1028 const fvsPatchScalarField &patchPhiU = phiU.boundaryField()[patchi];
1030 label facei = patchPhi.patch().start();
1032 forAll (patchPhi, i) {
1033 const label oldFacei = faceMap[facei];
1035 if (oldFacei == -1) {
1037 patchPhi[i] = patchPhiU[i];
1038 }
else if (reverseFaceMap[oldFacei] != facei) {
1040 patchPhi[i] = patchPhiU[i];
1048 for (
const label facei : masterFaces) {
1049 if (isInternalFace(facei)) {
1050 phi[facei] = phiU[facei];
1052 const label patchi = boundaryMesh().whichPatch(facei);
1053 const label i = facei - boundaryMesh()[patchi].start();
1055 const fvsPatchScalarField &patchPhiU = phiU.boundaryField()[patchi];
1057 fvsPatchScalarField &patchPhi = phiBf[patchi];
1059 patchPhi[i] = patchPhiU[i];
1069 const labelList &faceMap = mpm.faceMap();
1071 mapNewInternalFaces<scalar>(this->Sf(), this->magSf(), faceMap);
1072 mapNewInternalFaces<vector>(this->Sf(), this->magSf(), faceMap);
1075 mapNewInternalFaces<sphericalTensor>(faceMap);
1076 mapNewInternalFaces<symmTensor>(faceMap);
1077 mapNewInternalFaces<tensor>(faceMap);
1084 polyTopoChange meshMod(*
this);
1087 meshCutter_.setRefinement(cellsToRefine, meshMod);
1091 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*
this,
false);
1093 Info <<
"Refined from " << returnReduce(map().nOldCells(), sumOp<label>())
1094 <<
" to " << globalData().nTotalCells() <<
" cells." << endl;
1098 for (label facei = 0; facei < nInternalFaces(); ++facei) {
1099 const label oldFacei = map().faceMap()[facei];
1101 if (oldFacei >= nInternalFaces()) {
1102 FatalErrorInFunction <<
"New internal face:" << facei
1103 <<
" fc:" << faceCentres()[facei]
1104 <<
" originates from boundary oldFace:" << oldFacei
1105 << abort(FatalError);
1124 bitSet newProtectedCell(nCells());
1125 forAll (newProtectedCell, celli) {
1126 const label oldCelli = map().cellMap()[celli];
1127 if (
protectedCell_.test(oldCelli)) { newProtectedCell.set(celli); }
1133 meshCutter_.checkRefinementLevels(-1, labelList());
1139 polyTopoChange meshMod(*
this);
1142 meshCutter_.setUnrefinement(splitPoints, meshMod);
1150 Map<label> faceToSplitPoint(3 * splitPoints.size());
1153 for (
const label pointi : splitPoints) {
1154 const labelList &pEdges = pointEdges()[pointi];
1156 for (
const label edgei : pEdges) {
1157 const label otherPointi = edges()[edgei].otherVertex(pointi);
1159 const labelList &pFaces = pointFaces()[otherPointi];
1161 for (
const label facei : pFaces) {
1162 faceToSplitPoint.insert(facei, otherPointi);
1170 autoPtr<mapPolyMesh> map = meshMod.changeMesh(*
this,
false);
1172 Info <<
"Unrefined from " << returnReduce(map().nOldCells(), sumOp<label>())
1173 <<
" to " << globalData().nTotalCells() <<
" cells." << endl;
1186 const labelList &reversePointMap = map().reversePointMap();
1187 const labelList &reverseFaceMap = map().reverseFaceMap();
1189 HashTable<surfaceScalarField *> fluxes(lookupClass<surfaceScalarField>());
1190 forAllIters(fluxes, iter) {
1193 <<
"Cannot find surfaceScalarField " << iter.key()
1194 <<
" in user-provided flux mapping table " <<
correctFluxes_ << endl
1195 <<
" The flux mapping table is used to recreate the" 1196 <<
" flux on newly created faces." << endl
1197 <<
" Either add the entry if it is a flux or use (" << iter.key()
1198 <<
" none) to suppress this warning." << endl;
1204 if (UName ==
"none") {
continue; }
1206 DebugInfo <<
"Mapping flux " << iter.key() <<
" using interpolated flux " 1209 surfaceScalarField &phi = *iter();
1210 surfaceScalarField::Boundary &phiBf = phi.boundaryFieldRef();
1212 const surfaceScalarField phiU(
1213 fvc::interpolate(lookupObject<volVectorField>(UName)) & Sf());
1215 forAllConstIters(faceToSplitPoint, iter2) {
1216 const label oldFacei = iter2.key();
1217 const label oldPointi = iter2.val();
1218 if (reversePointMap[oldPointi] < 0) {
1220 const label facei = reverseFaceMap[oldFacei];
1223 if (isInternalFace(facei)) {
1224 phi[facei] = phiU[facei];
1226 label patchi = boundaryMesh().whichPatch(facei);
1227 label i = facei - boundaryMesh()[patchi].start();
1229 const fvsPatchScalarField &patchPhiU =
1230 phiU.boundaryField()[patchi];
1231 fvsPatchScalarField &patchPhi = phiBf[patchi];
1232 patchPhi[i] = patchPhiU[i];
1245 bitSet newProtectedCell(nCells());
1247 forAll (newProtectedCell, celli) {
1248 const label oldCelli = map().cellMap()[celli];
1249 if (
protectedCell_.test(oldCelli)) { newProtectedCell.set(celli); }
1255 meshCutter_.checkRefinementLevels(-1, labelList());
1261 scalarField vFld(nCells(), -GREAT);
1263 forAll (pointCells(), pointi) {
1264 const labelList &pCells = pointCells()[pointi];
1266 for (
const label celli : pCells) {
1267 vFld[celli] = max(vFld[celli], pFld[pointi]);
1274 scalarField pFld(nPoints(), -GREAT);
1276 forAll (pointCells(), pointi) {
1277 const labelList &pCells = pointCells()[pointi];
1279 for (
const label celli : pCells) {
1280 pFld[pointi] = max(pFld[pointi], vFld[celli]);
1287 scalarField pFld(nPoints());
1289 forAll (pointCells(), pointi) {
1290 const labelList &pCells = pointCells()[pointi];
1293 for (
const label celli : pCells) { sum += vFld[celli]; }
1294 pFld[pointi] = sum / pCells.size();
1300 const scalar maxLevel)
const {
1301 scalarField c(fld.size(), scalar(-1));
1303 scalar err = min(fld[i] - minLevel, maxLevel - fld[i]);
1305 if (err >= 0) { c[i] = err; }
1311 const scalar upperRefineLevel,
1312 const scalarField &vFld,
1313 bitSet &candidateCell)
const {
1320 forAll (cellError, celli) {
1321 if (cellError[celli] > 0) { candidateCell.set(celli); }
1326 const label maxRefinement,
1327 const bitSet &candidateCell)
const {
1329 label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
1331 const labelList &cellLevel =
meshCutter_.cellLevel();
1335 bitSet unrefineableCell;
1339 label nLocalCandidates = candidateCell.count();
1340 label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
1343 DynamicList<label> candidates(nLocalCandidates);
1345 if (nCandidates < nTotToRefine) {
1346 for (
const label celli : candidateCell) {
1347 if ((!unrefineableCell.test(celli)) && cellLevel[celli] < maxRefinement) {
1348 candidates.append(celli);
1353 for (label level = 0; level < maxRefinement; ++level) {
1354 for (
const label celli : candidateCell) {
1355 if ((!unrefineableCell.test(celli)) && cellLevel[celli] == level) {
1356 candidates.append(celli);
1360 if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine) {
1367 labelList consistentSet(
meshCutter_.consistentRefinement(
1368 candidates.shrink(),
1372 Info <<
"Selected " << returnReduce(consistentSet.size(), sumOp<label>())
1373 <<
" cells for refinement out of " << globalData().nTotalCells() <<
"." 1376 return consistentSet;
1381 bitSet markedFace(nFaces());
1383 for (
const label celli : markedCell) {
1384 markedFace.set(cells()[celli]);
1387 syncTools::syncFaceList(*
this, markedFace, orEqOp<unsigned int>());
1390 for (label facei = 0; facei < nInternalFaces(); ++facei) {
1391 if (markedFace.test(facei)) {
1392 markedCell.set(faceOwner()[facei]);
1393 markedCell.set(faceNeighbour()[facei]);
1396 for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
1397 if (markedFace.test(facei)) { markedCell.set(faceOwner()[facei]); }
1402 const labelList &cellLevel =
meshCutter_.cellLevel();
1403 const labelList &pointLevel =
meshCutter_.pointLevel();
1405 labelList nAnchorPoints(nCells(), Zero);
1407 forAll (pointLevel, pointi) {
1408 const labelList &pCells = pointCells(pointi);
1410 for (
const label celli : pCells) {
1411 if (pointLevel[pointi] <= cellLevel[celli]) {
1413 if (nAnchorPoints[celli] == 8) { protectedCell.set(celli); }
1415 if (!protectedCell.test(celli)) { ++nAnchorPoints[celli]; }
1420 forAll (protectedCell, celli) {
1421 if (nAnchorPoints[celli] != 8) { protectedCell.set(celli); }
1427 const_cast<hexRef8 &
>(
meshCutter_).setInstance(time().timeName());
1429 IOstreamOption(time().writeFormat(), time().writeCompression());
1431 (dynamicFvMesh::writeObject(strmOpt,
true) &&
meshCutter_.write(valid));
1434 volScalarField scalarCellLevel(
1435 IOobject(
"cellLevel", time().timeName(), *
this, IOobject::NO_READ,
1436 IOobject::AUTO_WRITE,
false),
1437 *
this, dimensionedScalar(
"level", dimless, 0));
1439 const labelList &cellLevel =
meshCutter_.cellLevel();
1441 forAll (cellLevel, celli) { scalarCellLevel[celli] = cellLevel[celli]; }
1443 writeOk = writeOk && scalarCellLevel.write();
1452 if (foundObject<volVectorField>(
"U")) {
1453 lookupObjectRef<volVectorField>(
"U").correctBoundaryConditions();
1459 const labelList &faceMap,
1460 GeometricField<T, fvsPatchField, surfaceMesh> &sFld) {
1461 using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1464 Field<T> tsFld(this->nFaces(), Zero);
1465 SubField<T>(tsFld, this->nInternalFaces()) = sFld.internalField();
1467 const typename GeoField::Boundary &bFld = sFld.boundaryField();
1468 forAll (bFld, patchi) {
1469 label facei = this->boundaryMesh()[patchi].start();
1470 for (
const T &val : bFld[patchi]) { tsFld[facei++] = val; }
1473 const labelUList &owner = this->faceOwner();
1474 const labelUList &neighbour = this->faceNeighbour();
1475 const cellList &cells = this->cells();
1477 for (label facei = 0; facei < nInternalFaces(); facei++) {
1478 label oldFacei = faceMap[facei];
1482 if (oldFacei == -1) {
1485 T tmpValue(pTraits<T>::zero);
1488 const cell &ownFaces = cells[owner[facei]];
1489 for (
auto ownFacei : ownFaces) {
1490 if (faceMap[ownFacei] != -1) {
1491 tmpValue += tsFld[ownFacei];
1496 const cell &neiFaces = cells[neighbour[facei]];
1497 for (
auto neiFacei : neiFaces) {
1498 if (faceMap[neiFacei] != -1) {
1499 tmpValue += tsFld[neiFacei];
1504 if (counter > 0) { sFld[facei] = tmpValue / counter; }
1511 using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1512 HashTable<GeoField *> sFlds(this->objectRegistry::lookupClass<GeoField>());
1514 forAllIters(sFlds, iter) {
1517 DebugInfo <<
"dynamicRefineMotionFvMesh::mapNewInternalFaces():" 1518 <<
" Mapping new internal faces by interpolation on " 1519 << iter.key() << endl;
1521 GeoField &sFld = *iter();
1523 if (sFld.oriented()()) {
1524 WarningInFunction <<
"Ignoring mapping oriented field " << sFld.name()
1525 <<
" since of type " << sFld.type() << endl;
1535 const surfaceScalarField &magSf,
1536 const labelList &faceMap) {
1537 using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1538 HashTable<GeoField *> sFlds(this->objectRegistry::lookupClass<GeoField>());
1540 forAllIters(sFlds, iter) {
1543 DebugInfo <<
"dynamicRefineMotionFvMesh::mapNewInternalFaces():" 1544 <<
" Mapping new internal faces by interpolation on " 1545 << iter.key() << endl;
1547 GeoField &sFld = *iter();
1549 if (sFld.oriented()()) {
1550 DebugInfo <<
"dynamicRefineMotionFvMesh::mapNewInternalFaces(): " 1551 <<
"Converting oriented field " << iter.key()
1552 <<
" to intensive field and mapping" << endl;
1557 using NormalGeoField =
1558 GeometricField<typename outerProduct<vector, T>::type,
1559 fvsPatchField, surfaceMesh>;
1562 NormalGeoField fFld(sFld * Sf / Foam::sqr(magSf));
virtual Foam::autoPtr< Foam::mapPolyMesh > unrefine(const labelList &)
Refines selected cells in a mesh.
pointScalarField initPntSField(const std::string &fldName)
Creates an empty pointScalarField based on current mesh.
std::vector< double > incomingField
Vector to store user defined vector.
scalarField error(const scalarField &fld, const scalar minLevel, const scalar maxLevel) const
void enableMeshWriting()
Access to mesh data.
virtual labelList selectUnrefinePoints(const scalar unrefineAbove, const scalar unrefineBelow, const bitSet &markedCell, const scalarField &pFld) const
Marked the cells to unrefine based on user defined levels.
void enableUpdatedField()
Access to updated field at every time step.
bool enableMotion
Boolean to check if mesh motion is needed.
bool writeObjectAMR(const bool valid) const
void calculateProtectedCells(bitSet &unrefineableCell) const
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
void checkForMotion()
Checks for availability of mesh motion keywords in dictionary.
Foam::scalarField cell2Pt(const scalarField &vFld)
Converts volume field to point field.
void solveMotion()
A mesh motion solver.
volScalarField getGradient(const volScalarField &fldGrd)
Returns a gradient of scalar field over mesh param fldGrd Scalar Field for Gradient Calculation...
std::shared_ptr< char > strToChar(const std::string &strng)
void mapNewInternalFaces(const labelList &faceMap, GeometricField< T, fvsPatchField, surfaceMesh > &)
label nRefinementIterations_
volScalarField assignToVolScalarField(const std::vector< int > &vec)
Converts vector to volScalarField for refinement/unrefinement.
void calcProtectedCells()
Calculates and stores non-hex cells in protected cells catagory to avoid their refinement.
const hexRef8 & meshCutter() const
virtual void mapFields(const mapPolyMesh &mpm)
void writeHistory()
Writes refinement history in current time directory.
AMRFoam(const Foam::IOobject &iomesh)
Standard constructor.
HashTable< word > correctFluxes_
bool updateAMR(const int &refineInterval, const int &maxRefinement, volScalarField &vFld, const double &lowerRefineLevel, const double &upperRefineLevel, const double &unrefineAbove, const double &unrefineBelow, const int &nBufferLayers, const int &maxCells)
updateAMR is a master method for this process.
bool writeRefHistory
Boolean to enable writing of refinement history.
volScalarField initScalarField(const std::string &fldName)
Creates an empty volScalarField based on current mesh.
volScalarField initGradientField(const std::string &fldName)
Creates an empty volScalarField for gradient magnitude.
const polyMesh & getMesh()
Access to current mesh at every time step.
void enableRefHistoryData()
Access to refinement history data.
scalarField maxCellField(const volScalarField &) const
const bitSet & protectedCell() const
bool updateAMRML(const int &refineInterval, const int &maxRefinement, const int &nBufferLayers, const int &maxCells, volScalarField &vFld)
New method for machine learning ML.
void transformField(volScalarField &inField)
Transforms incoming scalar field into refinement levels understood by OpenFOAM environement.
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
pointScalarField readIncomingPtField(const std::string &inName, const std::string &outName)
Converts incoming size-field/solution-field into pointScalarField defined over all points of mesh...
void checkEightAnchorPoints(bitSet &protectedCell) const
void disableMotion()
Ability to explicitely disable motion.
void extendMarkedCells(bitSet &markedCell) const
void writeMesh()
Ability to write current mesh into current time directory.
scalarField maxPointField(const scalarField &) const
volScalarField readIncomingCellField(const std::string &inName, const std::string &outName)
reads incoming field and converts to volScalarField
autoPtr< motionSolver > motionPtr_
scalarField cellToPoint(const scalarField &vFld) const
volScalarField pF2vF(const pointScalarField &pntF, const std::string &outName)
Converts pointScalarField to volScalarField.
volScalarField readInitialField(const std::string &fldName)
Reads the refinement field and registers it.
bool writeMeshData
Boolean to enable writing of mesh.
bool writeField
Boolean to enable writing of updated solution field every timestep.
virtual Foam::autoPtr< Foam::mapPolyMesh > refine(const labelList &)
Unrefines selected cells in a mesh.
std::vector< bool > cellsToRefine(const std::vector< T > &values, T tol)
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const