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 "multiDirRefinement.H"
28 #include "polyTopoChanger.H"
30 #include "undoableMeshCutter.H"
31 #include "hexCellLooper.H"
32 #include "geomCellLooper.H"
34 #include "directions.H"
36 #include "mapPolyMesh.H"
37 #include "polyTopoChange.H"
39 #include "cellModeller.H"
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(Foam::multiDirRefinement, 0);
46 // * * * * * * * * * * * * * Private Statc Functions * * * * * * * * * * * * //
48 // Update refCells pattern for split cells. Note refCells is current
49 // list of cells to refine (these should all have been refined)
50 void Foam::multiDirRefinement::addCells
52 const Map<label>& splitMap,
53 List<refineCell>& refCells
56 label newRefI = refCells.size();
58 label oldSize = refCells.size();
60 refCells.setSize(newRefI + splitMap.size());
62 for (label refI = 0; refI < oldSize; refI++)
64 const refineCell& refCell = refCells[refI];
66 Map<label>::const_iterator iter = splitMap.find(refCell.cellNo());
68 if (iter == splitMap.end())
72 "multiDirRefinement::addCells(const Map<label>&"
73 ", List<refineCell>&)"
74 ) << "Problem : cannot find added cell for cell "
75 << refCell.cellNo() << abort(FatalError);
78 refCells[newRefI++] = refineCell(iter(), refCell.direction());
83 // Update vectorField for all the new cells. Takes over value of
85 void Foam::multiDirRefinement::update
87 const Map<label>& splitMap,
91 field.setSize(field.size() + splitMap.size());
93 forAllConstIter(Map<label>, splitMap, iter)
95 field[iter()] = field[iter.key()];
100 // Add added cells to labelList
101 void Foam::multiDirRefinement::addCells
103 const Map<label>& splitMap,
107 label newCellI = labels.size();
109 labels.setSize(labels.size() + splitMap.size());
111 forAllConstIter(Map<label>, splitMap, iter)
113 labels[newCellI++] = iter();
118 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
120 void Foam::multiDirRefinement::addCells
122 const primitiveMesh& mesh,
123 const Map<label>& splitMap
126 // Construct inverse addressing: from new to original cell.
127 labelList origCell(mesh.nCells(), -1);
129 forAll(addedCells_, cellI)
131 const labelList& added = addedCells_[cellI];
135 label slave = added[i];
137 if (origCell[slave] == -1)
139 origCell[slave] = cellI;
141 else if (origCell[slave] != cellI)
145 "multiDirRefinement::addCells(const primitiveMesh&"
146 ", const Map<label>&"
147 ) << "Added cell " << slave << " has two different masters:"
148 << origCell[slave] << " , " << cellI
149 << abort(FatalError);
155 forAllConstIter(Map<label>, splitMap, iter)
157 label masterI = iter.key();
158 label newCellI = iter();
160 while (origCell[masterI] != -1 && origCell[masterI] != masterI)
162 masterI = origCell[masterI];
165 if (masterI >= addedCells_.size())
169 "multiDirRefinement::addCells(const primitiveMesh&"
170 ", const Map<label>&"
171 ) << "Map of added cells contains master cell " << masterI
172 << " which is not a valid cell number" << endl
173 << "This means that the mesh is not consistent with the"
174 << " done refinement" << endl
175 << "newCell:" << newCellI << abort(FatalError);
178 labelList& added = addedCells_[masterI];
186 else if (findIndex(added, newCellI) == -1)
188 label sz = added.size();
189 added.setSize(sz + 1);
190 added[sz] = newCellI;
196 Foam::labelList Foam::multiDirRefinement::splitOffHex(const primitiveMesh& mesh)
198 const cellModel& hex = *(cellModeller::lookup("hex"));
200 const cellShapeList& cellShapes = mesh.cellShapes();
202 // Split cellLabels_ into two lists.
204 labelList nonHexLabels(cellLabels_.size());
207 labelList hexLabels(cellLabels_.size());
210 forAll(cellLabels_, i)
212 label cellI = cellLabels_[i];
214 if (cellShapes[cellI].model() == hex)
216 hexLabels[hexI++] = cellI;
220 nonHexLabels[nonHexI++] = cellI;
224 nonHexLabels.setSize(nonHexI);
226 cellLabels_.transfer(nonHexLabels);
228 hexLabels.setSize(hexI);
234 void Foam::multiDirRefinement::refineHex8
237 const labelList& hexCells,
243 Pout<< "multiDirRefinement : Refining hexes " << hexCells.size()
250 labelList(mesh.nCells(), 0), // cellLevel
251 labelList(mesh.nPoints(), 0), // pointLevel
257 mesh.facesInstance(),
258 polyMesh::meshSubDir,
264 List<refinementHistory::splitCell8>(0),
266 ) // refinement history
269 polyTopoChange meshMod(mesh);
271 labelList consistentCells
273 hexRefiner.consistentRefinement
280 // Check that consistentRefinement hasn't added cells
282 // Create count 1 for original cells
283 Map<label> hexCellSet(2*hexCells.size());
286 hexCellSet.insert(hexCells[i], 1);
290 forAll(consistentCells, i)
292 const label cellI = consistentCells[i];
294 Map<label>::iterator iter = hexCellSet.find(cellI);
296 if (iter == hexCellSet.end())
300 "multiDirRefinement::refineHex8"
301 "(polyMesh&, const labelList&, const bool)"
302 ) << "Resulting mesh would not satisfy 2:1 ratio"
303 << " when refining cell " << cellI << abort(FatalError);
311 // Check if all been visited (should always be since
312 // consistentRefinement set up to extend set.
313 forAllConstIter(Map<label>, hexCellSet, iter)
319 "multiDirRefinement::refineHex8"
320 "(polyMesh&, const labelList&, const bool)"
321 ) << "Resulting mesh would not satisfy 2:1 ratio"
322 << " when refining cell " << iter.key()
323 << abort(FatalError);
329 hexRefiner.setRefinement(consistentCells, meshMod);
331 // Change mesh, no inflation
332 autoPtr<mapPolyMesh> morphMapPtr = meshMod.changeMesh(mesh, false, true);
333 const mapPolyMesh& morphMap = morphMapPtr();
335 if (morphMap.hasMotionPoints())
337 mesh.movePoints(morphMap.preMotionPoints());
347 Pout<< "multiDirRefinement : updated mesh at time "
348 << mesh.time().timeName() << endl;
351 hexRefiner.updateMesh(morphMap);
353 // Collect all cells originating from same old cell (original + 7 extra)
355 forAll(consistentCells, i)
357 addedCells_[consistentCells[i]].setSize(8);
359 labelList nAddedCells(addedCells_.size(), 0);
361 const labelList& cellMap = morphMap.cellMap();
363 forAll(cellMap, cellI)
365 const label oldCellI = cellMap[cellI];
367 if (addedCells_[oldCellI].size())
369 addedCells_[oldCellI][nAddedCells[oldCellI]++] = cellI;
375 void Foam::multiDirRefinement::refineAllDirs
378 List<vectorField>& cellDirections,
379 const cellLooper& cellWalker,
380 undoableMeshCutter& cutter,
385 refinementIterator refiner(mesh, cutter, cellWalker, writeMesh);
387 forAll(cellDirections, dirI)
391 Pout<< "multiDirRefinement : Refining " << cellLabels_.size()
392 << " cells in direction " << dirI << endl
396 const vectorField& dirField = cellDirections[dirI];
398 // Combine cell to be cut with direction to cut in.
399 // If dirField is only one element use this for all cells.
401 List<refineCell> refCells(cellLabels_.size());
403 if (dirField.size() == 1)
405 // Uniform directions.
408 Pout<< "multiDirRefinement : Uniform refinement:"
409 << dirField[0] << endl;
412 forAll(refCells, refI)
414 label cellI = cellLabels_[refI];
416 refCells[refI] = refineCell(cellI, dirField[0]);
421 // Non uniform directions.
422 forAll(refCells, refI)
424 const label cellI = cellLabels_[refI];
426 refCells[refI] = refineCell(cellI, dirField[cellI]);
430 // Do refine mesh (multiple iterations). Remember added cells.
431 Map<label> splitMap = refiner.setRefinement(refCells);
433 // Update overall map of added cells
434 addCells(mesh, splitMap);
436 // Add added cells to list of cells to refine in next iteration
437 addCells(splitMap, cellLabels_);
439 // Update refinement direction for added cells.
440 if (dirField.size() != 1)
442 forAll(cellDirections, i)
444 update(splitMap, cellDirections[i]);
450 Pout<< "multiDirRefinement : Done refining direction " << dirI
451 << " resulting in " << cellLabels_.size() << " cells" << nl
458 void Foam::multiDirRefinement::refineFromDict
461 List<vectorField>& cellDirections,
462 const dictionary& dict,
466 // How to walk cell circumference.
467 Switch pureGeomCut(dict.lookup("geometricCut"));
469 autoPtr<cellLooper> cellWalker(NULL);
472 cellWalker.reset(new geomCellLooper(mesh));
476 cellWalker.reset(new hexCellLooper(mesh));
479 // Construct undoable refinement topology modifier.
480 //Note: undoability switched off.
481 // Might want to reconsider if needs to be possible. But then can always
482 // use other constructor.
483 undoableMeshCutter cutter(mesh, false);
485 refineAllDirs(mesh, cellDirections, cellWalker(), cutter, writeMesh);
490 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
492 // Construct from dictionary
493 Foam::multiDirRefinement::multiDirRefinement
496 const labelList& cellLabels, // list of cells to refine
497 const dictionary& dict
500 cellLabels_(cellLabels),
501 addedCells_(mesh.nCells())
503 Switch useHex(dict.lookup("useHexTopology"));
505 Switch writeMesh(dict.lookup("writeMesh"));
507 wordList dirNames(dict.lookup("directions"));
509 if (useHex && dirNames.size() == 3)
511 // Filter out hexes from cellLabels_
512 labelList hexCells(splitOffHex(mesh));
514 refineHex8(mesh, hexCells, writeMesh);
517 label nRemainingCells = cellLabels_.size();
519 reduce(nRemainingCells, sumOp<label>());
521 if (nRemainingCells > 0)
523 // Any cells to refine using meshCutter
525 // Determine directions for every cell. Can either be uniform
526 // (size = 1) or non-uniform (one vector per cell)
527 directions cellDirections(mesh, dict);
529 refineFromDict(mesh, cellDirections, dict, writeMesh);
534 // Construct from directionary and directions to refine.
535 Foam::multiDirRefinement::multiDirRefinement
538 const labelList& cellLabels, // list of cells to refine
539 const List<vectorField>& cellDirs, // Explicitly provided directions
540 const dictionary& dict
543 cellLabels_(cellLabels),
544 addedCells_(mesh.nCells())
546 Switch useHex(dict.lookup("useHexTopology"));
548 Switch writeMesh(dict.lookup("writeMesh"));
550 wordList dirNames(dict.lookup("directions"));
552 if (useHex && dirNames.size() == 3)
554 // Filter out hexes from cellLabels_
555 labelList hexCells(splitOffHex(mesh));
557 refineHex8(mesh, hexCells, writeMesh);
560 label nRemainingCells = cellLabels_.size();
562 reduce(nRemainingCells, sumOp<label>());
564 if (nRemainingCells > 0)
566 // Any cells to refine using meshCutter
568 // Working copy of cells to refine
569 List<vectorField> cellDirections(cellDirs);
571 refineFromDict(mesh, cellDirections, dict, writeMesh);
576 // Construct from components. Implies meshCutter since directions provided.
577 Foam::multiDirRefinement::multiDirRefinement
580 undoableMeshCutter& cutter, // actual mesh modifier
581 const cellLooper& cellWalker, // how to cut a single cell with
583 const labelList& cellLabels, // list of cells to refine
584 const List<vectorField>& cellDirs,
585 const bool writeMesh // write intermediate meshes
588 cellLabels_(cellLabels),
589 addedCells_(mesh.nCells())
591 // Working copy of cells to refine
592 List<vectorField> cellDirections(cellDirs);
594 refineAllDirs(mesh, cellDirections, cellWalker, cutter, writeMesh);
598 // ************************************************************************* //