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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2018 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 "removeCells.H"
30 #include "bitSet.H"
31 #include "polyMesh.H"
32 #include "polyTopoChange.H"
33 #include "polyRemoveCell.H"
34 #include "polyRemoveFace.H"
35 #include "polyModifyFace.H"
36 #include "polyRemovePoint.H"
37 #include "syncTools.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(removeCells, 0);
44 }
45 
46 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
47 
48 namespace
49 {
50 
51 // Increase count (usage) of elements of list
52 inline void incrCount(const Foam::labelUList& list, Foam::labelList& counter)
53 {
54  for (auto idx : list)
55  {
56  ++counter[idx];
57  }
58 }
59 
60 // Decrease count (usage) of elements of list
61 inline void decrCount(const Foam::labelUList& list, Foam::labelList& counter)
62 {
63  for (auto idx : list)
64  {
65  --counter[idx];
66  }
67 }
68 
69 } // End anonymous namespace
70 
71 
72 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
73 
75 (
76  const polyMesh& mesh
77 )
78 :
79  removeCells(mesh, true)
80 {}
81 
82 
84 (
85  const polyMesh& mesh,
86  const bool syncPar
87 )
88 :
89  mesh_(mesh),
90  syncPar_(syncPar)
91 {}
92 
93 
94 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
95 
97 (
98  const bitSet& removedCell
99 ) const
100 {
101  const labelList& faceOwner = mesh_.faceOwner();
102  const labelList& faceNeighbour = mesh_.faceNeighbour();
103 
104  // Count cells using face.
105  labelList nCellsUsingFace(mesh_.nFaces(), Zero);
106 
107  for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
108  {
109  const label own = faceOwner[facei];
110  const label nei = faceNeighbour[facei];
111 
112  if (!removedCell[own])
113  {
114  ++nCellsUsingFace[facei];
115  }
116  if (!removedCell[nei])
117  {
118  ++nCellsUsingFace[facei];
119  }
120  }
121 
122  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); ++facei)
123  {
124  const label own = faceOwner[facei];
125 
126  if (!removedCell[own])
127  {
128  ++nCellsUsingFace[facei];
129  }
130  }
131 
132  // Coupled faces: add number of cells using face across couple.
133  {
134  // Note cyclics done always, parallel bits only done if syncPar_
135 
136  SubList<label> bndValues
137  (
138  nCellsUsingFace,
139  mesh_.nBoundaryFaces(),
140  mesh_.nInternalFaces()
141  );
142 
143  syncTools::syncBoundaryFaceList
144  (
145  mesh_,
146  bndValues,
147  plusEqOp<label>(),
149  syncPar_
150  );
151  }
152 
153  // Now nCellsUsingFace:
154  // 0 : internal face whose both cells get deleted
155  // boundary face whose all cells get deleted
156  // 1 : internal face that gets exposed
157  // unaffected (uncoupled) boundary face
158  // coupled boundary face that gets exposed ('uncoupled')
159  // 2 : unaffected internal face
160  // unaffected coupled boundary face
161 
162  DynamicList<label> exposedFaces(mesh_.nFaces()/10);
163 
164  for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
165  {
166  if (nCellsUsingFace[facei] == 1)
167  {
168  exposedFaces.append(facei);
169  }
170  }
171 
172  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
173 
174  for (const polyPatch& pp : patches)
175  {
176  if (pp.coupled())
177  {
178  label facei = pp.start();
179 
180  forAll(pp, i)
181  {
182  const label own = faceOwner[facei];
183 
184  if (nCellsUsingFace[facei] == 1 && !removedCell[own])
185  {
186  // My owner not removed but other side is so has to become
187  // normal, uncoupled, boundary face
188  exposedFaces.append(facei);
189  }
190 
191  ++facei;
192  }
193  }
194  }
195 
196  return exposedFaces.shrink();
197 }
198 
199 
201 (
202  const bitSet& removedCell,
203  const labelUList& exposedFaceLabels,
204  const labelUList& exposedPatchIDs,
205  polyTopoChange& meshMod
206 ) const
207 {
208  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
209 
210  if (exposedFaceLabels.size() != exposedPatchIDs.size())
211  {
213  << "Size of exposedFaceLabels " << exposedFaceLabels.size()
214  << " differs from size of exposedPatchIDs "
215  << exposedPatchIDs.size()
216  << abort(FatalError);
217  }
218 
219  // List of new patchIDs
220  labelList newPatchID(mesh_.nFaces(), -1);
221 
222  forAll(exposedFaceLabels, i)
223  {
224  const label facei = exposedFaceLabels[i];
225  const label patchi = exposedPatchIDs[i];
226 
227  if (patchi < 0 || patchi >= patches.size())
228  {
230  << "Invalid patch " << patchi
231  << " for exposed face " << facei << nl
232  << "Valid patches 0.." << patches.size()-1
233  << abort(FatalError);
234  }
235 
236  if (patches[patchi].coupled())
237  {
239  << "Trying to put exposed face " << facei
240  << " into a coupled patch : " << patches[patchi].name()
241  << nl
242  << "This is illegal."
243  << abort(FatalError);
244  }
245 
246  newPatchID[facei] = patchi;
247  }
248 
249 
250  // Walk all the cells mentioned for removal
251  for (const label celli : removedCell)
252  {
253  //Pout<< "Removing cell " << celli
254  // << " cc:" << mesh_.cellCentres()[celli] << endl;
255 
256  meshMod.setAction(polyRemoveCell(celli));
257  }
258 
259 
260  // Remove faces that are no longer used. Modify faces that
261  // are used by one cell only.
262 
263  const faceList& faces = mesh_.faces();
264  const labelList& faceOwner = mesh_.faceOwner();
265  const labelList& faceNeighbour = mesh_.faceNeighbour();
266  const faceZoneMesh& faceZones = mesh_.faceZones();
267 
268  // Count starting number of faces using each point.
269  // Update whenever removing a face.
270  labelList nFacesUsingPoint(mesh_.nPoints(), Zero);
271 
272  for (const face& f : faces)
273  {
274  incrCount(f, nFacesUsingPoint);
275  }
276 
277 
278  for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
279  {
280  const face& f = faces[facei];
281  const label own = faceOwner[facei];
282  const 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  decrCount(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  const 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  const 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  for (const polyPatch& pp : patches)
384  {
385  if (pp.coupled())
386  {
387  label facei = pp.start();
388 
389  forAll(pp, i)
390  {
391  if (newPatchID[facei] != -1)
392  {
393  //Pout<< "Putting uncoupled coupled face " << facei
394  // << " fc:" << mesh_.faceCentres()[facei]
395  // << " into patch " << newPatchID[facei] << endl;
396 
397  const label zoneID = faceZones.whichZone(facei);
398  bool zoneFlip = false;
399 
400  if (zoneID >= 0)
401  {
402  const faceZone& fZone = faceZones[zoneID];
403  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
404  }
405 
406  meshMod.setAction
407  (
409  (
410  faces[facei], // modified face
411  facei, // label of face
412  faceOwner[facei], // owner
413  -1, // neighbour
414  false, // face flip
415  newPatchID[facei], // patch for face
416  false, // remove from zone
417  zoneID, // zone for face
418  zoneFlip // face flip in zone
419  )
420  );
421  }
422  else if (removedCell[faceOwner[facei]])
423  {
424  // Face no longer used
425  //Pout<< "Removing boundary face " << facei
426  // << " fc:" << mesh_.faceCentres()[facei]
427  // << endl;
428 
429  meshMod.setAction(polyRemoveFace(facei));
430  decrCount(faces[facei], nFacesUsingPoint);
431  }
432 
433  ++facei;
434  }
435  }
436  else
437  {
438  label facei = pp.start();
439 
440  forAll(pp, i)
441  {
442  if (newPatchID[facei] != -1)
443  {
445  << "new patchID provided for boundary face " << facei
446  << " even though it is not on a coupled face."
447  << abort(FatalError);
448  }
449 
450  if (removedCell[faceOwner[facei]])
451  {
452  // Face no longer used
453  //Pout<< "Removing boundary face " << facei
454  // << " fc:" << mesh_.faceCentres()[facei]
455  // << endl;
456 
457  meshMod.setAction(polyRemoveFace(facei));
458  decrCount(faces[facei], nFacesUsingPoint);
459  }
460 
461  ++facei;
462  }
463  }
464  }
465 
466 
467  // Remove points that are no longer used.
468  // Loop rewritten to not use pointFaces.
469 
470  forAll(nFacesUsingPoint, pointi)
471  {
472  if (nFacesUsingPoint[pointi] == 0)
473  {
474  //Pout<< "Removing unused point " << pointi
475  // << " at:" << mesh_.points()[pointi] << endl;
476 
477  meshMod.setAction(polyRemovePoint(pointi));
478  }
479  else if (nFacesUsingPoint[pointi] == 1)
480  {
482  << "point " << pointi << " at coordinate "
483  << mesh_.points()[pointi]
484  << " is only used by 1 face after removing cells."
485  << " This probably results in an illegal mesh."
486  << endl;
487  }
488  }
489 }
490 
491 
493 (
494  const labelUList& cellsToRemove
495 ) const
496 {
497  bitSet removeCell(mesh_.nCells(), cellsToRemove);
498 
499  return getExposedFaces(removeCell);
500 }
501 
502 
504 (
505  const labelUList& cellsToRemove,
506  const labelUList& exposedFaceLabels,
507  const labelUList& exposedPatchIDs,
508  polyTopoChange& meshMod
509 ) const
510 {
511  bitSet removedCell(mesh_.nCells(), cellsToRemove);
512 
513  setRefinement
514  (
515  removedCell,
516  exposedFaceLabels,
517  exposedPatchIDs,
518  meshMod
519  );
520 }
521 
522 
523 // ************************************************************************* //
polyRemovePoint.H
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::polyRemovePoint
Class containing data for point removal.
Definition: polyRemovePoint.H:48
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::removeCells
Given list of cells to remove, insert all the topology changes.
Definition: removeCells.H:63
Foam::DynamicList< label >
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
polyRemoveFace.H
polyTopoChange.H
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::polyModifyFace
Class describing modification of a face.
Definition: polyModifyFace.H:50
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
removeCells.H
polyMesh.H
bitSet.H
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::removeCells::setRefinement
void setRefinement(const bitSet &removedCell, const labelUList &facesToExpose, const labelUList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:201
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::polyRemoveCell
Class containing data for cell removal.
Definition: polyRemoveCell.H:48
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::removeCells::removeCells
removeCells(const polyMesh &mesh)
Construct from mesh. With parallel synchronization.
Definition: removeCells.C:75
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::ZoneMesh< faceZone, polyMesh >
Foam::ZoneMesh::whichZone
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:289
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
polyRemoveCell.H
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::faceZone::whichFace
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:372
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
polyModifyFace.H
Foam::mapDistribute::transform
Default transformation behaviour.
Definition: mapDistribute.H:209
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::polyTopoChange::setAction
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Definition: polyTopoChange.C:2481
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::polyRemoveFace
Class containing data for face removal.
Definition: polyRemoveFace.H:48
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::UList< label >
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::plusEqOp
Definition: ops.H:72
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::removeCells::getExposedFaces
labelList getExposedFaces(const bitSet &removedCell) const
Get labels of faces exposed after cells removal.
Definition: removeCells.C:97