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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include <OpenFOAM/argList.H>
00049 #include <OpenFOAM/Time.H>
00050 #include <OpenFOAM/polyMesh.H>
00051 #include <meshTools/twoDPointCorrector.H>
00052 #include <OpenFOAM/OFstream.H>
00053 #include <dynamicMesh/multiDirRefinement.H>
00054
00055 #include <triSurface/triSurface.H>
00056 #include <meshTools/triSurfaceSearch.H>
00057
00058 #include <meshTools/cellSet.H>
00059 #include <meshTools/pointSet.H>
00060 #include <meshTools/surfaceToCell.H>
00061 #include <meshTools/surfaceToPoint.H>
00062 #include <meshTools/cellToPoint.H>
00063 #include <meshTools/pointToCell.H>
00064 #include <meshTools/cellToCell.H>
00065 #include <meshTools/surfaceSets.H>
00066 #include <dynamicMesh/polyTopoChange.H>
00067 #include <dynamicMesh/polyTopoChanger.H>
00068 #include <OpenFOAM/mapPolyMesh.H>
00069 #include <OpenFOAM/labelIOList.H>
00070 #include <OpenFOAM/emptyPolyPatch.H>
00071 #include <dynamicMesh/removeCells.H>
00072 #include <meshTools/meshSearch.H>
00073
00074 using namespace Foam;
00075
00076
00077
00078
00079
00080 static const scalar edgeTol = 1E-3;
00081
00082
00083 void writeSet(const cellSet& cells, const string& msg)
00084 {
00085 Info<< "Writing " << msg << " (" << cells.size() << ") to cellSet "
00086 << cells.instance()/cells.local()/cells.name()
00087 << endl;
00088 cells.write();
00089 }
00090
00091
00092 direction getNormalDir(const twoDPointCorrector* correct2DPtr)
00093 {
00094 direction dir = 3;
00095
00096 if (correct2DPtr)
00097 {
00098 const vector& normal = correct2DPtr->planeNormal();
00099
00100 if (mag(normal & vector(1, 0, 0)) > 1-edgeTol)
00101 {
00102 dir = 0;
00103 }
00104 else if (mag(normal & vector(0, 1, 0)) > 1-edgeTol)
00105 {
00106 dir = 1;
00107 }
00108 else if (mag(normal & vector(0, 0, 1)) > 1-edgeTol)
00109 {
00110 dir = 2;
00111 }
00112 }
00113 return dir;
00114 }
00115
00116
00117
00118
00119
00120 scalar getEdgeStats(const primitiveMesh& mesh, const direction excludeCmpt)
00121 {
00122 label nX = 0;
00123 label nY = 0;
00124 label nZ = 0;
00125
00126 scalar minX = GREAT;
00127 scalar maxX = -GREAT;
00128 vector x(1, 0, 0);
00129
00130 scalar minY = GREAT;
00131 scalar maxY = -GREAT;
00132 vector y(0, 1, 0);
00133
00134 scalar minZ = GREAT;
00135 scalar maxZ = -GREAT;
00136 vector z(0, 0, 1);
00137
00138 scalar minOther = GREAT;
00139 scalar maxOther = -GREAT;
00140
00141 const edgeList& edges = mesh.edges();
00142
00143 forAll(edges, edgeI)
00144 {
00145 const edge& e = edges[edgeI];
00146
00147 vector eVec(e.vec(mesh.points()));
00148
00149 scalar eMag = mag(eVec);
00150
00151 eVec /= eMag;
00152
00153 if (mag(eVec & x) > 1-edgeTol)
00154 {
00155 minX = min(minX, eMag);
00156 maxX = max(maxX, eMag);
00157 nX++;
00158 }
00159 else if (mag(eVec & y) > 1-edgeTol)
00160 {
00161 minY = min(minY, eMag);
00162 maxY = max(maxY, eMag);
00163 nY++;
00164 }
00165 else if (mag(eVec & z) > 1-edgeTol)
00166 {
00167 minZ = min(minZ, eMag);
00168 maxZ = max(maxZ, eMag);
00169 nZ++;
00170 }
00171 else
00172 {
00173 minOther = min(minOther, eMag);
00174 maxOther = max(maxOther, eMag);
00175 }
00176 }
00177
00178 Info<< "Mesh bounding box:" << boundBox(mesh.points()) << nl << nl
00179 << "Mesh edge statistics:" << nl
00180 << " x aligned : number:" << nX << "\tminLen:" << minX
00181 << "\tmaxLen:" << maxX << nl
00182 << " y aligned : number:" << nY << "\tminLen:" << minY
00183 << "\tmaxLen:" << maxY << nl
00184 << " z aligned : number:" << nZ << "\tminLen:" << minZ
00185 << "\tmaxLen:" << maxZ << nl
00186 << " other : number:" << mesh.nEdges() - nX - nY - nZ
00187 << "\tminLen:" << minOther
00188 << "\tmaxLen:" << maxOther << nl << endl;
00189
00190 if (excludeCmpt == 0)
00191 {
00192 return min(minY, min(minZ, minOther));
00193 }
00194 else if (excludeCmpt == 1)
00195 {
00196 return min(minX, min(minZ, minOther));
00197 }
00198 else if (excludeCmpt == 2)
00199 {
00200 return min(minX, min(minY, minOther));
00201 }
00202 else
00203 {
00204 return min(minX, min(minY, min(minZ, minOther)));
00205 }
00206 }
00207
00208
00209
00210 label addPatch(polyMesh& mesh, const word& patchName)
00211 {
00212 label patchI = mesh.boundaryMesh().findPatchID(patchName);
00213
00214 if (patchI == -1)
00215 {
00216 const polyBoundaryMesh& patches = mesh.boundaryMesh();
00217
00218 List<polyPatch*> newPatches(patches.size() + 1);
00219
00220
00221 patchI = 0;
00222
00223 newPatches[patchI] =
00224 new emptyPolyPatch
00225 (
00226 Foam::word(patchName),
00227 0,
00228 mesh.nInternalFaces(),
00229 patchI,
00230 patches
00231 );
00232
00233 forAll(patches, i)
00234 {
00235 const polyPatch& pp = patches[i];
00236
00237 newPatches[i+1] =
00238 pp.clone
00239 (
00240 patches,
00241 i+1,
00242 pp.size(),
00243 pp.start()
00244 ).ptr();
00245 }
00246
00247 mesh.removeBoundary();
00248 mesh.addPatches(newPatches);
00249
00250 Info<< "Created patch oldInternalFaces at " << patchI << endl;
00251 }
00252 else
00253 {
00254 Info<< "Reusing patch oldInternalFaces at " << patchI << endl;
00255 }
00256
00257
00258 return patchI;
00259 }
00260
00261
00262
00263 void selectCurvatureCells
00264 (
00265 const polyMesh& mesh,
00266 const fileName& surfName,
00267 const triSurfaceSearch& querySurf,
00268 const scalar nearDist,
00269 const scalar curvature,
00270 cellSet& cells
00271 )
00272 {
00273
00274
00275
00276 cells.write();
00277
00278
00279
00280 surfaceToCell cutSource
00281 (
00282 mesh,
00283 surfName,
00284 querySurf.surface(),
00285 querySurf,
00286 pointField(1, mesh.cellCentres()[0]),
00287 false,
00288 false,
00289 false,
00290 nearDist,
00291 curvature
00292 );
00293
00294 cutSource.applyToSet(topoSetSource::ADD, cells);
00295 }
00296
00297
00298
00299
00300 void addCutNeighbours
00301 (
00302 const polyMesh& mesh,
00303 const bool selectInside,
00304 const bool selectOutside,
00305 const labelHashSet& inside,
00306 const labelHashSet& outside,
00307 labelHashSet& cutCells
00308 )
00309 {
00310
00311
00312 labelHashSet addCutFaces(cutCells.size());
00313
00314 for
00315 (
00316 labelHashSet::const_iterator iter = cutCells.begin();
00317 iter != cutCells.end();
00318 ++iter
00319 )
00320 {
00321 label cellI = iter.key();
00322
00323 const labelList& cFaces = mesh.cells()[cellI];
00324
00325 forAll(cFaces, i)
00326 {
00327 label faceI = cFaces[i];
00328
00329 if (mesh.isInternalFace(faceI))
00330 {
00331 label nbr = mesh.faceOwner()[faceI];
00332
00333 if (nbr == cellI)
00334 {
00335 nbr = mesh.faceNeighbour()[faceI];
00336 }
00337
00338 if (selectInside && inside.found(nbr))
00339 {
00340 addCutFaces.insert(nbr);
00341 }
00342 else if (selectOutside && outside.found(nbr))
00343 {
00344 addCutFaces.insert(nbr);
00345 }
00346 }
00347 }
00348 }
00349
00350 Info<< " Selected an additional " << addCutFaces.size()
00351 << " neighbours of cutCells to refine" << endl;
00352
00353 for
00354 (
00355 labelHashSet::const_iterator iter = addCutFaces.begin();
00356 iter != addCutFaces.end();
00357 ++iter
00358 )
00359 {
00360 cutCells.insert(iter.key());
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369 bool limitRefinementLevel
00370 (
00371 const primitiveMesh& mesh,
00372 const label limitDiff,
00373 const labelHashSet& excludeCells,
00374 const labelList& refLevel,
00375 labelHashSet& cutCells
00376 )
00377 {
00378
00379 forAll(refLevel, cellI)
00380 {
00381 if (!excludeCells.found(cellI))
00382 {
00383 const labelList& cCells = mesh.cellCells()[cellI];
00384
00385 forAll(cCells, i)
00386 {
00387 label nbr = cCells[i];
00388
00389 if (!excludeCells.found(nbr))
00390 {
00391 if (refLevel[cellI] - refLevel[nbr] >= limitDiff)
00392 {
00393 FatalErrorIn("limitRefinementLevel")
00394 << "Level difference between neighbouring cells "
00395 << cellI << " and " << nbr
00396 << " greater than or equal to " << limitDiff << endl
00397 << "refLevels:" << refLevel[cellI] << ' '
00398 << refLevel[nbr] << abort(FatalError);
00399 }
00400 }
00401 }
00402 }
00403 }
00404
00405
00406 labelHashSet addCutCells(cutCells.size());
00407
00408 for
00409 (
00410 labelHashSet::const_iterator iter = cutCells.begin();
00411 iter != cutCells.end();
00412 ++iter
00413 )
00414 {
00415
00416 label cellI = iter.key();
00417
00418 const labelList& cCells = mesh.cellCells()[cellI];
00419
00420 forAll(cCells, i)
00421 {
00422 label nbr = cCells[i];
00423
00424 if (!excludeCells.found(nbr) && !cutCells.found(nbr))
00425 {
00426 if (refLevel[cellI] + 1 - refLevel[nbr] >= limitDiff)
00427 {
00428 addCutCells.insert(nbr);
00429 }
00430 }
00431 }
00432 }
00433
00434 if (addCutCells.size())
00435 {
00436
00437
00438 Info<< "Added an additional " << addCutCells.size() << " cells"
00439 << " to satisfy 1:" << limitDiff << " refinement level"
00440 << endl;
00441 for
00442 (
00443 labelHashSet::const_iterator iter = addCutCells.begin();
00444 iter != addCutCells.end();
00445 ++iter
00446 )
00447 {
00448 cutCells.insert(iter.key());
00449 }
00450 return true;
00451 }
00452 else
00453 {
00454 Info<< "Added no additional cells"
00455 << " to satisfy 1:" << limitDiff << " refinement level"
00456 << endl;
00457
00458 return false;
00459 }
00460 }
00461
00462
00463
00464
00465 void doRefinement
00466 (
00467 polyMesh& mesh,
00468 const dictionary& refineDict,
00469 const labelHashSet& refCells,
00470 labelList& refLevel
00471 )
00472 {
00473 label oldCells = mesh.nCells();
00474
00475
00476 multiDirRefinement multiRef
00477 (
00478 mesh,
00479 refCells.toc(),
00480 refineDict
00481 );
00482
00483
00484
00485
00486
00487 refLevel.setSize(mesh.nCells());
00488
00489 for (label cellI = oldCells; cellI < mesh.nCells(); cellI++)
00490 {
00491 refLevel[cellI] = 0;
00492 }
00493
00494 const labelListList& addedCells = multiRef.addedCells();
00495
00496 forAll(addedCells, oldCellI)
00497 {
00498 const labelList& added = addedCells[oldCellI];
00499
00500 if (added.size())
00501 {
00502
00503
00504 label masterLevel = ++refLevel[oldCellI];
00505
00506 forAll(added, i)
00507 {
00508 refLevel[added[i]] = masterLevel;
00509 }
00510 }
00511 }
00512 }
00513
00514
00515
00516 void subsetMesh
00517 (
00518 polyMesh& mesh,
00519 const label writeMesh,
00520 const label patchI,
00521 const labelHashSet& cellsToRemove,
00522 cellSet& cutCells,
00523 labelIOList& refLevel
00524 )
00525 {
00526 removeCells cellRemover(mesh);
00527
00528 labelList cellLabels(cellsToRemove.toc());
00529
00530 Info<< "Mesh has:" << mesh.nCells() << " cells."
00531 << " Removing:" << cellLabels.size() << " cells" << endl;
00532
00533
00534 labelList exposedFaces(cellRemover.getExposedFaces(cellLabels));
00535
00536 polyTopoChange meshMod(mesh);
00537 cellRemover.setRefinement
00538 (
00539 cellLabels,
00540 exposedFaces,
00541 labelList(exposedFaces.size(), patchI),
00542 meshMod
00543 );
00544
00545
00546 Info<< "Morphing ..." << endl;
00547
00548 const Time& runTime = mesh.time();
00549
00550 autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
00551
00552 if (morphMap().hasMotionPoints())
00553 {
00554 mesh.movePoints(morphMap().preMotionPoints());
00555 }
00556
00557
00558 cellRemover.updateMesh(morphMap());
00559
00560
00561 const labelList& cellMap = morphMap().cellMap();
00562
00563 labelList newRefLevel(cellMap.size());
00564
00565 forAll(cellMap, i)
00566 {
00567 newRefLevel[i] = refLevel[cellMap[i]];
00568 }
00569
00570
00571 refLevel.transfer(newRefLevel);
00572
00573 if (writeMesh)
00574 {
00575 Info<< "Writing refined mesh to time " << runTime.timeName() << nl
00576 << endl;
00577
00578 IOstream::defaultPrecision(10);
00579 mesh.write();
00580 refLevel.write();
00581 }
00582
00583
00584 cutCells.updateMesh(morphMap());
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594 void classifyCells
00595 (
00596 const polyMesh& mesh,
00597 const fileName& surfName,
00598 const triSurfaceSearch& querySurf,
00599 const pointField& outsidePts,
00600
00601 const bool selectCut,
00602 const bool selectInside,
00603 const bool selectOutside,
00604
00605 const label nCutLayers,
00606
00607 cellSet& inside,
00608 cellSet& outside,
00609 cellSet& cutCells,
00610 cellSet& selected
00611 )
00612 {
00613
00614 surfaceSets::getSurfaceSets
00615 (
00616 mesh,
00617 surfName,
00618 querySurf.surface(),
00619 querySurf,
00620 outsidePts,
00621
00622 nCutLayers,
00623
00624 inside,
00625 outside,
00626 cutCells
00627 );
00628
00629
00630 if (selectCut)
00631 {
00632 selected.addSet(cutCells);
00633 }
00634 if (selectInside)
00635 {
00636 selected.addSet(inside);
00637 }
00638 if (selectOutside)
00639 {
00640 selected.addSet(outside);
00641 }
00642
00643 Info<< "Determined cell status:" << endl
00644 << " inside :" << inside.size() << endl
00645 << " outside :" << outside.size() << endl
00646 << " cutCells:" << cutCells.size() << endl
00647 << " selected:" << selected.size() << endl
00648 << endl;
00649
00650 writeSet(inside, "inside cells");
00651 writeSet(outside, "outside cells");
00652 writeSet(cutCells, "cut cells");
00653 writeSet(selected, "selected cells");
00654 }
00655
00656
00657
00658
00659 int main(int argc, char *argv[])
00660 {
00661 argList::noParallel();
00662
00663 # include <OpenFOAM/setRootCase.H>
00664 # include <OpenFOAM/createTime.H>
00665 # include <OpenFOAM/createPolyMesh.H>
00666
00667
00668 label newPatchI = addPatch(mesh, "oldInternalFaces");
00669
00670
00671
00672
00673
00674
00675 Info<< "Checking for motionProperties\n" << endl;
00676
00677 IOobject motionObj
00678 (
00679 "motionProperties",
00680 runTime.constant(),
00681 mesh,
00682 IOobject::MUST_READ,
00683 IOobject::NO_WRITE
00684 );
00685
00686
00687 twoDPointCorrector* correct2DPtr = NULL;
00688
00689 if (motionObj.headerOk())
00690 {
00691 Info<< "Reading " << runTime.constant() / "motionProperties"
00692 << endl << endl;
00693
00694 IOdictionary motionProperties(motionObj);
00695
00696 Switch twoDMotion(motionProperties.lookup("twoDMotion"));
00697
00698 if (twoDMotion)
00699 {
00700 Info<< "Correcting for 2D motion" << endl << endl;
00701 correct2DPtr = new twoDPointCorrector(mesh);
00702 }
00703 }
00704
00705 IOdictionary refineDict
00706 (
00707 IOobject
00708 (
00709 "autoRefineMeshDict",
00710 runTime.system(),
00711 mesh,
00712 IOobject::MUST_READ,
00713 IOobject::NO_WRITE
00714 )
00715 );
00716
00717 fileName surfName(refineDict.lookup("surface"));
00718 surfName.expand();
00719 label nCutLayers(readLabel(refineDict.lookup("nCutLayers")));
00720 label cellLimit(readLabel(refineDict.lookup("cellLimit")));
00721 bool selectCut(readBool(refineDict.lookup("selectCut")));
00722 bool selectInside(readBool(refineDict.lookup("selectInside")));
00723 bool selectOutside(readBool(refineDict.lookup("selectOutside")));
00724 bool selectHanging(readBool(refineDict.lookup("selectHanging")));
00725
00726 scalar minEdgeLen(readScalar(refineDict.lookup("minEdgeLen")));
00727 scalar maxEdgeLen(readScalar(refineDict.lookup("maxEdgeLen")));
00728 scalar curvature(readScalar(refineDict.lookup("curvature")));
00729 scalar curvDist(readScalar(refineDict.lookup("curvatureDistance")));
00730 pointField outsidePts(refineDict.lookup("outsidePoints"));
00731 label refinementLimit(readLabel(refineDict.lookup("splitLevel")));
00732 bool writeMesh(readBool(refineDict.lookup("writeMesh")));
00733
00734 Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
00735 << " cells cut by surface : " << selectCut << nl
00736 << " cells inside of surface : " << selectInside << nl
00737 << " cells outside of surface : " << selectOutside << nl
00738 << " hanging cells : " << selectHanging << nl
00739 << endl;
00740
00741
00742 if (nCutLayers > 0 && selectInside)
00743 {
00744 WarningIn(args.executable())
00745 << "Illogical settings : Both nCutLayers>0 and selectInside true."
00746 << endl
00747 << "This would mean that inside cells get removed but should be"
00748 << " included in final mesh" << endl;
00749 }
00750
00751
00752 triSurface surf(surfName);
00753
00754
00755 triSurfaceSearch querySurf(surf);
00756
00757
00758 meshSearch queryMesh(mesh, false);
00759
00760
00761 forAll(outsidePts, outsideI)
00762 {
00763 const point& outsidePoint = outsidePts[outsideI];
00764
00765 if (queryMesh.findCell(outsidePoint, -1, false) == -1)
00766 {
00767 FatalErrorIn(args.executable())
00768 << "outsidePoint " << outsidePoint
00769 << " is not inside any cell"
00770 << exit(FatalError);
00771 }
00772 }
00773
00774
00775
00776
00777 labelIOList refLevel
00778 (
00779 IOobject
00780 (
00781 "refinementLevel",
00782 runTime.timeName(),
00783 polyMesh::defaultRegion,
00784 mesh,
00785 IOobject::READ_IF_PRESENT,
00786 IOobject::AUTO_WRITE
00787 ),
00788 labelList(mesh.nCells(), 0)
00789 );
00790
00791 label maxLevel = max(refLevel);
00792
00793 if (maxLevel > 0)
00794 {
00795 Info<< "Read existing refinement level from file "
00796 << refLevel.objectPath() << nl
00797 << " min level : " << min(refLevel) << nl
00798 << " max level : " << maxLevel << nl
00799 << endl;
00800 }
00801 else
00802 {
00803 Info<< "Created zero refinement level in file "
00804 << refLevel.objectPath() << nl
00805 << endl;
00806 }
00807
00808
00809
00810
00811
00812 direction normalDir(getNormalDir(correct2DPtr));
00813 scalar meshMinEdgeLen = getEdgeStats(mesh, normalDir);
00814
00815 while (meshMinEdgeLen > minEdgeLen)
00816 {
00817
00818 cellSet inside(mesh, "inside", mesh.nCells()/10);
00819 cellSet outside(mesh, "outside", mesh.nCells()/10);
00820 cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
00821 cellSet selected(mesh, "selected", mesh.nCells()/10);
00822
00823 classifyCells
00824 (
00825 mesh,
00826 surfName,
00827 querySurf,
00828 outsidePts,
00829
00830 selectCut,
00831 selectInside,
00832 selectOutside,
00833
00834 nCutLayers,
00835
00836 inside,
00837 outside,
00838 cutCells,
00839 selected
00840 );
00841
00842 Info<< " Selected " << cutCells.name() << " with "
00843 << cutCells.size() << " cells" << endl;
00844
00845 if ((curvDist > 0) && (meshMinEdgeLen < maxEdgeLen))
00846 {
00847
00848
00849
00850 cellSet curveCells(mesh, "curveCells", mesh.nCells()/10);
00851
00852 selectCurvatureCells
00853 (
00854 mesh,
00855 surfName,
00856 querySurf,
00857 maxEdgeLen,
00858 curvature,
00859 curveCells
00860 );
00861
00862 Info<< " Selected " << curveCells.name() << " with "
00863 << curveCells.size() << " cells" << endl;
00864
00865
00866
00867
00868 if (!selectCut)
00869 {
00870 addCutNeighbours
00871 (
00872 mesh,
00873 selectInside,
00874 selectOutside,
00875 inside,
00876 outside,
00877 cutCells
00878 );
00879 }
00880
00881
00882 cutCells.subset(curveCells);
00883
00884 Info<< " Removed cells not on surface curvature. Selected "
00885 << cutCells.size() << endl;
00886 }
00887
00888
00889 if (nCutLayers > 0)
00890 {
00891
00892
00893 subsetMesh(mesh, writeMesh, newPatchI, inside, cutCells, refLevel);
00894 }
00895
00896
00897
00898 while
00899 (
00900 limitRefinementLevel
00901 (
00902 mesh,
00903 refinementLimit,
00904 labelHashSet(),
00905 refLevel,
00906 cutCells
00907 )
00908 )
00909 {}
00910
00911
00912 Info<< " Current cells : " << mesh.nCells() << nl
00913 << " Selected for refinement :" << cutCells.size() << nl
00914 << endl;
00915
00916 if (cutCells.empty())
00917 {
00918 Info<< "Stopping refining since 0 cells selected to be refined ..."
00919 << nl << endl;
00920 break;
00921 }
00922
00923 if ((mesh.nCells() + 8*cutCells.size()) > cellLimit)
00924 {
00925 Info<< "Stopping refining since cell limit reached ..." << nl
00926 << "Would refine from " << mesh.nCells()
00927 << " to " << mesh.nCells() + 8*cutCells.size() << " cells."
00928 << nl << endl;
00929 break;
00930 }
00931
00932 doRefinement
00933 (
00934 mesh,
00935 refineDict,
00936 cutCells,
00937 refLevel
00938 );
00939
00940 Info<< " After refinement:" << mesh.nCells() << nl
00941 << endl;
00942
00943 if (writeMesh)
00944 {
00945 Info<< " Writing refined mesh to time " << runTime.timeName()
00946 << nl << endl;
00947
00948 IOstream::defaultPrecision(10);
00949 mesh.write();
00950 refLevel.write();
00951 }
00952
00953
00954 meshMinEdgeLen = getEdgeStats(mesh, normalDir);
00955 }
00956
00957
00958 if (selectHanging)
00959 {
00960
00961 cellSet inside(mesh, "inside", mesh.nCells()/10);
00962 cellSet outside(mesh, "outside", mesh.nCells()/10);
00963 cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
00964 cellSet selected(mesh, "selected", mesh.nCells()/10);
00965
00966 classifyCells
00967 (
00968 mesh,
00969 surfName,
00970 querySurf,
00971 outsidePts,
00972
00973 selectCut,
00974 selectInside,
00975 selectOutside,
00976
00977 nCutLayers,
00978
00979 inside,
00980 outside,
00981 cutCells,
00982 selected
00983 );
00984
00985
00986
00987
00988 labelHashSet hanging = surfaceSets::getHangingCells(mesh, selected);
00989
00990 Info<< "Detected " << hanging.size() << " hanging cells"
00991 << " (cells with all points on"
00992 << " outside of cellSet 'selected').\nThese would probably result"
00993 << " in flattened cells when snapping the mesh to the surface"
00994 << endl;
00995
00996 Info<< "Refining " << hanging.size() << " hanging cells" << nl
00997 << endl;
00998
00999
01000 while
01001 (
01002 limitRefinementLevel
01003 (
01004 mesh,
01005 refinementLimit,
01006 labelHashSet(),
01007 refLevel,
01008 hanging
01009 )
01010 )
01011 {}
01012
01013 doRefinement(mesh, refineDict, hanging, refLevel);
01014
01015 Info<< "Writing refined mesh to time " << runTime.timeName() << nl
01016 << endl;
01017
01018
01019 IOstream::defaultPrecision(10);
01020 mesh.write();
01021 refLevel.write();
01022
01023 }
01024 else if (!writeMesh)
01025 {
01026 Info<< "Writing refined mesh to time " << runTime.timeName() << nl
01027 << endl;
01028
01029
01030 IOstream::defaultPrecision(10);
01031 mesh.write();
01032 refLevel.write();
01033 }
01034
01035
01036 Info << "End\n" << endl;
01037
01038 return 0;
01039 }
01040
01041
01042