1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*----------------------------------------------------------------------------*/
26 #include "autoRefineDriver.H"
27 #include "meshRefinement.H"
31 #include "syncTools.H"
32 #include "refinementParameters.H"
33 #include "refinementSurfaces.H"
34 #include "refinementFeatures.H"
35 #include "shellSurfaces.H"
36 #include "mapDistributePolyMesh.H"
37 #include "unitConversion.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(autoRefineDriver, 0);
46 } // End namespace Foam
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
54 // Construct from components
55 Foam::autoRefineDriver::autoRefineDriver
57 meshRefinement& meshRefiner,
58 decompositionMethod& decomposer,
59 fvMeshDistribute& distributor,
60 const labelList& globalToPatch
63 meshRefiner_(meshRefiner),
64 decomposer_(decomposer),
65 distributor_(distributor),
66 globalToPatch_(globalToPatch)
70 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
72 Foam::label Foam::autoRefineDriver::featureEdgeRefine
74 const refinementParameters& refineParams,
79 const fvMesh& mesh = meshRefiner_.mesh();
83 if (meshRefiner_.features().size() && maxIter > 0)
85 for (; iter < maxIter; iter++)
88 << "Feature refinement iteration " << iter << nl
89 << "------------------------------" << nl
92 labelList candidateCells
94 meshRefiner_.refineCandidates
96 refineParams.keepPoints()[0], // For now only use one.
97 refineParams.curvature(),
99 true, // featureRefinement
100 false, // internalRefinement
101 false, // surfaceRefinement
102 false, // curvatureRefinement
103 refineParams.maxGlobalCells(),
104 refineParams.maxLocalCells()
107 labelList cellsToRefine
109 meshRefiner_.meshCutter().consistentRefinement
115 Info<< "Determined cells to refine in = "
116 << mesh.time().cpuTimeIncrement() << " s" << endl;
120 label nCellsToRefine = cellsToRefine.size();
121 reduce(nCellsToRefine, sumOp<label>());
123 Info<< "Selected for feature refinement : " << nCellsToRefine
124 << " cells (out of " << mesh.globalData().nTotalCells()
127 if (nCellsToRefine <= minRefine)
129 Info<< "Stopping refining since too few cells selected."
137 const_cast<Time&>(mesh.time())++;
145 (mesh.nCells() >= refineParams.maxLocalCells()),
150 meshRefiner_.balanceAndRefine
152 "feature refinement iteration " + name(iter),
156 refineParams.maxLoadUnbalance()
161 meshRefiner_.refineAndBalance
163 "feature refinement iteration " + name(iter),
167 refineParams.maxLoadUnbalance()
176 Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
178 const refinementParameters& refineParams,
182 const fvMesh& mesh = meshRefiner_.mesh();
184 // Determine the maximum refinement level over all surfaces. This
185 // determines the minumum number of surface refinement iterations.
186 label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
189 for (iter = 0; iter < maxIter; iter++)
192 << "Surface refinement iteration " << iter << nl
193 << "------------------------------" << nl
197 // Determine cells to refine
198 // ~~~~~~~~~~~~~~~~~~~~~~~~~
199 // Only look at surface intersections (minLevel and surface curvature),
200 // do not do internal refinement (refinementShells)
202 labelList candidateCells
204 meshRefiner_.refineCandidates
206 refineParams.keepPoints()[0],
207 refineParams.curvature(),
209 false, // featureRefinement
210 false, // internalRefinement
211 true, // surfaceRefinement
212 true, // curvatureRefinement
213 refineParams.maxGlobalCells(),
214 refineParams.maxLocalCells()
217 labelList cellsToRefine
219 meshRefiner_.meshCutter().consistentRefinement
225 Info<< "Determined cells to refine in = "
226 << mesh.time().cpuTimeIncrement() << " s" << endl;
229 label nCellsToRefine = cellsToRefine.size();
230 reduce(nCellsToRefine, sumOp<label>());
232 Info<< "Selected for refinement : " << nCellsToRefine
233 << " cells (out of " << mesh.globalData().nTotalCells()
236 // Stop when no cells to refine or have done minimum nessecary
237 // iterations and not enough cells to refine.
242 iter >= overallMaxLevel
243 && nCellsToRefine <= refineParams.minRefineCells()
247 Info<< "Stopping refining since too few cells selected."
255 const_cast<Time&>(mesh.time())++;
263 (mesh.nCells() >= refineParams.maxLocalCells()),
268 meshRefiner_.balanceAndRefine
270 "surface refinement iteration " + name(iter),
274 refineParams.maxLoadUnbalance()
279 meshRefiner_.refineAndBalance
281 "surface refinement iteration " + name(iter),
285 refineParams.maxLoadUnbalance()
293 void Foam::autoRefineDriver::removeInsideCells
295 const refinementParameters& refineParams,
296 const label nBufferLayers
300 << "Removing mesh beyond surface intersections" << nl
301 << "------------------------------------------" << nl
304 const fvMesh& mesh = meshRefiner_.mesh();
308 const_cast<Time&>(mesh.time())++;
311 meshRefiner_.splitMesh
313 nBufferLayers, // nBufferLayers
315 refineParams.keepPoints()[0]
320 Pout<< "Writing subsetted mesh to time "
321 << meshRefiner_.timeName() << '.' << endl;
322 meshRefiner_.write(debug, mesh.time().path()/meshRefiner_.timeName());
323 Pout<< "Dumped mesh in = "
324 << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
329 Foam::label Foam::autoRefineDriver::shellRefine
331 const refinementParameters& refineParams,
335 const fvMesh& mesh = meshRefiner_.mesh();
337 // Mark current boundary faces with 0. Have meshRefiner maintain them.
338 meshRefiner_.userFaceData().setSize(1);
340 // mark list to remove any refined faces
341 meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
342 meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
346 meshRefiner_.intersectedFaces(),
350 // Determine the maximum refinement level over all volume refinement
351 // regions. This determines the minumum number of shell refinement
353 label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
356 for (iter = 0; iter < maxIter; iter++)
359 << "Shell refinement iteration " << iter << nl
360 << "----------------------------" << nl
363 labelList candidateCells
365 meshRefiner_.refineCandidates
367 refineParams.keepPoints()[0],
368 refineParams.curvature(),
370 false, // featureRefinement
371 true, // internalRefinement
372 false, // surfaceRefinement
373 false, // curvatureRefinement
374 refineParams.maxGlobalCells(),
375 refineParams.maxLocalCells()
381 Pout<< "Dumping " << candidateCells.size()
382 << " cells to cellSet candidateCellsFromShells." << endl;
384 cellSet c(mesh, "candidateCellsFromShells", candidateCells);
385 c.instance() = meshRefiner_.timeName();
389 // Problem choosing starting faces for bufferlayers (bFaces)
390 // - we can't use the current intersected boundary faces
391 // (intersectedFaces) since this grows indefinitely
392 // - if we use 0 faces we don't satisfy bufferLayers from the
394 // - possibly we want to have bFaces only the initial set of faces
395 // and maintain the list while doing the refinement.
398 findIndices(meshRefiner_.userFaceData()[0].second(), 0)
401 //Info<< "Collected boundary faces : "
402 // << returnReduce(bFaces.size(), sumOp<label>()) << endl;
404 labelList cellsToRefine;
406 if (refineParams.nBufferLayers() <= 2)
408 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
410 refineParams.nBufferLayers(),
411 candidateCells, // cells to refine
412 bFaces, // faces for nBufferLayers
413 1, // point difference
414 meshRefiner_.intersectedPoints() // points to check
419 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
421 refineParams.nBufferLayers(),
422 candidateCells, // cells to refine
423 bFaces // faces for nBufferLayers
427 Info<< "Determined cells to refine in = "
428 << mesh.time().cpuTimeIncrement() << " s" << endl;
431 label nCellsToRefine = cellsToRefine.size();
432 reduce(nCellsToRefine, sumOp<label>());
434 Info<< "Selected for internal refinement : " << nCellsToRefine
435 << " cells (out of " << mesh.globalData().nTotalCells()
438 // Stop when no cells to refine or have done minimum nessecary
439 // iterations and not enough cells to refine.
444 iter >= overallMaxShellLevel
445 && nCellsToRefine <= refineParams.minRefineCells()
449 Info<< "Stopping refining since too few cells selected."
457 const_cast<Time&>(mesh.time())++;
464 (mesh.nCells() >= refineParams.maxLocalCells()),
469 meshRefiner_.balanceAndRefine
471 "shell refinement iteration " + name(iter),
475 refineParams.maxLoadUnbalance()
480 meshRefiner_.refineAndBalance
482 "shell refinement iteration " + name(iter),
486 refineParams.maxLoadUnbalance()
490 meshRefiner_.userFaceData().clear();
496 void Foam::autoRefineDriver::baffleAndSplitMesh
498 const refinementParameters& refineParams,
499 const bool handleSnapProblems,
500 const dictionary& motionDict
504 << "Splitting mesh at surface intersections" << nl
505 << "---------------------------------------" << nl
508 const fvMesh& mesh = meshRefiner_.mesh();
510 // Introduce baffles at surface intersections. Note:
511 // meshRefiment::surfaceIndex() will
512 // be like boundary face from now on so not coupled anymore.
513 meshRefiner_.baffleAndSplitMesh
515 handleSnapProblems, // detect&remove potential snap problem
516 false, // perpendicular edge connected cells
517 scalarField(0), // per region perpendicular angle
518 !handleSnapProblems, // merge free standing baffles?
520 const_cast<Time&>(mesh.time()),
522 refineParams.keepPoints()[0]
527 void Foam::autoRefineDriver::zonify
529 const refinementParameters& refineParams
532 // Mesh is at its finest. Do zoning
533 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
534 // This puts all faces with intersection across a zoneable surface
535 // into that surface's faceZone. All cells inside faceZone get given the
538 if (meshRefiner_.surfaces().getNamedSurfaces().size())
541 << "Introducing zones for interfaces" << nl
542 << "--------------------------------" << nl
545 const fvMesh& mesh = meshRefiner_.mesh();
549 const_cast<Time&>(mesh.time())++;
554 refineParams.keepPoints()[0],
555 refineParams.allowFreeStandingZoneFaces()
560 Pout<< "Writing zoned mesh to time "
561 << meshRefiner_.timeName() << '.' << endl;
565 mesh.time().path()/meshRefiner_.timeName()
569 // Check that all faces are synced
570 meshRefinement::checkCoupledFaceZones(mesh);
575 void Foam::autoRefineDriver::splitAndMergeBaffles
577 const refinementParameters& refineParams,
578 const bool handleSnapProblems,
579 const dictionary& motionDict
583 << "Handling cells with snap problems" << nl
584 << "---------------------------------" << nl
587 const fvMesh& mesh = meshRefiner_.mesh();
589 // Introduce baffles and split mesh
592 const_cast<Time&>(mesh.time())++;
595 const scalarField& perpAngle = meshRefiner_.surfaces().perpendicularAngle();
597 meshRefiner_.baffleAndSplitMesh
600 handleSnapProblems, // remove perp edge connected cells
601 perpAngle, // perp angle
602 false, // merge free standing baffles?
603 //true, // merge free standing baffles?
605 const_cast<Time&>(mesh.time()),
607 refineParams.keepPoints()[0]
612 const_cast<Time&>(mesh.time())++;
615 // Duplicate points on baffles that are on more than one cell
616 // region. This will help snapping pull them to separate surfaces.
617 meshRefiner_.dupNonManifoldPoints();
620 // Merge all baffles that are still remaining after duplicating points.
621 List<labelPair> couples
623 meshRefiner_.getDuplicateFaces // get all baffles
625 identity(mesh.nFaces()-mesh.nInternalFaces())
626 + mesh.nInternalFaces()
630 label nCouples = returnReduce(couples.size(), sumOp<label>());
632 Info<< "Detected unsplittable baffles : "
637 // Actually merge baffles. Note: not exactly parallellized. Should
638 // convert baffle faces into processor faces if they resulted
640 meshRefiner_.mergeBaffles(couples);
644 // Debug:test all is still synced across proc patches
645 meshRefiner_.checkData();
647 Info<< "Merged free-standing baffles in = "
648 << mesh.time().cpuTimeIncrement() << " s." << endl;
653 Pout<< "Writing handleProblemCells mesh to time "
654 << meshRefiner_.timeName() << '.' << endl;
655 meshRefiner_.write(debug, mesh.time().path()/meshRefiner_.timeName());
660 void Foam::autoRefineDriver::mergePatchFaces
662 const refinementParameters& refineParams,
663 const dictionary& motionDict
666 const fvMesh& mesh = meshRefiner_.mesh();
669 << "Merge refined boundary faces" << nl
670 << "----------------------------" << nl
675 const_cast<Time&>(mesh.time())++;
678 meshRefiner_.mergePatchFacesUndo
680 Foam::cos(degToRad(45.0)),
681 Foam::cos(degToRad(45.0)),
682 meshRefiner_.meshedPatches(),
688 meshRefiner_.checkData();
691 meshRefiner_.mergeEdgesUndo(Foam::cos(degToRad(45.0)), motionDict);
695 meshRefiner_.checkData();
700 void Foam::autoRefineDriver::doRefine
702 const dictionary& refineDict,
703 const refinementParameters& refineParams,
704 const bool prepareForSnapping,
705 const dictionary& motionDict
709 << "Refinement phase" << nl
710 << "----------------" << nl
713 const fvMesh& mesh = meshRefiner_.mesh();
715 // Check that all the keep points are inside the mesh.
716 refineParams.findCells(mesh);
718 // Refine around feature edges
723 0 // min cells to refine
726 // Refine based on surface
733 // Remove cells (a certain distance) beyond surface intersections
740 // Internal mesh refinement
747 // Introduce baffles at surface intersections. Remove sections unreachable
749 baffleAndSplitMesh(refineParams, prepareForSnapping, motionDict);
751 // Mesh is at its finest. Do optional zoning.
752 zonify(refineParams);
754 // Pull baffles apart
755 splitAndMergeBaffles(refineParams, prepareForSnapping, motionDict);
757 // Do something about cells with refined faces on the boundary
758 if (prepareForSnapping)
760 mergePatchFaces(refineParams, motionDict);
764 if (Pstream::parRun())
767 << "Doing final balancing" << nl
768 << "---------------------" << nl
773 // const_cast<Time&>(mesh.time())++;
776 // Do final balancing. Keep zoned faces on one processor since the
777 // snap phase will convert them to baffles and this only works for
783 scalarField(mesh.nCells(), 1), // dummy weights
791 // ************************************************************************* //