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