Loading...
Searching...
No Matches
multiDirRefinement.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2015-2024 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "multiDirRefinement.H"
30#include "polyMesh.H"
31#include "Time.H"
32#include "undoableMeshCutter.H"
33#include "hexCellLooper.H"
34#include "geomCellLooper.H"
35#include "directions.H"
36#include "hexRef8.H"
37#include "mapPolyMesh.H"
39#include "cellModel.H"
40
41// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42
43namespace Foam
44{
46}
47
48
49// * * * * * * * * * * * * * Private Statc Functions * * * * * * * * * * * * //
50
51// Update refCells pattern for split cells. Note refCells is current
52// list of cells to refine (these should all have been refined)
53void Foam::multiDirRefinement::addCells
54(
55 const Map<label>& splitMap,
56 List<refineCell>& refCells
57)
58{
59 label newRefI = refCells.size();
60
61 label oldSize = refCells.size();
62
63 refCells.setSize(newRefI + splitMap.size());
64
65 for (label refI = 0; refI < oldSize; refI++)
66 {
67 const refineCell& refCell = refCells[refI];
68
69 const auto iter = splitMap.cfind(refCell.cellNo());
70
71 if (!iter.good())
72 {
74 << "Problem : cannot find added cell for cell "
75 << refCell.cellNo() << endl
76 << abort(FatalError);
77 }
78
79 refCells[newRefI++] = refineCell(iter.val(), refCell.direction());
80 }
81}
82
83
84// Update vectorField for all the new cells. Takes over value of
85// original cell.
86void Foam::multiDirRefinement::update
87(
88 const Map<label>& splitMap,
90)
91{
92 field.setSize(field.size() + splitMap.size());
93
94 forAllConstIters(splitMap, iter)
95 {
96 field[iter.val()] = field[iter.key()];
97 }
98}
99
100
101// Add added cells to labelList
102void Foam::multiDirRefinement::addCells
103(
104 const Map<label>& splitMap,
105 labelList& labels
106)
107{
108 label newCelli = labels.size();
109
110 labels.setSize(labels.size() + splitMap.size());
111
112 forAllConstIters(splitMap, iter)
113 {
114 labels[newCelli++] = iter.val();
115 }
116}
117
118
119// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
120
121void Foam::multiDirRefinement::addCells
122(
123 const primitiveMesh& mesh,
124 const Map<label>& splitMap
125)
126{
127 // Construct inverse addressing: from new to original cell.
128 labelList origCell(mesh.nCells(), -1);
129
130 forAll(addedCells_, celli)
131 {
132 const labelList& added = addedCells_[celli];
133
134 forAll(added, i)
135 {
136 label slave = added[i];
137
138 if (origCell[slave] == -1)
139 {
140 origCell[slave] = celli;
141 }
142 else if (origCell[slave] != celli)
143 {
145 << "Added cell " << slave << " has two different masters:"
146 << origCell[slave] << " , " << celli
147 << abort(FatalError);
148 }
149 }
150 }
151
152
153 forAllConstIters(splitMap, iter)
154 {
155 label masterI = iter.key();
156 const label newCelli = iter.val();
157
158 while (origCell[masterI] != -1 && origCell[masterI] != masterI)
159 {
160 masterI = origCell[masterI];
161 }
162
163 if (masterI >= addedCells_.size())
164 {
166 << "Map of added cells contains master cell " << masterI
167 << " which is not a valid cell number" << endl
168 << "This means that the mesh is not consistent with the"
169 << " done refinement" << endl
170 << "newCell:" << newCelli << abort(FatalError);
171 }
172
173 labelList& added = addedCells_[masterI];
174
175 if (added.empty())
176 {
177 added.setSize(2);
178 added[0] = masterI;
179 added[1] = newCelli;
180 }
181 else if (!added.found(newCelli))
182 {
183 const label sz = added.size();
184 added.setSize(sz + 1);
185 added[sz] = newCelli;
186 }
187 }
188}
189
190
191Foam::labelList Foam::multiDirRefinement::splitOffHex(const primitiveMesh& mesh)
192{
194
196
197 // Split cellLabels_ into two lists.
198
199 labelList nonHexLabels(cellLabels_.size());
200 label nonHexI = 0;
201
202 labelList hexLabels(cellLabels_.size());
203 label hexI = 0;
204
205 forAll(cellLabels_, i)
206 {
207 label celli = cellLabels_[i];
208
209 if (cellShapes[celli].model() == hex)
210 {
211 hexLabels[hexI++] = celli;
212 }
213 else
214 {
215 nonHexLabels[nonHexI++] = celli;
216 }
217 }
218
219 nonHexLabels.setSize(nonHexI);
220
221 cellLabels_.transfer(nonHexLabels);
222
223 hexLabels.setSize(hexI);
224
225 return hexLabels;
226}
227
228
229void Foam::multiDirRefinement::refineHex8
230(
231 polyMesh& mesh,
232 const labelList& hexCells,
233 const bool writeMesh
234)
235{
236 if (debug)
237 {
238 Pout<< "multiDirRefinement : Refining hexes " << hexCells.size()
239 << endl;
240 }
241
242 hexRef8 hexRefiner
243 (
244 mesh,
245 labelList(mesh.nCells(), Zero), // cellLevel
246 labelList(mesh.nPoints(), Zero), // pointLevel
248 (
250 (
251 "refinementHistory",
254 mesh,
258 ),
260 labelList(),
261 false
262 ) // refinement history
263 );
264
265 polyTopoChange meshMod(mesh);
266
267 labelList consistentCells
268 (
269 hexRefiner.consistentRefinement
270 (
271 hexCells,
272 true // buffer layer
273 )
274 );
275
276 // Check that consistentRefinement hasn't added cells
277 {
278 // Create count 1 for original cells
279 Map<label> hexCellSet(2*hexCells.size());
280 for (const label celli : hexCells)
281 {
282 hexCellSet.insert(celli, 1);
283 }
284
285 // Increment count
286 for (const label celli : consistentCells)
287 {
288 auto iter = hexCellSet.find(celli);
289
290 if (iter.good())
291 {
292 iter.val() = 2;
293 }
294 else
295 {
297 << "Resulting mesh would not satisfy 2:1 ratio"
298 << " when refining cell " << celli << abort(FatalError);
299 }
300 }
301
302 // Check if all been visited (should always be since
303 // consistentRefinement set up to extend set.
304 forAllConstIters(hexCellSet, iter)
305 {
306 if (iter.val() != 2)
307 {
309 << "Resulting mesh would not satisfy 2:1 ratio"
310 << " when refining cell " << iter.key()
311 << abort(FatalError);
312 }
313 }
314 }
315
316
317 hexRefiner.setRefinement(consistentCells, meshMod);
318
319 // Change mesh, no inflation
320 autoPtr<mapPolyMesh> morphMapPtr = meshMod.changeMesh(mesh, false, true);
321 const mapPolyMesh& morphMap = morphMapPtr();
322
323 if (morphMap.hasMotionPoints())
324 {
325 mesh.movePoints(morphMap.preMotionPoints());
326 }
327
328 if (writeMesh)
329 {
330 mesh.write();
331 }
332
333 if (debug)
334 {
335 Pout<< "multiDirRefinement : updated mesh at time "
336 << mesh.time().timeName() << endl;
337 }
338
339 hexRefiner.updateMesh(morphMap);
340
341 // Collect all cells originating from same old cell (original + 7 extra)
342
343 forAll(consistentCells, i)
344 {
345 addedCells_[consistentCells[i]].setSize(8);
346 }
347 labelList nAddedCells(addedCells_.size(), Zero);
348
349 const labelList& cellMap = morphMap.cellMap();
350
351 forAll(cellMap, celli)
352 {
353 const label oldCelli = cellMap[celli];
354
355 if (addedCells_[oldCelli].size())
356 {
357 addedCells_[oldCelli][nAddedCells[oldCelli]++] = celli;
358 }
359 }
360}
361
362
363void Foam::multiDirRefinement::refineAllDirs
364(
365 polyMesh& mesh,
366 List<vectorField>& cellDirections,
367 const cellLooper& cellWalker,
368 undoableMeshCutter& cutter,
369 const bool writeMesh
370)
371{
372 // Iterator
373 refinementIterator refiner(mesh, cutter, cellWalker, writeMesh);
374
375 forAll(cellDirections, dirI)
376 {
377 if (debug)
378 {
379 Pout<< "multiDirRefinement : Refining " << cellLabels_.size()
380 << " cells in direction " << dirI << endl
381 << endl;
382 }
383
384 const vectorField& dirField = cellDirections[dirI];
385
386 // Combine cell to be cut with direction to cut in.
387 // If dirField is only one element use this for all cells.
388
389 List<refineCell> refCells(cellLabels_.size());
390
391 if (dirField.size() == 1)
392 {
393 // Uniform directions.
394 if (debug)
395 {
396 Pout<< "multiDirRefinement : Uniform refinement:"
397 << dirField[0] << endl;
398 }
399
400 forAll(refCells, refI)
401 {
402 const label celli = cellLabels_[refI];
403
404 refCells[refI] = refineCell(celli, dirField[0]);
405 }
406 }
407 else
408 {
409 // Non uniform directions.
410 forAll(refCells, refI)
411 {
412 const label celli = cellLabels_[refI];
413
414 refCells[refI] = refineCell(celli, dirField[celli]);
415 }
416 }
417
418 // Do refine mesh (multiple iterations). Remember added cells.
419 Map<label> splitMap = refiner.setRefinement(refCells);
420
421 // Update overall map of added cells
422 addCells(mesh, splitMap);
423
424 // Add added cells to list of cells to refine in next iteration
425 addCells(splitMap, cellLabels_);
426
427 // Update refinement direction for added cells.
428 if (dirField.size() != 1)
429 {
430 forAll(cellDirections, i)
431 {
432 update(splitMap, cellDirections[i]);
433 }
434 }
435
436 if (debug)
437 {
438 Pout<< "multiDirRefinement : Done refining direction " << dirI
439 << " resulting in " << cellLabels_.size() << " cells" << nl
440 << endl;
441 }
442 }
443}
444
445
446void Foam::multiDirRefinement::refineFromDict
447(
448 polyMesh& mesh,
449 List<vectorField>& cellDirections,
450 const dictionary& dict,
451 const bool writeMesh
452)
453{
454 // How to walk cell circumference.
455 const bool pureGeomCut(dict.get<bool>("geometricCut"));
456
457 autoPtr<cellLooper> cellWalker;
458 if (pureGeomCut)
459 {
460 cellWalker.reset(new geomCellLooper(mesh));
461 }
462 else
463 {
464 cellWalker.reset(new hexCellLooper(mesh));
465 }
466
467 // Construct undoable refinement topology modifier.
468 //Note: undoability switched off.
469 // Might want to reconsider if needs to be possible. But then can always
470 // use other constructor.
471 undoableMeshCutter cutter(mesh, false);
472
473 refineAllDirs(mesh, cellDirections, cellWalker(), cutter, writeMesh);
475
476
477
478// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
479
480// Construct from dictionary
481Foam::multiDirRefinement::multiDirRefinement
482(
483 polyMesh& mesh,
484 const labelList& cellLabels, // list of cells to refine
485 const dictionary& dict
486)
487:
488 cellLabels_(cellLabels),
489 addedCells_(mesh.nCells())
490{
491 const bool useHex(dict.get<bool>("useHexTopology"));
492
493 const bool writeMesh(dict.get<bool>("writeMesh"));
494
495 const wordList dirNames(dict.get<wordList>("directions"));
496
497 if (useHex && dirNames.size() == 3)
498 {
499 // Filter out hexes from cellLabels_
500 labelList hexCells(splitOffHex(mesh));
501
502 refineHex8(mesh, hexCells, writeMesh);
503 }
504
505 if (returnReduceOr(cellLabels_.size()))
506 {
507 // Any cells to refine using meshCutter
508
509 // Determine directions for every cell. Can either be uniform
510 // (size = 1) or non-uniform (one vector per cell)
511 directions cellDirections(mesh, dict);
513 refineFromDict(mesh, cellDirections, dict, writeMesh);
514 }
515}
516
517
518// Construct from dictionary and directions to refine.
519Foam::multiDirRefinement::multiDirRefinement
520(
521 polyMesh& mesh,
522 const labelList& cellLabels, // list of cells to refine
523 const List<vectorField>& cellDirs, // Explicitly provided directions
524 const dictionary& dict
525)
526:
527 cellLabels_(cellLabels),
528 addedCells_(mesh.nCells())
529{
530 const bool useHex(dict.get<bool>("useHexTopology"));
531
532 const bool writeMesh(dict.get<bool>("writeMesh"));
533
534 const wordList dirNames(dict.get<wordList>("directions"));
535
536 if (useHex && dirNames.size() == 3)
537 {
538 // Filter out hexes from cellLabels_
539 labelList hexCells(splitOffHex(mesh));
540
541 refineHex8(mesh, hexCells, writeMesh);
542 }
543
544 if (returnReduceOr(cellLabels_.size()))
545 {
546 // Any cells to refine using meshCutter
547
548 // Working copy of cells to refine
549 List<vectorField> cellDirections(cellDirs);
551 refineFromDict(mesh, cellDirections, dict, writeMesh);
552 }
553}
554
555
556// Construct from components. Implies meshCutter since directions provided.
557Foam::multiDirRefinement::multiDirRefinement
558(
559 polyMesh& mesh,
560 undoableMeshCutter& cutter, // actual mesh modifier
561 const cellLooper& cellWalker, // how to cut a single cell with
562 // a plane
563 const labelList& cellLabels, // list of cells to refine
564 const List<vectorField>& cellDirs,
565 const bool writeMesh // write intermediate meshes
566)
567:
568 cellLabels_(cellLabels),
569 addedCells_(mesh.nCells())
570{
571 // Working copy of cells to refine
572 List<vectorField> cellDirections(cellDirs);
573
574 refineAllDirs(mesh, cellDirections, cellWalker, cutter, writeMesh);
575}
576
577
578// ************************************************************************* //
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition Time.C:714
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
Abstract base class. Concrete implementations know how to cut a cell (i.e. determine a loop around th...
Definition cellLooper.H:71
Maps a geometry to a set of cell primitives.
Definition cellModel.H:73
static const cellModel & ref(const modelType model)
Look up reference to cellModel by enumeration. Fatal on failure.
Definition cellModels.C:150
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
Set of directions for each cell in the mesh. Either uniform and size=1 or one set of directions per c...
Definition directions.H:67
const Time & time() const
Return the top-level database.
Definition fvMesh.H:360
virtual bool write(const bool writeOnProc=true) const
Write mesh using IO settings from time.
Definition fvMesh.C:1068
virtual void movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition fvMesh.C:884
Implementation of cellLooper. Does pure geometric cut through cell.
Implementation of cellLooper.
Refinement of (split) hexes using polyTopoChange.
Definition hexRef8.H:63
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Does multiple pass refinement to refine cells in multiple directions.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition polyMesh.C:844
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh").
Definition polyMesh.H:411
Direct mesh changes based on v1.3 polyTopoChange syntax.
Cell-face mesh analysis engine.
const cellShapeList & cellShapes() const
Return cell shapes.
label nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
Container with cells to refine. Refinement given as single direction.
Definition refineCell.H:53
All refinement history. Used in unrefinement.
Utility class to do iterating meshCutter until all requests satisfied.
The main refinement handler. Gets cellCuts which is structure that describes which cells are to be cu...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
rDeltaTY field()
mesh update()
cellShapeList cellShapes
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< label > labelList
A List of labels.
Definition List.H:62
IOstream & hex(IOstream &io)
Definition IOstream.H:579
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
errorManip< error > abort(error &err)
Definition errorManip.H:139
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< cellShape > cellShapeList
List of cellShape.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235