refinementIterator.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "refinementIterator.H"
27 #include "polyMesh.H"
28 #include "Time.H"
29 #include "refineCell.H"
30 #include "undoableMeshCutter.H"
31 #include "polyTopoChange.H"
32 #include "polyTopoChangeMap.H"
33 #include "cellCuts.H"
34 #include "OFstream.H"
35 #include "meshTools.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 defineTypeNameAndDebug(refinementIterator, 0);
42 }
43 
44 
45 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
46 
47 // Construct from components
49 (
50  polyMesh& mesh,
51  undoableMeshCutter& meshRefiner,
52  const cellLooper& cellWalker,
53  const bool writeMesh
54 )
55 :
56  edgeVertex(mesh),
57  mesh_(mesh),
58  meshRefiner_(meshRefiner),
59  cellWalker_(cellWalker),
60  writeMesh_(writeMesh)
61 {}
62 
63 
64 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
65 
67 {}
68 
69 
70 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
71 
73 (
74  const List<refineCell>& refCells
75 )
76 {
77  Map<label> addedCells(2*refCells.size());
78 
79  Time& runTime = const_cast<Time&>(mesh_.time());
80 
81  label nRefCells = refCells.size();
82 
83  label oldRefCells = -1;
84 
85  // Operate on copy.
86  List<refineCell> currentRefCells(refCells);
87 
88  bool stop = false;
89 
90  do
91  {
92  if (writeMesh_)
93  {
94  // Need different times to write meshes.
95  runTime++;
96  }
97 
98  polyTopoChange meshMod(mesh_);
99 
100  if (debug)
101  {
102  Pout<< "refinementIterator : refining "
103  << currentRefCells.size() << " cells." << endl;
104  }
105 
106  // Determine cut pattern.
107  cellCuts cuts(mesh_, cellWalker_, currentRefCells);
108 
109  label nCuts = cuts.nLoops();
110  reduce(nCuts, sumOp<label>());
111 
112  if (nCuts == 0)
113  {
114  if (debug)
115  {
116  Pout<< "refinementIterator : exiting iteration since no valid"
117  << " loops found for " << currentRefCells.size()
118  << " cells" << endl;
119 
120 
121  fileName cutsFile("failedCuts_" + runTime.timeName() + ".obj");
122 
123  Pout<< "Writing cuts for time " << runTime.timeName()
124  << " to " << cutsFile << endl;
125 
126  OFstream cutsStream(cutsFile);
127 
128 
129  labelList refCellsDebug(currentRefCells.size());
130  forAll(currentRefCells, i)
131  {
132  refCellsDebug[i] = currentRefCells[i].cellNo();
133  }
135  (
136  cutsStream,
137  mesh().cells(),
138  mesh().faces(),
139  mesh().points(),
140  refCellsDebug
141  );
142  }
143 
144  break;
145  }
146 
147  if (debug)
148  {
149  fileName cutsFile("cuts_" + runTime.timeName() + ".obj");
150 
151  Pout<< "Writing cuts for time " << runTime.timeName()
152  << " to " << cutsFile << endl;
153 
154  OFstream cutsStream(cutsFile);
155  cuts.writeOBJ(cutsStream);
156  }
157 
158 
159  // Insert mesh refinement into polyTopoChange.
160  meshRefiner_.setRefinement(cuts, meshMod);
161 
162 
163  //
164  // Do all changes
165  //
166 
168  (
169  mesh_,
170  false
171  );
172 
173  // Move mesh (since morphing does not do this)
174  if (map().hasMotionPoints())
175  {
176  mesh_.movePoints(map().preMotionPoints());
177  }
178 
179  // Update stored refinement pattern
180  meshRefiner_.topoChange(map());
181 
182  // Write resulting mesh
183  if (writeMesh_)
184  {
185  if (debug)
186  {
187  Pout<< "Writing refined polyMesh to time "
188  << runTime.timeName() << endl;
189  }
190 
191  mesh_.write();
192  }
193 
194  // Update currentRefCells for new cell numbers. Use helper function
195  // in meshCutter class.
196  updateLabels
197  (
198  map->reverseCellMap(),
199  currentRefCells
200  );
201 
202  // Update addedCells for new cell numbers
203  updateLabels
204  (
205  map->reverseCellMap(),
206  addedCells
207  );
208 
209  // Get all added cells from cellCutter (already in new numbering
210  // from meshRefiner.topoChange call) and add to global list of added
211  const Map<label>& addedNow = meshRefiner_.addedCells();
212 
213  forAllConstIter(Map<label>, addedNow, iter)
214  {
215  if (!addedCells.insert(iter.key(), iter()))
216  {
218  << "Master cell " << iter.key()
219  << " already has been refined" << endl
220  << "Added cell:" << iter() << abort(FatalError);
221  }
222  }
223 
224 
225  // Get failed refinement in new cell numbering and reconstruct input
226  // to the meshRefiner. Is done by removing all refined cells from
227  // current list of cells to refine.
228 
229  // Update refCells for new cell numbers.
230  updateLabels
231  (
232  map->reverseCellMap(),
233  currentRefCells
234  );
235 
236  // Pack refCells acc. to refined status
237  nRefCells = 0;
238 
239  forAll(currentRefCells, refI)
240  {
241  const refineCell& refCell = currentRefCells[refI];
242 
243  if (!addedNow.found(refCell.cellNo()))
244  {
245  if (nRefCells != refI)
246  {
247  currentRefCells[nRefCells++] =
248  refineCell
249  (
250  refCell.cellNo(),
251  refCell.direction()
252  );
253  }
254  }
255  }
256 
257  oldRefCells = currentRefCells.size();
258 
259  currentRefCells.setSize(nRefCells);
260 
261  if (debug)
262  {
263  Pout<< endl;
264  }
265 
266  // Stop only if all finished or all can't refine any further.
267  stop = (nRefCells == 0) || (nRefCells == oldRefCells);
268  reduce(stop, andOp<bool>());
269  }
270  while (!stop);
271 
272 
273  if (returnReduce((nRefCells == oldRefCells), andOp<bool>()))
274  {
276  << "stopped refining."
277  << "Did not manage to refine a single cell" << endl
278  << "Wanted :" << oldRefCells << endl;
279  }
280 
281  return addedCells;
282 }
283 
284 
285 
286 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
autoPtr< polyTopoChangeMap > changeMesh(polyMesh &mesh, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
virtual Ostream & write(const char)=0
Write character.
A class for handling file names.
Definition: fileName.H:79
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
Map< label > setRefinement(const List< refineCell > &)
Try to refine cells in given direction. Constructs intermediate.
Output to file stream.
Definition: OFstream.H:82
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Abstract base class. Concrete implementations know how to cut a cell (i.e. determine a loop around th...
Definition: cellLooper.H:69
The main refinement handler. Gets cellCuts which is structure that describes which cells are to be cu...
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
fvMesh & mesh
Description of cuts across cells.
Definition: cellCuts.H:108
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
const vector & direction() const
Definition: refineCell.H:87
const cellShapeList & cells
const pointField & points
Combines edge or vertex in single label. Used to specify cuts across cell circumference.
Definition: edgeVertex.H:52
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:56
errorManip< error > abort(error &err)
Definition: errorManip.H:131
defineTypeNameAndDebug(combustionModel, 0)
const labelList & reverseCellMap() const
Reverse cell map.
label cellNo() const
Definition: refineCell.H:82
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void setSize(const label)
Reset size of List.
Definition: List.C:281
label nLoops() const
Number of valid cell loops.
Definition: cellCuts.H:569
#define WarningInFunction
Report a warning using Foam::Warning.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Direct mesh changes based on v1.3 polyTopoChange syntax.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:76
refinementIterator(polyMesh &mesh, undoableMeshCutter &meshRefiner, const cellLooper &cellWalker, const bool writeMesh=false)
Construct from mesh, refinementEngine and cell walking routine.
Namespace for OpenFOAM.
A HashTable to objects of type <T> with a label key.
Definition: Map.H:49