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"
28 #include "meshRefinement.H"
32 #include "mapDistributePolyMesh.H"
34 #include "syncTools.H"
35 #include "refinementParameters.H"
36 #include "featureEdgeMesh.H"
37 #include "refinementSurfaces.H"
38 #include "shellSurfaces.H"
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 defineTypeNameAndDebug(autoRefineDriver, 0);
47 } // End namespace Foam
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 // Read explicit feature edges
53 Foam::label Foam::autoRefineDriver::readFeatureEdges
55 const PtrList<dictionary>& featDicts,
56 PtrList<featureEdgeMesh>& featureMeshes,
57 labelList& featureLevels
60 Info<< "Reading external feature lines." << endl;
62 const fvMesh& mesh = meshRefiner_.mesh();
64 featureMeshes.setSize(featDicts.size());
65 featureLevels.setSize(featDicts.size());
69 const dictionary& dict = featDicts[i];
71 fileName featFileName(dict.lookup("file"));
81 mesh.time().constant(), // directory
82 "triSurface", // instance
83 mesh.db(), // registry
91 featureMeshes[i].mergePoints(meshRefiner_.mergeDistance());
92 featureLevels[i] = readLabel(dict.lookup("level"));
94 Info<< "Refinement level " << featureLevels[i]
95 << " for all cells crossed by feature " << featFileName
96 << " (" << featureMeshes[i].points().size() << " points, "
97 << featureMeshes[i].edges().size() << ")." << endl;
100 Info<< "Read feature lines in = "
101 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
103 return featureMeshes.size();
107 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
109 // Construct from components
110 Foam::autoRefineDriver::autoRefineDriver
112 meshRefinement& meshRefiner,
113 decompositionMethod& decomposer,
114 fvMeshDistribute& distributor,
115 const labelList& globalToPatch
118 meshRefiner_(meshRefiner),
119 decomposer_(decomposer),
120 distributor_(distributor),
121 globalToPatch_(globalToPatch)
125 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
127 Foam::label Foam::autoRefineDriver::featureEdgeRefine
129 const refinementParameters& refineParams,
130 const PtrList<dictionary>& featDicts,
132 const label minRefine
135 const fvMesh& mesh = meshRefiner_.mesh();
137 // Read explicit feature edges
138 PtrList<featureEdgeMesh> featureMeshes;
139 // Per feature the refinement level
140 labelList featureLevels;
141 readFeatureEdges(featDicts, featureMeshes, featureLevels);
146 if (featureMeshes.size() > 0 && maxIter > 0)
148 for (; iter < maxIter; iter++)
151 << "Feature refinement iteration " << iter << nl
152 << "------------------------------" << nl
155 labelList candidateCells
157 meshRefiner_.refineCandidates
159 refineParams.keepPoints()[0], // For now only use one.
160 refineParams.curvature(),
165 true, // featureRefinement
166 false, // internalRefinement
167 false, // surfaceRefinement
168 false, // curvatureRefinement
169 refineParams.maxGlobalCells(),
170 refineParams.maxLocalCells()
173 labelList cellsToRefine
175 meshRefiner_.meshCutter().consistentRefinement
181 Info<< "Determined cells to refine in = "
182 << mesh.time().cpuTimeIncrement() << " s" << endl;
186 label nCellsToRefine = cellsToRefine.size();
187 reduce(nCellsToRefine, sumOp<label>());
189 Info<< "Selected for feature refinement : " << nCellsToRefine
190 << " cells (out of " << mesh.globalData().nTotalCells()
193 if (nCellsToRefine <= minRefine)
195 Info<< "Stopping refining since too few cells selected."
203 const_cast<Time&>(mesh.time())++;
206 meshRefiner_.refineAndBalance
208 "feature refinement iteration " + name(iter),
219 Foam::label Foam::autoRefineDriver::surfaceOnlyRefine
221 const refinementParameters& refineParams,
225 const fvMesh& mesh = meshRefiner_.mesh();
227 // Determine the maximum refinement level over all surfaces. This
228 // determines the minumum number of surface refinement iterations.
229 label overallMaxLevel = max(meshRefiner_.surfaces().maxLevel());
232 for (iter = 0; iter < maxIter; iter++)
235 << "Surface refinement iteration " << iter << nl
236 << "------------------------------" << nl
240 // Determine cells to refine
241 // ~~~~~~~~~~~~~~~~~~~~~~~~~
242 // Only look at surface intersections (minLevel and surface curvature),
243 // do not do internal refinement (refinementShells)
245 const PtrList<featureEdgeMesh> dummyFeatures;
247 labelList candidateCells
249 meshRefiner_.refineCandidates
251 refineParams.keepPoints()[0],
252 refineParams.curvature(),
254 dummyFeatures, // dummy featureMeshes;
255 labelList(0), // dummy featureLevels;
257 false, // featureRefinement
258 false, // internalRefinement
259 true, // surfaceRefinement
260 true, // curvatureRefinement
261 refineParams.maxGlobalCells(),
262 refineParams.maxLocalCells()
265 labelList cellsToRefine
267 meshRefiner_.meshCutter().consistentRefinement
273 Info<< "Determined cells to refine in = "
274 << mesh.time().cpuTimeIncrement() << " s" << endl;
277 label nCellsToRefine = cellsToRefine.size();
278 reduce(nCellsToRefine, sumOp<label>());
280 Info<< "Selected for refinement : " << nCellsToRefine
281 << " cells (out of " << mesh.globalData().nTotalCells()
284 // Stop when no cells to refine or have done minimum nessecary
285 // iterations and not enough cells to refine.
290 iter >= overallMaxLevel
291 && nCellsToRefine <= refineParams.minRefineCells()
295 Info<< "Stopping refining since too few cells selected."
303 const_cast<Time&>(mesh.time())++;
306 meshRefiner_.refineAndBalance
308 "surface refinement iteration " + name(iter),
318 void Foam::autoRefineDriver::removeInsideCells
320 const refinementParameters& refineParams,
321 const label nBufferLayers
325 << "Removing mesh beyond surface intersections" << nl
326 << "------------------------------------------" << nl
329 const fvMesh& mesh = meshRefiner_.mesh();
333 const_cast<Time&>(mesh.time())++;
336 meshRefiner_.splitMesh
338 nBufferLayers, // nBufferLayers
340 refineParams.keepPoints()[0]
345 Pout<< "Writing subsetted mesh to time "
346 << mesh.time().timeName() << '.' << endl;
347 meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
348 Pout<< "Dumped mesh in = "
349 << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
354 Foam::label Foam::autoRefineDriver::shellRefine
356 const refinementParameters& refineParams,
360 const fvMesh& mesh = meshRefiner_.mesh();
362 // Mark current boundary faces with 0. Have meshRefiner maintain them.
363 meshRefiner_.userFaceData().setSize(1);
365 // mark list to remove any refined faces
366 meshRefiner_.userFaceData()[0].first() = meshRefinement::REMOVE;
367 meshRefiner_.userFaceData()[0].second() = createWithValues<labelList>
371 meshRefiner_.intersectedFaces(),
375 // Determine the maximum refinement level over all volume refinement
376 // regions. This determines the minumum number of shell refinement
378 label overallMaxShellLevel = meshRefiner_.shells().maxLevel();
381 for (iter = 0; iter < maxIter; iter++)
384 << "Shell refinement iteration " << iter << nl
385 << "----------------------------" << nl
388 const PtrList<featureEdgeMesh> dummyFeatures;
390 labelList candidateCells
392 meshRefiner_.refineCandidates
394 refineParams.keepPoints()[0],
395 refineParams.curvature(),
397 dummyFeatures, // dummy featureMeshes;
398 labelList(0), // dummy featureLevels;
400 false, // featureRefinement
401 true, // internalRefinement
402 false, // surfaceRefinement
403 false, // curvatureRefinement
404 refineParams.maxGlobalCells(),
405 refineParams.maxLocalCells()
411 Pout<< "Dumping " << candidateCells.size()
412 << " cells to cellSet candidateCellsFromShells." << endl;
414 cellSet(mesh, "candidateCellsFromShells", candidateCells).write();
417 // Problem choosing starting faces for bufferlayers (bFaces)
418 // - we can't use the current intersected boundary faces
419 // (intersectedFaces) since this grows indefinitely
420 // - if we use 0 faces we don't satisfy bufferLayers from the
422 // - possibly we want to have bFaces only the initial set of faces
423 // and maintain the list while doing the refinement.
426 findIndices(meshRefiner_.userFaceData()[0].second(), 0)
429 //Info<< "Collected boundary faces : "
430 // << returnReduce(bFaces.size(), sumOp<label>()) << endl;
432 labelList cellsToRefine;
434 if (refineParams.nBufferLayers() <= 2)
436 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement
438 refineParams.nBufferLayers(),
439 candidateCells, // cells to refine
440 bFaces, // faces for nBufferLayers
441 1, // point difference
442 meshRefiner_.intersectedPoints() // points to check
447 cellsToRefine = meshRefiner_.meshCutter().consistentSlowRefinement2
449 refineParams.nBufferLayers(),
450 candidateCells, // cells to refine
451 bFaces // faces for nBufferLayers
455 Info<< "Determined cells to refine in = "
456 << mesh.time().cpuTimeIncrement() << " s" << endl;
459 label nCellsToRefine = cellsToRefine.size();
460 reduce(nCellsToRefine, sumOp<label>());
462 Info<< "Selected for internal refinement : " << nCellsToRefine
463 << " cells (out of " << mesh.globalData().nTotalCells()
466 // Stop when no cells to refine or have done minimum nessecary
467 // iterations and not enough cells to refine.
472 iter >= overallMaxShellLevel
473 && nCellsToRefine <= refineParams.minRefineCells()
477 Info<< "Stopping refining since too few cells selected."
485 const_cast<Time&>(mesh.time())++;
488 meshRefiner_.refineAndBalance
490 "shell refinement iteration " + name(iter),
496 meshRefiner_.userFaceData().clear();
502 void Foam::autoRefineDriver::baffleAndSplitMesh
504 const refinementParameters& refineParams,
505 const bool handleSnapProblems,
506 const dictionary& motionDict
510 << "Splitting mesh at surface intersections" << nl
511 << "---------------------------------------" << nl
514 const fvMesh& mesh = meshRefiner_.mesh();
516 // Introduce baffles at surface intersections. Note:
517 // meshRefiment::surfaceIndex() will
518 // be like boundary face from now on so not coupled anymore.
519 meshRefiner_.baffleAndSplitMesh
521 handleSnapProblems, // detect&remove potential snap problem
522 false, // perpendicular edge connected cells
523 scalarField(0), // per region perpendicular angle
524 !handleSnapProblems, // merge free standing baffles?
526 const_cast<Time&>(mesh.time()),
528 refineParams.keepPoints()[0]
533 void Foam::autoRefineDriver::zonify
535 const refinementParameters& refineParams
538 // Mesh is at its finest. Do zoning
539 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540 // This puts all faces with intersection across a zoneable surface
541 // into that surface's faceZone. All cells inside faceZone get given the
544 if (meshRefiner_.surfaces().getNamedSurfaces().size() > 0)
547 << "Introducing zones for interfaces" << nl
548 << "--------------------------------" << nl
551 const fvMesh& mesh = meshRefiner_.mesh();
555 const_cast<Time&>(mesh.time())++;
558 meshRefiner_.zonify(refineParams.keepPoints()[0]);
562 Pout<< "Writing zoned mesh to time "
563 << mesh.time().timeName() << '.' << endl;
567 mesh.time().path()/mesh.time().timeName()
571 // Check that all faces are synced
572 meshRefinement::checkCoupledFaceZones(mesh);
577 void Foam::autoRefineDriver::splitAndMergeBaffles
579 const refinementParameters& refineParams,
580 const bool handleSnapProblems,
581 const dictionary& motionDict
585 << "Handling cells with snap problems" << nl
586 << "---------------------------------" << nl
589 const fvMesh& mesh = meshRefiner_.mesh();
591 // Introduce baffles and split mesh
594 const_cast<Time&>(mesh.time())++;
597 const scalarField& perpAngle = meshRefiner_.surfaces().perpendicularAngle();
599 meshRefiner_.baffleAndSplitMesh
602 handleSnapProblems, // remove perp edge connected cells
603 perpAngle, // perp angle
604 false, // merge free standing baffles?
606 const_cast<Time&>(mesh.time()),
608 refineParams.keepPoints()[0]
613 const_cast<Time&>(mesh.time())++;
616 // Duplicate points on baffles that are on more than one cell
617 // region. This will help snapping pull them to separate surfaces.
618 meshRefiner_.dupNonManifoldPoints();
621 // Merge all baffles that are still remaining after duplicating points.
622 List<labelPair> couples
624 meshRefiner_.getDuplicateFaces // get all baffles
626 identity(mesh.nFaces()-mesh.nInternalFaces())
627 + mesh.nInternalFaces()
631 label nCouples = returnReduce(couples.size(), sumOp<label>());
633 Info<< "Detected unsplittable baffles : "
638 // Actually merge baffles. Note: not exactly parallellized. Should
639 // convert baffle faces into processor faces if they resulted
641 meshRefiner_.mergeBaffles(couples);
645 // Debug:test all is still synced across proc patches
646 meshRefiner_.checkData();
648 Info<< "Merged free-standing baffles in = "
649 << mesh.time().cpuTimeIncrement() << " s." << endl;
654 Pout<< "Writing handleProblemCells mesh to time "
655 << mesh.time().timeName() << '.' << endl;
656 meshRefiner_.write(debug, mesh.time().path()/mesh.time().timeName());
661 void Foam::autoRefineDriver::mergePatchFaces
663 const refinementParameters& refineParams
666 const fvMesh& mesh = meshRefiner_.mesh();
669 << "Merge refined boundary faces" << nl
670 << "----------------------------" << nl
675 const_cast<Time&>(mesh.time())++;
678 meshRefiner_.mergePatchFaces
680 Foam::cos(45*mathematicalConstant::pi/180.0),
681 Foam::cos(45*mathematicalConstant::pi/180.0),
682 meshRefinement::addedPatches(globalToPatch_)
687 meshRefiner_.checkData();
690 meshRefiner_.mergeEdges(Foam::cos(45*mathematicalConstant::pi/180.0));
694 meshRefiner_.checkData();
699 void Foam::autoRefineDriver::doRefine
701 const dictionary& refineDict,
702 const refinementParameters& refineParams,
703 const bool prepareForSnapping,
704 const dictionary& motionDict
708 << "Refinement phase" << nl
709 << "----------------" << nl
712 const fvMesh& mesh = meshRefiner_.mesh();
714 const_cast<Time&>(mesh.time())++;
717 // Check that all the keep points are inside the mesh.
718 refineParams.findCells(mesh);
720 PtrList<dictionary> featDicts(refineDict.lookup("features"));
722 // Refine around feature edges
728 0 // min cells to refine
731 // Refine based on surface
738 // Remove cells (a certain distance) beyond surface intersections
745 // Internal mesh refinement
752 // Introduce baffles at surface intersections
753 baffleAndSplitMesh(refineParams, prepareForSnapping, motionDict);
755 // Mesh is at its finest. Do optional zoning.
756 zonify(refineParams);
758 // Pull baffles apart
759 splitAndMergeBaffles(refineParams, prepareForSnapping, motionDict);
761 // Do something about cells with refined faces on the boundary
762 if (prepareForSnapping)
764 mergePatchFaces(refineParams);
768 if (Pstream::parRun())
771 << "Doing final balancing" << nl
772 << "---------------------" << nl
777 const_cast<Time&>(mesh.time())++;
780 // Do final balancing. Keep zoned faces on one processor.
792 // ************************************************************************* //