1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*----------------------------------------------------------------------------*/
27 #include "autoRefineDriver.H"
31 #include "mapDistributePolyMesh.H"
33 #include "syncTools.H"
34 #include "refinementParameters.H"
35 #include "featureEdgeMesh.H"
36 #include "refinementSurfaces.H"
37 #include "shellSurfaces.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(autoRefineDriver, 0);
46 } // End namespace Foam
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 // Read explicit feature edges
52 Foam::label Foam::autoRefineDriver::readFeatureEdges
54 const PtrList<dictionary>& featDicts,
55 PtrList<featureEdgeMesh>& featureMeshes,
56 labelList& featureLevels
59 Info<< "Reading external feature lines." << endl;
61 const fvMesh& mesh = meshRefiner_.mesh();
63 featureMeshes.setSize(featDicts.size());
64 featureLevels.setSize(featDicts.size());
68 const dictionary& dict = featDicts[i];
70 fileName featFileName(dict.lookup("file"));
80 mesh.time().constant(), // directory
81 "triSurface", // instance
82 mesh.db(), // registry
90 featureMeshes[i].mergePoints(meshRefiner_.mergeDistance());
91 featureLevels[i] = readLabel(dict.lookup("level"));
93 Info<< "Refinement level " << featureLevels[i]
94 << " for all cells crossed by feature " << featFileName
95 << " (" << featureMeshes[i].points().size() << " points, "
96 << featureMeshes[i].edges().size() << ")." << endl;
99 Info<< "Read feature lines in = "
100 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
102 return featureMeshes.size();
106 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
108 // Construct from components
109 Foam::autoRefineDriver::autoRefineDriver
111 meshRefinement& meshRefiner,
112 decompositionMethod& decomposer,
113 fvMeshDistribute& distributor,
114 const labelList& globalToPatch
117 meshRefiner_(meshRefiner),
118 decomposer_(decomposer),
119 distributor_(distributor),
120 globalToPatch_(globalToPatch)
124 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
126 Foam::label Foam::autoRefineDriver::featureEdgeRefine
128 const refinementParameters& refineParams,
129 const PtrList<dictionary>& featDicts,
131 const label minRefine
134 const fvMesh& mesh = meshRefiner_.mesh();
136 // Read explicit feature edges
137 PtrList<featureEdgeMesh> featureMeshes;
138 // Per feature the refinement level
139 labelList featureLevels;
140 readFeatureEdges(featDicts, featureMeshes, featureLevels);
145 if (featureMeshes.size() > 0 && maxIter > 0)
147 for (; iter < maxIter; iter++)
150 << "Feature refinement iteration " << iter << nl
151 << "------------------------------" << nl
154 labelList candidateCells
156 meshRefiner_.refineCandidates
158 refineParams.keepPoints()[0], // For now only use one.
159 refineParams.curvature(),
164 true, // featureRefinement
165 false, // internalRefinement
166 false, // surfaceRefinement
167 false, // curvatureRefinement
168 refineParams.maxGlobalCells(),
169 refineParams.maxLocalCells()
172 labelList cellsToRefine
174 meshRefiner_.meshCutter().consistentRefinement
180 Info<< "Determined cells to refine in = "
181 << mesh.time().cpuTimeIncrement() << " s" << endl;
185 label nCellsToRefine = cellsToRefine.size();
186 reduce(nCellsToRefine, sumOp<label>());
188 Info<< "Selected for feature refinement : " << nCellsToRefine
189 << " cells (out of " << mesh.globalData().nTotalCells()
192 if (nCellsToRefine <= minRefine)
194 Info<< "Stopping refining since too few cells selected."
202 const_cast<Time&>(mesh.time())++;
205 meshRefiner_.refineAndBalance
207 "feature refinement iteration " + name(iter),
218 Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
220 const refinementParameters& refineParams,
224 const fvMesh& mesh = meshRefiner_.mesh();
226 // Determine the maximum refinement level over all surfaces. This
227 // determines the minumum number of surface refinement iterations.
228 label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
231 for (iter = 0; iter < maxIter; iter++)
234 << "Surface refinement iteration " << iter << nl
235 << "------------------------------" << nl
239 // Determine cells to refine
240 // ~~~~~~~~~~~~~~~~~~~~~~~~~
241 // Only look at surface intersections (minLevel and surface curvature),
242 // do not do internal refinement (refinementShells)
244 const PtrList<featureEdgeMesh> dummyFeatures;
246 labelList candidateCells
248 meshRefiner_.refineCandidates
250 refineParams.keepPoints()[0],
251 refineParams.curvature(),
253 dummyFeatures, // dummy featureMeshes;
254 labelList(0), // dummy featureLevels;
256 false, // featureRefinement
257 false, // internalRefinement
258 true, // surfaceRefinement
259 true, // curvatureRefinement
260 refineParams.maxGlobalCells(),
261 refineParams.maxLocalCells()
264 labelList cellsToRefine
266 meshRefiner_.meshCutter().consistentRefinement
272 Info<< "Determined cells to refine in = "
273 << mesh.time().cpuTimeIncrement() << " s" << endl;
276 label nCellsToRefine = cellsToRefine.size();
277 reduce(nCellsToRefine, sumOp<label>());
279 Info<< "Selected for refinement : " << nCellsToRefine
280 << " cells (out of " << mesh.globalData().nTotalCells()
283 // Stop when no cells to refine or have done minimum nessecary
284 // iterations and not enough cells to refine.
289 iter >= overallMaxLevel
290 && nCellsToRefine <= refineParams.minRefineCells()
294 Info<< "Stopping refining since too few cells selected."
302 const_cast<Time&>(mesh.time())++;
305 meshRefiner_.refineAndBalance
307 "surface refinement iteration " + name(iter),
317 void Foam::autoRefineDriver::removeInsideCells
319 const refinementParameters& refineParams,
320 const label nBufferLayers
324 << "Removing mesh beyond surface intersections" << nl
325 << "------------------------------------------" << nl
328 const fvMesh& mesh = meshRefiner_.mesh();
332 const_cast<Time&>(mesh.time())++;
335 meshRefiner_.splitMesh
337 nBufferLayers, // nBufferLayers
339 refineParams.keepPoints()[0]
344 Pout<< "Writing subsetted mesh to time "
345 << mesh.time().timeName() << '.' << endl;
346 meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
347 Pout<< "Dumped mesh in = "
348 << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
353 Foam::label Foam::autoRefineDriver::shellRefine
355 const refinementParameters& refineParams,
359 const fvMesh& mesh = meshRefiner_.mesh();
361 // Mark current boundary faces with 0. Have meshRefiner maintain them.
362 meshRefiner_.userFaceData().setSize(1);
364 // mark list to remove any refined faces
365 meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
366 meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
370 meshRefiner_.intersectedFaces(),
374 // Determine the maximum refinement level over all volume refinement
375 // regions. This determines the minumum number of shell refinement
377 label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
380 for (iter = 0; iter < maxIter; iter++)
383 << "Shell refinement iteration " << iter << nl
384 << "----------------------------" << nl
387 const PtrList<featureEdgeMesh> dummyFeatures;
389 labelList candidateCells
391 meshRefiner_.refineCandidates
393 refineParams.keepPoints()[0],
394 refineParams.curvature(),
396 dummyFeatures, // dummy featureMeshes;
397 labelList(0), // dummy featureLevels;
399 false, // featureRefinement
400 true, // internalRefinement
401 false, // surfaceRefinement
402 false, // curvatureRefinement
403 refineParams.maxGlobalCells(),
404 refineParams.maxLocalCells()
410 Pout<< "Dumping " << candidateCells.size()
411 << " cells to cellSet candidateCellsFromShells." << endl;
413 cellSet(mesh, "candidateCellsFromShells", candidateCells).write();
416 // Problem choosing starting faces for bufferlayers (bFaces)
417 // - we can't use the current intersected boundary faces
418 // (intersectedFaces) since this grows indefinitely
419 // - if we use 0 faces we don't satisfy bufferLayers from the
421 // - possibly we want to have bFaces only the initial set of faces
422 // and maintain the list while doing the refinement.
425 findIndices(meshRefiner_.userFaceData()[0].second(), 0)
428 //Info<< "Collected boundary faces : "
429 // << returnReduce(bFaces.size(), sumOp<label>()) << endl;
431 labelList cellsToRefine;
433 if (refineParams.nBufferLayers() <= 2)
435 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
437 refineParams.nBufferLayers(),
438 candidateCells, // cells to refine
439 bFaces, // faces for nBufferLayers
440 1, // point difference
441 meshRefiner_.intersectedPoints() // points to check
446 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
448 refineParams.nBufferLayers(),
449 candidateCells, // cells to refine
450 bFaces // faces for nBufferLayers
454 Info<< "Determined cells to refine in = "
455 << mesh.time().cpuTimeIncrement() << " s" << endl;
458 label nCellsToRefine = cellsToRefine.size();
459 reduce(nCellsToRefine, sumOp<label>());
461 Info<< "Selected for internal refinement : " << nCellsToRefine
462 << " cells (out of " << mesh.globalData().nTotalCells()
465 // Stop when no cells to refine or have done minimum nessecary
466 // iterations and not enough cells to refine.
471 iter >= overallMaxShellLevel
472 && nCellsToRefine <= refineParams.minRefineCells()
476 Info<< "Stopping refining since too few cells selected."
484 const_cast<Time&>(mesh.time())++;
487 meshRefiner_.refineAndBalance
489 "shell refinement iteration " + name(iter),
495 meshRefiner_.userFaceData().clear();
501 void Foam::autoRefineDriver::baffleAndSplitMesh
503 const refinementParameters& refineParams,
504 const bool handleSnapProblems
508 << "Splitting mesh at surface intersections" << nl
509 << "---------------------------------------" << nl
512 const fvMesh& mesh = meshRefiner_.mesh();
514 // Introduce baffles at surface intersections. Note:
515 // meshRefiment::surfaceIndex() will
516 // be like boundary face from now on so not coupled anymore.
517 meshRefiner_.baffleAndSplitMesh
520 !handleSnapProblems, // merge free standing baffles?
521 const_cast<Time&>(mesh.time()),
523 refineParams.keepPoints()[0]
528 void Foam::autoRefineDriver::zonify
530 const refinementParameters& refineParams
533 // Mesh is at its finest. Do zoning
534 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
535 // This puts all faces with intersection across a zoneable surface
536 // into that surface's faceZone. All cells inside faceZone get given the
539 if (meshRefiner_.surfaces().getNamedSurfaces().size() > 0)
542 << "Introducing zones for interfaces" << nl
543 << "--------------------------------" << nl
546 const fvMesh& mesh = meshRefiner_.mesh();
550 const_cast<Time&>(mesh.time())++;
553 meshRefiner_.zonify(refineParams.keepPoints()[0]);
557 Pout<< "Writing zoned mesh to time "
558 << mesh.time().timeName() << '.' << endl;
562 mesh.time().path()/mesh.time().timeName()
566 // Check that all faces are synced
567 meshRefinement::checkCoupledFaceZones(mesh);
572 void Foam::autoRefineDriver::splitAndMergeBaffles
574 const refinementParameters& refineParams,
575 const bool handleSnapProblems
579 << "Handling cells with snap problems" << nl
580 << "---------------------------------" << nl
583 const fvMesh& mesh = meshRefiner_.mesh();
585 // Introduce baffles and split mesh
588 const_cast<Time&>(mesh.time())++;
591 meshRefiner_.baffleAndSplitMesh
594 false, // merge free standing baffles?
595 const_cast<Time&>(mesh.time()),
597 refineParams.keepPoints()[0]
602 const_cast<Time&>(mesh.time())++;
605 // Duplicate points on baffles that are on more than one cell
606 // region. This will help snapping pull them to separate surfaces.
607 meshRefiner_.dupNonManifoldPoints();
610 // Merge all baffles that are still remaining after duplicating points.
611 List<labelPair> couples
613 meshRefiner_.getDuplicateFaces // get all baffles
615 identity(mesh.nFaces()-mesh.nInternalFaces())
616 + mesh.nInternalFaces()
620 label nCouples = returnReduce(couples.size(), sumOp<label>());
622 Info<< "Detected unsplittable baffles : "
627 // Actually merge baffles. Note: not exactly parallellized. Should
628 // convert baffle faces into processor faces if they resulted
630 meshRefiner_.mergeBaffles(couples);
634 // Debug:test all is still synced across proc patches
635 meshRefiner_.checkData();
637 Info<< "Merged free-standing baffles in = "
638 << mesh.time().cpuTimeIncrement() << " s." << endl;
643 Pout<< "Writing handleProblemCells mesh to time "
644 << mesh.time().timeName() << '.' << endl;
645 meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
650 void Foam::autoRefineDriver::mergePatchFaces
652 const refinementParameters& refineParams
655 const fvMesh& mesh = meshRefiner_.mesh();
658 << "Merge refined boundary faces" << nl
659 << "----------------------------" << nl
664 const_cast<Time&>(mesh.time())++;
667 meshRefiner_.mergePatchFaces
669 Foam::cos(45*mathematicalConstant::pi/180.0),
670 Foam::cos(45*mathematicalConstant::pi/180.0),
671 meshRefinement::addedPatches(globalToPatch_)
676 meshRefiner_.checkData();
679 meshRefiner_.mergeEdges(Foam::cos(45*mathematicalConstant::pi/180.0));
683 meshRefiner_.checkData();
688 void Foam::autoRefineDriver::doRefine
690 const dictionary& refineDict,
691 const refinementParameters& refineParams,
692 const bool prepareForSnapping
696 << "Refinement phase" << nl
697 << "----------------" << nl
700 const fvMesh& mesh = meshRefiner_.mesh();
702 const_cast<Time&>(mesh.time())++;
705 // Check that all the keep points are inside the mesh.
706 refineParams.findCells(mesh);
708 PtrList<dictionary> featDicts(refineDict.lookup("features"));
710 // Refine around feature edges
716 0 // min cells to refine
719 // Refine based on surface
726 // Remove cells (a certain distance) beyond surface intersections
733 // Internal mesh refinement
740 // Introduce baffles at surface intersections
741 baffleAndSplitMesh(refineParams, prepareForSnapping);
743 // Mesh is at its finest. Do optional zoning.
744 zonify(refineParams);
746 // Pull baffles apart
747 splitAndMergeBaffles(refineParams, prepareForSnapping);
749 // Do something about cells with refined faces on the boundary
750 if (prepareForSnapping)
752 mergePatchFaces(refineParams);
756 if (Pstream::parRun())
759 << "Doing final balancing" << nl
760 << "---------------------" << nl
765 const_cast<Time&>(mesh.time())++;
768 // Do final balancing. Keep zoned faces on one processor.
780 // ************************************************************************* //