removeCells.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) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
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 "removeCells.H"
27 #include "polyMesh.H"
28 #include "polyTopoChange.H"
29 #include "polyRemoveCell.H"
30 #include "polyRemoveFace.H"
31 #include "polyModifyFace.H"
32 #include "polyRemovePoint.H"
33 #include "syncTools.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(removeCells, 0);
40 }
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
45 (
46  const labelList& f,
47  labelList& nUsage
48 )
49 {
50  forAll(f, fp)
51  {
52  nUsage[f[fp]]--;
53  }
54 }
55 
56 
57 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
58 
60 (
61  const polyMesh& mesh,
62  const bool syncPar
63 )
64 :
65  mesh_(mesh),
66  syncPar_(syncPar)
67 {}
68 
69 
70 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
71 
73 (
74  const labelList& cellLabels
75 ) const
76 {
77  // Create list of cells to be removed
78  boolList removedCell(mesh_.nCells(), false);
79 
80  // Go from labelList of cells-to-remove to a boolList.
81  forAll(cellLabels, i)
82  {
83  removedCell[cellLabels[i]] = true;
84  }
85 
86 
87  const labelList& faceOwner = mesh_.faceOwner();
88  const labelList& faceNeighbour = mesh_.faceNeighbour();
89 
90  // Count cells using face.
91  labelList nCellsUsingFace(mesh_.nFaces(), 0);
92 
93  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
94  {
95  label own = faceOwner[faceI];
96  label nei = faceNeighbour[faceI];
97 
98  if (!removedCell[own])
99  {
100  nCellsUsingFace[faceI]++;
101  }
102  if (!removedCell[nei])
103  {
104  nCellsUsingFace[faceI]++;
105  }
106  }
107 
108  for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
109  {
110  label own = faceOwner[faceI];
111 
112  if (!removedCell[own])
113  {
114  nCellsUsingFace[faceI]++;
115  }
116  }
117 
118  // Coupled faces: add number of cells using face across couple.
119  {
120  // Note cyclics done always, parallel bits only done if syncPar_
121 
122  SubList<label> bndValues
123  (
124  nCellsUsingFace,
125  mesh_.nFaces()-mesh_.nInternalFaces(),
126  mesh_.nInternalFaces()
127  );
128 
129  syncTools::syncBoundaryFaceList
130  (
131  mesh_,
132  bndValues,
133  plusEqOp<label>(),
135  syncPar_
136  );
137  }
138 
139  // Now nCellsUsingFace:
140  // 0 : internal face whose both cells get deleted
141  // boundary face whose all cells get deleted
142  // 1 : internal face that gets exposed
143  // unaffected (uncoupled) boundary face
144  // coupled boundary face that gets exposed ('uncoupled')
145  // 2 : unaffected internal face
146  // unaffected coupled boundary face
147 
148  DynamicList<label> exposedFaces(mesh_.nFaces()/10);
149 
150  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
151  {
152  if (nCellsUsingFace[faceI] == 1)
153  {
154  exposedFaces.append(faceI);
155  }
156  }
157 
158  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
159 
160  forAll(patches, patchI)
161  {
162  const polyPatch& pp = patches[patchI];
163 
164  if (pp.coupled())
165  {
166  label faceI = pp.start();
167 
168  forAll(pp, i)
169  {
170  label own = faceOwner[faceI];
171 
172  if (nCellsUsingFace[faceI] == 1 && !removedCell[own])
173  {
174  // My owner not removed but other side is so has to become
175  // normal, uncoupled, boundary face
176  exposedFaces.append(faceI);
177  }
178 
179  faceI++;
180  }
181  }
182  }
183 
184  return exposedFaces.shrink();
185 }
186 
187 
189 (
190  const labelList& cellLabels,
191  const labelList& exposedFaceLabels,
192  const labelList& exposedPatchIDs,
193  polyTopoChange& meshMod
194 ) const
195 {
196  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
197 
198  if (exposedFaceLabels.size() != exposedPatchIDs.size())
199  {
201  << "Size of exposedFaceLabels " << exposedFaceLabels.size()
202  << " differs from size of exposedPatchIDs "
203  << exposedPatchIDs.size()
204  << abort(FatalError);
205  }
206 
207  // List of new patchIDs
208  labelList newPatchID(mesh_.nFaces(), -1);
209 
210  forAll(exposedFaceLabels, i)
211  {
212  label patchI = exposedPatchIDs[i];
213 
214  if (patchI < 0 || patchI >= patches.size())
215  {
217  << "Invalid patch " << patchI
218  << " for exposed face " << exposedFaceLabels[i] << endl
219  << "Valid patches 0.." << patches.size()-1
220  << abort(FatalError);
221  }
222 
223  if (patches[patchI].coupled())
224  {
226  << "Trying to put exposed face " << exposedFaceLabels[i]
227  << " into a coupled patch : " << patches[patchI].name()
228  << endl
229  << "This is illegal."
230  << abort(FatalError);
231  }
232 
233  newPatchID[exposedFaceLabels[i]] = patchI;
234  }
235 
236 
237  // Create list of cells to be removed
238  boolList removedCell(mesh_.nCells(), false);
239 
240  // Go from labelList of cells-to-remove to a boolList and remove all
241  // cells mentioned.
242  forAll(cellLabels, i)
243  {
244  label cellI = cellLabels[i];
245 
246  removedCell[cellI] = true;
247 
248  //Pout<< "Removing cell " << cellI
249  // << " cc:" << mesh_.cellCentres()[cellI] << endl;
250 
251  meshMod.setAction(polyRemoveCell(cellI));
252  }
253 
254 
255  // Remove faces that are no longer used. Modify faces that
256  // are used by one cell only.
257 
258  const faceList& faces = mesh_.faces();
259  const labelList& faceOwner = mesh_.faceOwner();
260  const labelList& faceNeighbour = mesh_.faceNeighbour();
261  const faceZoneMesh& faceZones = mesh_.faceZones();
262 
263  // Count starting number of faces using each point. Keep up to date whenever
264  // removing a face.
265  labelList nFacesUsingPoint(mesh_.nPoints(), 0);
266 
267  forAll(faces, faceI)
268  {
269  const face& f = faces[faceI];
270 
271  forAll(f, fp)
272  {
273  nFacesUsingPoint[f[fp]]++;
274  }
275  }
276 
277 
278  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
279  {
280  const face& f = faces[faceI];
281  label own = faceOwner[faceI];
282  label nei = faceNeighbour[faceI];
283 
284  if (removedCell[own])
285  {
286  if (removedCell[nei])
287  {
288  // Face no longer used
289  //Pout<< "Removing internal face " << faceI
290  // << " fc:" << mesh_.faceCentres()[faceI] << endl;
291 
292  meshMod.setAction(polyRemoveFace(faceI));
293  uncount(f, nFacesUsingPoint);
294  }
295  else
296  {
297  if (newPatchID[faceI] == -1)
298  {
300  << "No patchID provided for exposed face " << faceI
301  << " on cell " << nei << nl
302  << "Did you provide patch IDs for all exposed faces?"
303  << abort(FatalError);
304  }
305 
306  // nei is remaining cell. FaceI becomes external cell
307 
308  label zoneID = faceZones.whichZone(faceI);
309  bool zoneFlip = false;
310 
311  if (zoneID >= 0)
312  {
313  const faceZone& fZone = faceZones[zoneID];
314  // Note: we reverse the owner/neighbour of the face
315  // so should also select the other side of the zone
316  zoneFlip = !fZone.flipMap()[fZone.whichFace(faceI)];
317  }
318 
319  //Pout<< "Putting exposed internal face " << faceI
320  // << " fc:" << mesh_.faceCentres()[faceI]
321  // << " into patch " << newPatchID[faceI] << endl;
322 
323  meshMod.setAction
324  (
326  (
327  f.reverseFace(), // modified face
328  faceI, // label of face being modified
329  nei, // owner
330  -1, // neighbour
331  true, // face flip
332  newPatchID[faceI], // patch for face
333  false, // remove from zone
334  zoneID, // zone for face
335  zoneFlip // face flip in zone
336  )
337  );
338  }
339  }
340  else if (removedCell[nei])
341  {
342  if (newPatchID[faceI] == -1)
343  {
345  << "No patchID provided for exposed face " << faceI
346  << " on cell " << own << nl
347  << "Did you provide patch IDs for all exposed faces?"
348  << abort(FatalError);
349  }
350 
351  //Pout<< "Putting exposed internal face " << faceI
352  // << " fc:" << mesh_.faceCentres()[faceI]
353  // << " into patch " << newPatchID[faceI] << endl;
354 
355  // own is remaining cell. FaceI becomes external cell.
356  label zoneID = faceZones.whichZone(faceI);
357  bool zoneFlip = false;
358 
359  if (zoneID >= 0)
360  {
361  const faceZone& fZone = faceZones[zoneID];
362  zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
363  }
364 
365  meshMod.setAction
366  (
368  (
369  f, // modified face
370  faceI, // label of face being modified
371  own, // owner
372  -1, // neighbour
373  false, // face flip
374  newPatchID[faceI], // patch for face
375  false, // remove from zone
376  zoneID, // zone for face
377  zoneFlip // face flip in zone
378  )
379  );
380  }
381  }
382 
383  forAll(patches, patchI)
384  {
385  const polyPatch& pp = patches[patchI];
386 
387  if (pp.coupled())
388  {
389  label faceI = pp.start();
390 
391  forAll(pp, i)
392  {
393  if (newPatchID[faceI] != -1)
394  {
395  //Pout<< "Putting uncoupled coupled face " << faceI
396  // << " fc:" << mesh_.faceCentres()[faceI]
397  // << " into patch " << newPatchID[faceI] << endl;
398 
399  label zoneID = faceZones.whichZone(faceI);
400  bool zoneFlip = false;
401 
402  if (zoneID >= 0)
403  {
404  const faceZone& fZone = faceZones[zoneID];
405  zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
406  }
407 
408  meshMod.setAction
409  (
411  (
412  faces[faceI], // modified face
413  faceI, // label of face
414  faceOwner[faceI], // owner
415  -1, // neighbour
416  false, // face flip
417  newPatchID[faceI], // patch for face
418  false, // remove from zone
419  zoneID, // zone for face
420  zoneFlip // face flip in zone
421  )
422  );
423  }
424  else if (removedCell[faceOwner[faceI]])
425  {
426  // Face no longer used
427  //Pout<< "Removing boundary face " << faceI
428  // << " fc:" << mesh_.faceCentres()[faceI]
429  // << endl;
430 
431  meshMod.setAction(polyRemoveFace(faceI));
432  uncount(faces[faceI], nFacesUsingPoint);
433  }
434 
435  faceI++;
436  }
437  }
438  else
439  {
440  label faceI = pp.start();
441 
442  forAll(pp, i)
443  {
444  if (newPatchID[faceI] != -1)
445  {
447  << "new patchID provided for boundary face " << faceI
448  << " even though it is not on a coupled face."
449  << abort(FatalError);
450  }
451 
452  if (removedCell[faceOwner[faceI]])
453  {
454  // Face no longer used
455  //Pout<< "Removing boundary face " << faceI
456  // << " fc:" << mesh_.faceCentres()[faceI]
457  // << endl;
458 
459  meshMod.setAction(polyRemoveFace(faceI));
460  uncount(faces[faceI], nFacesUsingPoint);
461  }
462 
463  faceI++;
464  }
465  }
466  }
467 
468 
469  // Remove points that are no longer used.
470  // Loop rewritten to not use pointFaces.
471 
472  forAll(nFacesUsingPoint, pointI)
473  {
474  if (nFacesUsingPoint[pointI] == 0)
475  {
476  //Pout<< "Removing unused point " << pointI
477  // << " at:" << mesh_.points()[pointI] << endl;
478 
479  meshMod.setAction(polyRemovePoint(pointI));
480  }
481  else if (nFacesUsingPoint[pointI] == 1)
482  {
484  << "point " << pointI << " at coordinate "
485  << mesh_.points()[pointI]
486  << " is only used by 1 face after removing cells."
487  << " This probably results in an illegal mesh."
488  << endl;
489  }
490  }
491 }
492 
493 
494 // ************************************************************************* //
polyRemovePoint.H
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
Foam::polyRemovePoint
Class containing data for point removal.
Definition: polyRemovePoint.H:46
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::DynamicList< label >
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
polyRemoveFace.H
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:322
polyTopoChange.H
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:97
Foam::polyModifyFace
Class describing modification of a face.
Definition: polyModifyFace.H:48
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
removeCells.H
polyMesh.H
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::polyRemoveCell
Class containing data for cell removal.
Definition: polyRemoveCell.H:46
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::ZoneMesh< faceZone, polyMesh >
Foam::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
Foam::ZoneMesh::whichZone
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:226
Foam::removeCells::setRefinement
void setRefinement(const labelList &cellsToRemove, const labelList &facesToExpose, const labelList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:189
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::plusEqOp
Definition: ops.H:71
polyRemoveCell.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::faceZone::whichFace
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:314
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
polyModifyFace.H
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::mapDistribute::transform
Default transformation behaviour.
Definition: mapDistribute.H:196
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::polyTopoChange::setAction
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Definition: polyTopoChange.C:2530
f
labelList f(nPoints)
Foam::polyRemoveFace
Class containing data for face removal.
Definition: polyRemoveFace.H:46
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::removeCells::removeCells
removeCells(const polyMesh &mesh, const bool syncPar=true)
Construct from mesh. syncPar: do parallel synchronization.
Definition: removeCells.C:60
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::removeCells::uncount
static void uncount(const labelList &f, labelList &nUsage)
Decrease count of elements of f.
Definition: removeCells.C:45
Foam::faceZone::flipMap
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:249
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::removeCells::getExposedFaces
labelList getExposedFaces(const labelList &cellsToRemove) const
Get labels of exposed faces.
Definition: removeCells.C:73
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259