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 "autoRefineDriver.H"
00027 #include <autoMesh/meshRefinement.H>
00028 #include <finiteVolume/fvMesh.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <meshTools/cellSet.H>
00031 #include <OpenFOAM/syncTools.H>
00032 #include <autoMesh/refinementParameters.H>
00033 #include <edgeMesh/featureEdgeMesh.H>
00034 #include <autoMesh/refinementSurfaces.H>
00035 #include <autoMesh/shellSurfaces.H>
00036 #include <OpenFOAM/mapDistributePolyMesh.H>
00037 #include <OpenFOAM/mathematicalConstants.H>
00038
00039
00040
00041 namespace Foam
00042 {
00043
00044 defineTypeNameAndDebug(autoRefineDriver, 0);
00045
00046 }
00047
00048
00049
00050
00051
00052 Foam::label Foam::autoRefineDriver::readFeatureEdges
00053 (
00054 const PtrList<dictionary>& featDicts,
00055 PtrList<featureEdgeMesh>& featureMeshes,
00056 labelList& featureLevels
00057 ) const
00058 {
00059 Info<< "Reading external feature lines." << endl;
00060
00061 const fvMesh& mesh = meshRefiner_.mesh();
00062
00063 featureMeshes.setSize(featDicts.size());
00064 featureLevels.setSize(featDicts.size());
00065
00066 forAll(featDicts, i)
00067 {
00068 const dictionary& dict = featDicts[i];
00069
00070 fileName featFileName(dict.lookup("file"));
00071
00072 featureMeshes.set
00073 (
00074 i,
00075 new featureEdgeMesh
00076 (
00077 IOobject
00078 (
00079 featFileName,
00080
00081
00082 mesh.time().constant(),
00083 "triSurface",
00084 mesh.time(),
00085 IOobject::MUST_READ,
00086 IOobject::NO_WRITE,
00087 false
00088 )
00089 )
00090 );
00091
00092 featureMeshes[i].mergePoints(meshRefiner_.mergeDistance());
00093 featureLevels[i] = readLabel(dict.lookup("level"));
00094
00095 Info<< "Refinement level " << featureLevels[i]
00096 << " for all cells crossed by feature " << featFileName
00097 << " (" << featureMeshes[i].points().size() << " points, "
00098 << featureMeshes[i].edges().size() << " edges)." << endl;
00099 }
00100
00101 Info<< "Read feature lines in = "
00102 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
00103
00104 return featureMeshes.size();
00105 }
00106
00107
00108
00109
00110
00111 Foam::autoRefineDriver::autoRefineDriver
00112 (
00113 meshRefinement& meshRefiner,
00114 decompositionMethod& decomposer,
00115 fvMeshDistribute& distributor,
00116 const labelList& globalToPatch
00117 )
00118 :
00119 meshRefiner_(meshRefiner),
00120 decomposer_(decomposer),
00121 distributor_(distributor),
00122 globalToPatch_(globalToPatch)
00123 {}
00124
00125
00126
00127
00128 Foam::label Foam::autoRefineDriver::featureEdgeRefine
00129 (
00130 const refinementParameters& refineParams,
00131 const PtrList<dictionary>& featDicts,
00132 const label maxIter,
00133 const label minRefine
00134 )
00135 {
00136 const fvMesh& mesh = meshRefiner_.mesh();
00137
00138
00139 PtrList<featureEdgeMesh> featureMeshes;
00140
00141 labelList featureLevels;
00142 readFeatureEdges(featDicts, featureMeshes, featureLevels);
00143
00144
00145 label iter = 0;
00146
00147 if (featureMeshes.size() && maxIter > 0)
00148 {
00149 for (; iter < maxIter; iter++)
00150 {
00151 Info<< nl
00152 << "Feature refinement iteration " << iter << nl
00153 << "------------------------------" << nl
00154 << endl;
00155
00156 labelList candidateCells
00157 (
00158 meshRefiner_.refineCandidates
00159 (
00160 refineParams.keepPoints()[0],
00161 refineParams.curvature(),
00162
00163 featureMeshes,
00164 featureLevels,
00165
00166 true,
00167 false,
00168 false,
00169 false,
00170 refineParams.maxGlobalCells(),
00171 refineParams.maxLocalCells()
00172 )
00173 );
00174 labelList cellsToRefine
00175 (
00176 meshRefiner_.meshCutter().consistentRefinement
00177 (
00178 candidateCells,
00179 true
00180 )
00181 );
00182 Info<< "Determined cells to refine in = "
00183 << mesh.time().cpuTimeIncrement() << " s" << endl;
00184
00185
00186
00187 label nCellsToRefine = cellsToRefine.size();
00188 reduce(nCellsToRefine, sumOp<label>());
00189
00190 Info<< "Selected for feature refinement : " << nCellsToRefine
00191 << " cells (out of " << mesh.globalData().nTotalCells()
00192 << ')' << endl;
00193
00194 if (nCellsToRefine <= minRefine)
00195 {
00196 Info<< "Stopping refining since too few cells selected."
00197 << nl << endl;
00198 break;
00199 }
00200
00201
00202 if (debug > 0)
00203 {
00204 const_cast<Time&>(mesh.time())++;
00205 }
00206
00207
00208 if
00209 (
00210 returnReduce
00211 (
00212 (mesh.nCells() >= refineParams.maxLocalCells()),
00213 orOp<bool>()
00214 )
00215 )
00216 {
00217 meshRefiner_.balanceAndRefine
00218 (
00219 "feature refinement iteration " + name(iter),
00220 decomposer_,
00221 distributor_,
00222 cellsToRefine,
00223 refineParams.maxLoadUnbalance()
00224 );
00225 }
00226 else
00227 {
00228 meshRefiner_.refineAndBalance
00229 (
00230 "feature refinement iteration " + name(iter),
00231 decomposer_,
00232 distributor_,
00233 cellsToRefine,
00234 refineParams.maxLoadUnbalance()
00235 );
00236 }
00237 }
00238 }
00239 return iter;
00240 }
00241
00242
00243 Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
00244 (
00245 const refinementParameters& refineParams,
00246 const label maxIter
00247 )
00248 {
00249 const fvMesh& mesh = meshRefiner_.mesh();
00250
00251
00252
00253 label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
00254
00255 label iter;
00256 for (iter = 0; iter < maxIter; iter++)
00257 {
00258 Info<< nl
00259 << "Surface refinement iteration " << iter << nl
00260 << "------------------------------" << nl
00261 << endl;
00262
00263
00264
00265
00266
00267
00268
00269 const PtrList<featureEdgeMesh> dummyFeatures;
00270
00271 labelList candidateCells
00272 (
00273 meshRefiner_.refineCandidates
00274 (
00275 refineParams.keepPoints()[0],
00276 refineParams.curvature(),
00277
00278 dummyFeatures,
00279 labelList(0),
00280
00281 false,
00282 false,
00283 true,
00284 true,
00285 refineParams.maxGlobalCells(),
00286 refineParams.maxLocalCells()
00287 )
00288 );
00289 labelList cellsToRefine
00290 (
00291 meshRefiner_.meshCutter().consistentRefinement
00292 (
00293 candidateCells,
00294 true
00295 )
00296 );
00297 Info<< "Determined cells to refine in = "
00298 << mesh.time().cpuTimeIncrement() << " s" << endl;
00299
00300
00301 label nCellsToRefine = cellsToRefine.size();
00302 reduce(nCellsToRefine, sumOp<label>());
00303
00304 Info<< "Selected for refinement : " << nCellsToRefine
00305 << " cells (out of " << mesh.globalData().nTotalCells()
00306 << ')' << endl;
00307
00308
00309
00310 if
00311 (
00312 nCellsToRefine == 0
00313 || (
00314 iter >= overallMaxLevel
00315 && nCellsToRefine <= refineParams.minRefineCells()
00316 )
00317 )
00318 {
00319 Info<< "Stopping refining since too few cells selected."
00320 << nl << endl;
00321 break;
00322 }
00323
00324
00325 if (debug)
00326 {
00327 const_cast<Time&>(mesh.time())++;
00328 }
00329
00330
00331 if
00332 (
00333 returnReduce
00334 (
00335 (mesh.nCells() >= refineParams.maxLocalCells()),
00336 orOp<bool>()
00337 )
00338 )
00339 {
00340 meshRefiner_.balanceAndRefine
00341 (
00342 "surface refinement iteration " + name(iter),
00343 decomposer_,
00344 distributor_,
00345 cellsToRefine,
00346 refineParams.maxLoadUnbalance()
00347 );
00348 }
00349 else
00350 {
00351 meshRefiner_.refineAndBalance
00352 (
00353 "surface refinement iteration " + name(iter),
00354 decomposer_,
00355 distributor_,
00356 cellsToRefine,
00357 refineParams.maxLoadUnbalance()
00358 );
00359 }
00360 }
00361 return iter;
00362 }
00363
00364
00365 void Foam::autoRefineDriver::removeInsideCells
00366 (
00367 const refinementParameters& refineParams,
00368 const label nBufferLayers
00369 )
00370 {
00371 Info<< nl
00372 << "Removing mesh beyond surface intersections" << nl
00373 << "------------------------------------------" << nl
00374 << endl;
00375
00376 const fvMesh& mesh = meshRefiner_.mesh();
00377
00378 if (debug)
00379 {
00380 const_cast<Time&>(mesh.time())++;
00381 }
00382
00383 meshRefiner_.splitMesh
00384 (
00385 nBufferLayers,
00386 globalToPatch_,
00387 refineParams.keepPoints()[0]
00388 );
00389
00390 if (debug)
00391 {
00392 Pout<< "Writing subsetted mesh to time "
00393 << meshRefiner_.timeName() << '.' << endl;
00394 meshRefiner_.write(debug, mesh.time().path()/meshRefiner_.timeName());
00395 Pout<< "Dumped mesh in = "
00396 << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
00397 }
00398 }
00399
00400
00401 Foam::label Foam::autoRefineDriver::shellRefine
00402 (
00403 const refinementParameters& refineParams,
00404 const label maxIter
00405 )
00406 {
00407 const fvMesh& mesh = meshRefiner_.mesh();
00408
00409
00410 meshRefiner_.userFaceData().setSize(1);
00411
00412
00413 meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
00414 meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
00415 (
00416 mesh.nFaces(),
00417 -1,
00418 meshRefiner_.intersectedFaces(),
00419 0
00420 );
00421
00422
00423
00424
00425 label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
00426
00427 label iter;
00428 for (iter = 0; iter < maxIter; iter++)
00429 {
00430 Info<< nl
00431 << "Shell refinement iteration " << iter << nl
00432 << "----------------------------" << nl
00433 << endl;
00434
00435 const PtrList<featureEdgeMesh> dummyFeatures;
00436
00437 labelList candidateCells
00438 (
00439 meshRefiner_.refineCandidates
00440 (
00441 refineParams.keepPoints()[0],
00442 refineParams.curvature(),
00443
00444 dummyFeatures,
00445 labelList(0),
00446
00447 false,
00448 true,
00449 false,
00450 false,
00451 refineParams.maxGlobalCells(),
00452 refineParams.maxLocalCells()
00453 )
00454 );
00455
00456 if (debug)
00457 {
00458 Pout<< "Dumping " << candidateCells.size()
00459 << " cells to cellSet candidateCellsFromShells." << endl;
00460
00461 cellSet(mesh, "candidateCellsFromShells", candidateCells).write();
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471 labelList bFaces
00472 (
00473 findIndices(meshRefiner_.userFaceData()[0].second(), 0)
00474 );
00475
00476
00477
00478
00479 labelList cellsToRefine;
00480
00481 if (refineParams.nBufferLayers() <= 2)
00482 {
00483 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
00484 (
00485 refineParams.nBufferLayers(),
00486 candidateCells,
00487 bFaces,
00488 1,
00489 meshRefiner_.intersectedPoints()
00490 );
00491 }
00492 else
00493 {
00494 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
00495 (
00496 refineParams.nBufferLayers(),
00497 candidateCells,
00498 bFaces
00499 );
00500 }
00501
00502 Info<< "Determined cells to refine in = "
00503 << mesh.time().cpuTimeIncrement() << " s" << endl;
00504
00505
00506 label nCellsToRefine = cellsToRefine.size();
00507 reduce(nCellsToRefine, sumOp<label>());
00508
00509 Info<< "Selected for internal refinement : " << nCellsToRefine
00510 << " cells (out of " << mesh.globalData().nTotalCells()
00511 << ')' << endl;
00512
00513
00514
00515 if
00516 (
00517 nCellsToRefine == 0
00518 || (
00519 iter >= overallMaxShellLevel
00520 && nCellsToRefine <= refineParams.minRefineCells()
00521 )
00522 )
00523 {
00524 Info<< "Stopping refining since too few cells selected."
00525 << nl << endl;
00526 break;
00527 }
00528
00529
00530 if (debug)
00531 {
00532 const_cast<Time&>(mesh.time())++;
00533 }
00534
00535 if
00536 (
00537 returnReduce
00538 (
00539 (mesh.nCells() >= refineParams.maxLocalCells()),
00540 orOp<bool>()
00541 )
00542 )
00543 {
00544 meshRefiner_.balanceAndRefine
00545 (
00546 "shell refinement iteration " + name(iter),
00547 decomposer_,
00548 distributor_,
00549 cellsToRefine,
00550 refineParams.maxLoadUnbalance()
00551 );
00552 }
00553 else
00554 {
00555 meshRefiner_.refineAndBalance
00556 (
00557 "shell refinement iteration " + name(iter),
00558 decomposer_,
00559 distributor_,
00560 cellsToRefine,
00561 refineParams.maxLoadUnbalance()
00562 );
00563 }
00564 }
00565 meshRefiner_.userFaceData().clear();
00566
00567 return iter;
00568 }
00569
00570
00571 void Foam::autoRefineDriver::baffleAndSplitMesh
00572 (
00573 const refinementParameters& refineParams,
00574 const bool handleSnapProblems,
00575 const dictionary& motionDict
00576 )
00577 {
00578 Info<< nl
00579 << "Splitting mesh at surface intersections" << nl
00580 << "---------------------------------------" << nl
00581 << endl;
00582
00583 const fvMesh& mesh = meshRefiner_.mesh();
00584
00585
00586
00587
00588 meshRefiner_.baffleAndSplitMesh
00589 (
00590 handleSnapProblems,
00591 false,
00592 scalarField(0),
00593 !handleSnapProblems,
00594 motionDict,
00595 const_cast<Time&>(mesh.time()),
00596 globalToPatch_,
00597 refineParams.keepPoints()[0]
00598 );
00599 }
00600
00601
00602 void Foam::autoRefineDriver::zonify
00603 (
00604 const refinementParameters& refineParams
00605 )
00606 {
00607
00608
00609
00610
00611
00612
00613 if (meshRefiner_.surfaces().getNamedSurfaces().size())
00614 {
00615 Info<< nl
00616 << "Introducing zones for interfaces" << nl
00617 << "--------------------------------" << nl
00618 << endl;
00619
00620 const fvMesh& mesh = meshRefiner_.mesh();
00621
00622 if (debug)
00623 {
00624 const_cast<Time&>(mesh.time())++;
00625 }
00626
00627 meshRefiner_.zonify
00628 (
00629 refineParams.keepPoints()[0],
00630 refineParams.allowFreeStandingZoneFaces()
00631 );
00632
00633 if (debug)
00634 {
00635 Pout<< "Writing zoned mesh to time "
00636 << meshRefiner_.timeName() << '.' << endl;
00637 meshRefiner_.write
00638 (
00639 debug,
00640 mesh.time().path()/meshRefiner_.timeName()
00641 );
00642 }
00643
00644
00645 meshRefinement::checkCoupledFaceZones(mesh);
00646 }
00647 }
00648
00649
00650 void Foam::autoRefineDriver::splitAndMergeBaffles
00651 (
00652 const refinementParameters& refineParams,
00653 const bool handleSnapProblems,
00654 const dictionary& motionDict
00655 )
00656 {
00657 Info<< nl
00658 << "Handling cells with snap problems" << nl
00659 << "---------------------------------" << nl
00660 << endl;
00661
00662 const fvMesh& mesh = meshRefiner_.mesh();
00663
00664
00665 if (debug)
00666 {
00667 const_cast<Time&>(mesh.time())++;
00668 }
00669
00670 const scalarField& perpAngle = meshRefiner_.surfaces().perpendicularAngle();
00671
00672 meshRefiner_.baffleAndSplitMesh
00673 (
00674 handleSnapProblems,
00675 handleSnapProblems,
00676 perpAngle,
00677 false,
00678 motionDict,
00679 const_cast<Time&>(mesh.time()),
00680 globalToPatch_,
00681 refineParams.keepPoints()[0]
00682 );
00683
00684 if (debug)
00685 {
00686 const_cast<Time&>(mesh.time())++;
00687 }
00688
00689
00690
00691 meshRefiner_.dupNonManifoldPoints();
00692
00693
00694
00695 List<labelPair> couples
00696 (
00697 meshRefiner_.getDuplicateFaces
00698 (
00699 identity(mesh.nFaces()-mesh.nInternalFaces())
00700 + mesh.nInternalFaces()
00701 )
00702 );
00703
00704 label nCouples = returnReduce(couples.size(), sumOp<label>());
00705
00706 Info<< "Detected unsplittable baffles : "
00707 << nCouples << endl;
00708
00709 if (nCouples > 0)
00710 {
00711
00712
00713
00714 meshRefiner_.mergeBaffles(couples);
00715
00716 if (debug)
00717 {
00718
00719 meshRefiner_.checkData();
00720 }
00721 Info<< "Merged free-standing baffles in = "
00722 << mesh.time().cpuTimeIncrement() << " s." << endl;
00723 }
00724
00725 if (debug)
00726 {
00727 Pout<< "Writing handleProblemCells mesh to time "
00728 << meshRefiner_.timeName() << '.' << endl;
00729 meshRefiner_.write(debug, mesh.time().path()/meshRefiner_.timeName());
00730 }
00731 }
00732
00733
00734 void Foam::autoRefineDriver::mergePatchFaces
00735 (
00736 const refinementParameters& refineParams
00737 )
00738 {
00739 const fvMesh& mesh = meshRefiner_.mesh();
00740
00741 Info<< nl
00742 << "Merge refined boundary faces" << nl
00743 << "----------------------------" << nl
00744 << endl;
00745
00746 if (debug)
00747 {
00748 const_cast<Time&>(mesh.time())++;
00749 }
00750
00751 meshRefiner_.mergePatchFaces
00752 (
00753 Foam::cos(45*mathematicalConstant::pi/180.0),
00754 Foam::cos(45*mathematicalConstant::pi/180.0),
00755 meshRefiner_.meshedPatches()
00756 );
00757
00758 if (debug)
00759 {
00760 meshRefiner_.checkData();
00761 }
00762
00763 meshRefiner_.mergeEdges(Foam::cos(45*mathematicalConstant::pi/180.0));
00764
00765 if (debug)
00766 {
00767 meshRefiner_.checkData();
00768 }
00769 }
00770
00771
00772 void Foam::autoRefineDriver::doRefine
00773 (
00774 const dictionary& refineDict,
00775 const refinementParameters& refineParams,
00776 const bool prepareForSnapping,
00777 const dictionary& motionDict
00778 )
00779 {
00780 Info<< nl
00781 << "Refinement phase" << nl
00782 << "----------------" << nl
00783 << endl;
00784
00785 const fvMesh& mesh = meshRefiner_.mesh();
00786
00787
00788 refineParams.findCells(mesh);
00789
00790 PtrList<dictionary> featDicts(refineDict.lookup("features"));
00791
00792
00793 featureEdgeRefine
00794 (
00795 refineParams,
00796 featDicts,
00797 100,
00798 0
00799 );
00800
00801
00802 surfaceOnlyRefine
00803 (
00804 refineParams,
00805 100
00806 );
00807
00808
00809 removeInsideCells
00810 (
00811 refineParams,
00812 1
00813 );
00814
00815
00816 shellRefine
00817 (
00818 refineParams,
00819 100
00820 );
00821
00822
00823 baffleAndSplitMesh(refineParams, prepareForSnapping, motionDict);
00824
00825
00826 zonify(refineParams);
00827
00828
00829 splitAndMergeBaffles(refineParams, prepareForSnapping, motionDict);
00830
00831
00832 if (prepareForSnapping)
00833 {
00834 mergePatchFaces(refineParams);
00835 }
00836
00837
00838 if (Pstream::parRun())
00839 {
00840 Info<< nl
00841 << "Doing final balancing" << nl
00842 << "---------------------" << nl
00843 << endl;
00844
00845 if (debug)
00846 {
00847 const_cast<Time&>(mesh.time())++;
00848 }
00849
00850
00851
00852
00853 meshRefiner_.balance
00854 (
00855 true,
00856 false,
00857 scalarField(mesh.nCells(), 1),
00858 decomposer_,
00859 distributor_
00860 );
00861 }
00862 }
00863
00864
00865