removeCells.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-2024 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 "removeCells.H"
27 #include "polyMesh.H"
28 #include "polyTopoChange.H"
29 #include "syncTools.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
36 }
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 void Foam::removeCells::uncount
41 (
42  const labelList& f,
43  labelList& nUsage
44 )
45 {
46  forAll(f, fp)
47  {
48  nUsage[f[fp]]--;
49  }
50 }
51 
52 
53 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
54 
56 (
57  const polyMesh& mesh,
58  const bool syncPar
59 )
60 :
61  mesh_(mesh),
62  syncPar_(syncPar)
63 {}
64 
65 
66 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
67 
69 (
70  const labelList& cellLabels
71 ) const
72 {
73  // Create list of cells to be removed
74  boolList removedCell(mesh_.nCells(), false);
75 
76  // Go from labelList of cells-to-remove to a boolList.
77  forAll(cellLabels, i)
78  {
79  removedCell[cellLabels[i]] = true;
80  }
81 
82 
83  const labelList& faceOwner = mesh_.faceOwner();
84  const labelList& faceNeighbour = mesh_.faceNeighbour();
85 
86  // Count cells using face.
87  labelList nCellsUsingFace(mesh_.nFaces(), 0);
88 
89  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
90  {
91  label own = faceOwner[facei];
92  label nei = faceNeighbour[facei];
93 
94  if (!removedCell[own])
95  {
96  nCellsUsingFace[facei]++;
97  }
98  if (!removedCell[nei])
99  {
100  nCellsUsingFace[facei]++;
101  }
102  }
103 
104  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
105  {
106  label own = faceOwner[facei];
107 
108  if (!removedCell[own])
109  {
110  nCellsUsingFace[facei]++;
111  }
112  }
113 
114  // Coupled faces: add number of cells using face across couple.
115  if (syncPar_)
116  {
118  (
119  mesh_,
120  nCellsUsingFace,
122  );
123  }
124 
125  // Now nCellsUsingFace:
126  // 0 : internal face whose both cells get deleted
127  // boundary face whose all cells get deleted
128  // 1 : internal face that gets exposed
129  // unaffected (uncoupled) boundary face
130  // coupled boundary face that gets exposed ('uncoupled')
131  // 2 : unaffected internal face
132  // unaffected coupled boundary face
133 
134  DynamicList<label> exposedFaces(mesh_.nFaces()/10);
135 
136  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
137  {
138  if (nCellsUsingFace[facei] == 1)
139  {
140  exposedFaces.append(facei);
141  }
142  }
143 
144  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
145 
147  {
148  const polyPatch& pp = patches[patchi];
149 
150  if (pp.coupled())
151  {
152  label facei = pp.start();
153 
154  forAll(pp, i)
155  {
156  label own = faceOwner[facei];
157 
158  if (nCellsUsingFace[facei] == 1 && !removedCell[own])
159  {
160  // My owner not removed but other side is so has to become
161  // normal, uncoupled, boundary face
162  exposedFaces.append(facei);
163  }
164 
165  facei++;
166  }
167  }
168  }
169 
170  return exposedFaces.shrink();
171 }
172 
173 
175 (
176  const labelList& cellLabels,
177  const labelList& exposedFaceLabels,
178  const labelList& exposedPatchIDs,
179  polyTopoChange& meshMod
180 ) const
181 {
182  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
183 
184  if (exposedFaceLabels.size() != exposedPatchIDs.size())
185  {
187  << "Size of exposedFaceLabels " << exposedFaceLabels.size()
188  << " differs from size of exposedPatchIDs "
189  << exposedPatchIDs.size()
190  << abort(FatalError);
191  }
192 
193  // List of new patchIDs
194  labelList newPatchID(mesh_.nFaces(), -1);
195 
196  forAll(exposedFaceLabels, i)
197  {
198  label patchi = exposedPatchIDs[i];
199 
200  if (patchi < 0 || patchi >= patches.size())
201  {
203  << "Invalid patch " << patchi
204  << " for exposed face " << exposedFaceLabels[i] << endl
205  << "Valid patches 0.." << patches.size()-1
206  << abort(FatalError);
207  }
208 
209  if (patches[patchi].coupled())
210  {
212  << "Trying to put exposed face " << exposedFaceLabels[i]
213  << " into a coupled patch : " << patches[patchi].name()
214  << endl
215  << "This is illegal."
216  << abort(FatalError);
217  }
218 
219  newPatchID[exposedFaceLabels[i]] = patchi;
220  }
221 
222 
223  // Create list of cells to be removed
224  boolList removedCell(mesh_.nCells(), false);
225 
226  // Go from labelList of cells-to-remove to a boolList and remove all
227  // cells mentioned.
228  forAll(cellLabels, i)
229  {
230  label celli = cellLabels[i];
231 
232  removedCell[celli] = true;
233 
234  // Pout<< "Removing cell " << celli
235  // << " cc:" << mesh_.cellCentres()[celli] << endl;
236 
237  meshMod.removeCell(celli, -1);
238  }
239 
240 
241  // Remove faces that are no longer used. Modify faces that
242  // are used by one cell only.
243 
244  const faceList& faces = mesh_.faces();
245  const labelList& faceOwner = mesh_.faceOwner();
246  const labelList& faceNeighbour = mesh_.faceNeighbour();
247 
248  // Count starting number of faces using each point. Keep up to date whenever
249  // removing a face.
250  labelList nFacesUsingPoint(mesh_.nPoints(), 0);
251 
252  forAll(faces, facei)
253  {
254  const face& f = faces[facei];
255 
256  forAll(f, fp)
257  {
258  nFacesUsingPoint[f[fp]]++;
259  }
260  }
261 
262 
263  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
264  {
265  const face& f = faces[facei];
266  label own = faceOwner[facei];
267  label nei = faceNeighbour[facei];
268 
269  if (removedCell[own])
270  {
271  if (removedCell[nei])
272  {
273  // Face no longer used
274  // Pout<< "Removing internal face " << facei
275  // << " fc:" << mesh_.faceCentres()[facei] << endl;
276 
277  meshMod.removeFace(facei, -1);
278  uncount(f, nFacesUsingPoint);
279  }
280  else
281  {
282  if (newPatchID[facei] == -1)
283  {
285  << "No patchID provided for exposed face " << facei
286  << " on cell " << nei << nl
287  << "Did you provide patch IDs for all exposed faces?"
288  << abort(FatalError);
289  }
290 
291  // nei is remaining cell. Facei becomes external cell
292 
293  meshMod.modifyFace
294  (
295  f.reverseFace(), // modified face
296  facei, // label of face being modified
297  nei, // owner
298  -1, // neighbour
299  true, // face flip
300  newPatchID[facei] // patch for face
301  );
302  }
303  }
304  else if (removedCell[nei])
305  {
306  if (newPatchID[facei] == -1)
307  {
309  << "No patchID provided for exposed face " << facei
310  << " on cell " << own << nl
311  << "Did you provide patch IDs for all exposed faces?"
312  << abort(FatalError);
313  }
314 
315  // Pout<< "Putting exposed internal face " << facei
316  // << " fc:" << mesh_.faceCentres()[facei]
317  // << " into patch " << newPatchID[facei] << endl;
318 
319  meshMod.modifyFace
320  (
321  f, // modified face
322  facei, // label of face being modified
323  own, // owner
324  -1, // neighbour
325  false, // face flip
326  newPatchID[facei] // patch for face
327  );
328  }
329  }
330 
332  {
333  const polyPatch& pp = patches[patchi];
334 
335  if (pp.coupled())
336  {
337  label facei = pp.start();
338 
339  forAll(pp, i)
340  {
341  if (newPatchID[facei] != -1)
342  {
343  meshMod.modifyFace
344  (
345  faces[facei], // modified face
346  facei, // label of face
347  faceOwner[facei], // owner
348  -1, // neighbour
349  false, // face flip
350  newPatchID[facei] // patch for face
351  );
352  }
353  else if (removedCell[faceOwner[facei]])
354  {
355  // Face no longer used
356  // Pout<< "Removing boundary face " << facei
357  // << " fc:" << mesh_.faceCentres()[facei]
358  // << endl;
359 
360  meshMod.removeFace(facei, -1);
361  uncount(faces[facei], nFacesUsingPoint);
362  }
363 
364  facei++;
365  }
366  }
367  else
368  {
369  label facei = pp.start();
370 
371  forAll(pp, i)
372  {
373  if (newPatchID[facei] != -1)
374  {
376  << "new patchID provided for boundary face " << facei
377  << " even though it is not on a coupled face."
378  << abort(FatalError);
379  }
380 
381  if (removedCell[faceOwner[facei]])
382  {
383  // Face no longer used
384  // Pout<< "Removing boundary face " << facei
385  // << " fc:" << mesh_.faceCentres()[facei]
386  // << endl;
387 
388  meshMod.removeFace(facei, -1);
389  uncount(faces[facei], nFacesUsingPoint);
390  }
391 
392  facei++;
393  }
394  }
395  }
396 
397 
398  // Remove points that are no longer used.
399  // Loop rewritten to not use pointFaces.
400 
401  forAll(nFacesUsingPoint, pointi)
402  {
403  if (nFacesUsingPoint[pointi] == 0)
404  {
405  // Pout<< "Removing unused point " << pointi
406  // << " at:" << mesh_.points()[pointi] << endl;
407 
408  meshMod.removePoint(pointi, -1);
409  }
410  else if (nFacesUsingPoint[pointi] == 1)
411  {
413  << "point " << pointi << " at coordinate "
414  << mesh_.points()[pointi]
415  << " is only used by 1 face after removing cells."
416  << " This probably results in an illegal mesh."
417  << endl;
418  }
419  }
420 }
421 
422 
423 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Foam::polyBoundaryMesh.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:290
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:280
Direct mesh changes based on v1.3 polyTopoChange syntax.
void removePoint(const label, const label)
Remove point / merge points.
void removeFace(const label, const label)
Remove face / merge faces.
void removeCell(const label, const label)
Remove cell / merge cells.
void modifyFace(const face &f, const label facei, const label own, const label nei, const bool flipFaceFlux, const label patchID)
Modify vertices or cell of face.
Given list of cells to remove insert all the topology changes.
Definition: removeCells.H:60
void setRefinement(const labelList &cellsToRemove, const labelList &facesToExpose, const labelList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:175
removeCells(const polyMesh &mesh, const bool syncPar=true)
Construct from mesh. syncPar: do parallel synchronisation.
Definition: removeCells.C:56
labelList getExposedFaces(const labelList &cellsToRemove) const
Get labels of exposed faces.
Definition: removeCells.C:69
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronise values on all mesh faces.
Definition: syncTools.H:387
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const fvPatchList & patches
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: labelList.H:56
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
errorManip< error > abort(error &err)
Definition: errorManip.H:131
defineTypeNameAndDebug(combustionModel, 0)
error FatalError
static const char nl
Definition: Ostream.H:266
labelList f(nPoints)