FreeFOAM The Cross-Platform CFD Toolkit
refinementIterator.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 | Copyright (C) 1991-2010 OpenCFD Ltd.
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 <OpenFOAM/polyMesh.H>
28 #include <OpenFOAM/Time.H>
29 #include <dynamicMesh/refineCell.H>
32 #include <OpenFOAM/mapPolyMesh.H>
33 #include <dynamicMesh/cellCuts.H>
34 #include <OpenFOAM/OFstream.H>
35 #include <meshTools/meshTools.H>
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 
42 defineTypeNameAndDebug(refinementIterator, 0);
43 
44 }
45 
46 
47 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
48 
49 // Construct from components
51 (
52  polyMesh& mesh,
53  undoableMeshCutter& meshRefiner,
54  const cellLooper& cellWalker,
55  const bool writeMesh
56 )
57 :
58  edgeVertex(mesh),
59  mesh_(mesh),
60  meshRefiner_(meshRefiner),
61  cellWalker_(cellWalker),
62  writeMesh_(writeMesh)
63 {}
64 
65 
66 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
67 
69 {}
70 
71 
72 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
73 
75 (
76  const List<refineCell>& refCells
77 )
78 {
79  Map<label> addedCells(2*refCells.size());
80 
81  Time& runTime = const_cast<Time&>(mesh_.time());
82 
83  label nRefCells = refCells.size();
84 
85  label oldRefCells = -1;
86 
87  // Operate on copy.
88  List<refineCell> currentRefCells(refCells);
89 
90  bool stop = false;
91 
92  do
93  {
94  if (writeMesh_)
95  {
96  // Need different times to write meshes.
97  runTime++;
98  }
99 
100  polyTopoChange meshMod(mesh_);
101 
102  if (debug)
103  {
104  Pout<< "refinementIterator : refining "
105  << currentRefCells.size() << " cells." << endl;
106  }
107 
108  // Determine cut pattern.
109  cellCuts cuts(mesh_, cellWalker_, currentRefCells);
110 
111  label nCuts = cuts.nLoops();
112  reduce(nCuts, sumOp<label>());
113 
114  if (nCuts == 0)
115  {
116  if (debug)
117  {
118  Pout<< "refinementIterator : exiting iteration since no valid"
119  << " loops found for " << currentRefCells.size()
120  << " cells" << endl;
121 
122 
123  fileName cutsFile("failedCuts_" + runTime.timeName() + ".obj");
124 
125  Pout<< "Writing cuts for time " << runTime.timeName()
126  << " to " << cutsFile << endl;
127 
128  OFstream cutsStream(cutsFile);
129 
130 
131  labelList refCells(currentRefCells.size());
132  forAll(currentRefCells, i)
133  {
134  refCells[i] = currentRefCells[i].cellNo();
135  }
137  (
138  cutsStream,
139  mesh().cells(),
140  mesh().faces(),
141  mesh().points(),
142  refCells
143  );
144  }
145 
146  break;
147  }
148 
149  if (debug)
150  {
151  fileName cutsFile("cuts_" + runTime.timeName() + ".obj");
152 
153  Pout<< "Writing cuts for time " << runTime.timeName()
154  << " to " << cutsFile << endl;
155 
156  OFstream cutsStream(cutsFile);
157  cuts.writeOBJ(cutsStream);
158  }
159 
160 
161  // Insert mesh refinement into polyTopoChange.
162  meshRefiner_.setRefinement(cuts, meshMod);
163 
164 
165  //
166  // Do all changes
167  //
168 
169  autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh
170  (
171  mesh_,
172  false
173  );
174 
175  // Move mesh (since morphing does not do this)
176  if (morphMap().hasMotionPoints())
177  {
178  mesh_.movePoints(morphMap().preMotionPoints());
179  }
180 
181  // Update stored refinement pattern
182  meshRefiner_.updateMesh(morphMap());
183 
184  // Write resulting mesh
185  if (writeMesh_)
186  {
187  if (debug)
188  {
189  Pout<< "Writing refined polyMesh to time "
190  << runTime.timeName() << endl;
191  }
192 
193  mesh_.write();
194  }
195 
196  // Update currentRefCells for new cell numbers. Use helper function
197  // in meshCutter class.
198  updateLabels
199  (
200  morphMap->reverseCellMap(),
201  currentRefCells
202  );
203 
204  // Update addedCells for new cell numbers
205  updateLabels
206  (
207  morphMap->reverseCellMap(),
208  addedCells
209  );
210 
211  // Get all added cells from cellCutter (already in new numbering
212  // from meshRefiner.updateMesh call) and add to global list of added
213  const Map<label>& addedNow = meshRefiner_.addedCells();
214 
215  for
216  (
217  Map<label>::const_iterator iter = addedNow.begin();
218  iter != addedNow.end();
219  ++iter
220  )
221  {
222  if (!addedCells.insert(iter.key(), iter()))
223  {
224  FatalErrorIn("refinementIterator")
225  << "Master cell " << iter.key()
226  << " already has been refined" << endl
227  << "Added cell:" << iter() << abort(FatalError);
228  }
229  }
230 
231 
232  // Get failed refinement in new cell numbering and reconstruct input
233  // to the meshRefiner. Is done by removing all refined cells from
234  // current list of cells to refine.
235 
236  // Update refCells for new cell numbers.
237  updateLabels
238  (
239  morphMap->reverseCellMap(),
240  currentRefCells
241  );
242 
243  // Pack refCells acc. to refined status
244  nRefCells = 0;
245 
246  forAll(currentRefCells, refI)
247  {
248  const refineCell& refCell = currentRefCells[refI];
249 
250  if (!addedNow.found(refCell.cellNo()))
251  {
252  if (nRefCells != refI)
253  {
254  currentRefCells[nRefCells++] =
255  refineCell
256  (
257  refCell.cellNo(),
258  refCell.direction()
259  );
260  }
261  }
262  }
263 
264  oldRefCells = currentRefCells.size();
265 
266  currentRefCells.setSize(nRefCells);
267 
268  if (debug)
269  {
270  Pout<< endl;
271  }
272 
273  // Stop only if all finished or all can't refine any further.
274  stop = (nRefCells == 0) || (nRefCells == oldRefCells);
275  reduce(stop, andOp<bool>());
276  }
277  while (!stop);
278 
279 
280  if (nRefCells == oldRefCells)
281  {
282  WarningIn("refinementIterator")
283  << "stopped refining."
284  << "Did not manage to refine a single cell" << endl
285  << "Wanted :" << oldRefCells << endl;
286  }
287 
288  return addedCells;
289 }
290 
291 
292 
293 // ************************ vim: set sw=4 sts=4 et: ************************ //