cellToFaceStencil.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-2018 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 "cellToFaceStencil.H"
27 #include "SortableList.H"
28 #include "emptyPolyPatch.H"
29 #include "syncTools.H"
30 #include "dummyTransform.H"
31 
32 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
33 
35 (
36  const label global0,
37  const label global1,
38  const labelList& listA,
39  labelList& listB
40 )
41 {
42  sort(listB);
43 
44  // See if global0, global1 already present in listB
45  label nGlobalInsert = 0;
46 
47  if (global0 != -1)
48  {
49  label index0 = findSortedIndex(listB, global0);
50  if (index0 == -1)
51  {
52  nGlobalInsert++;
53  }
54  }
55 
56  if (global1 != -1)
57  {
58  label index1 = findSortedIndex(listB, global1);
59  if (index1 == -1)
60  {
61  nGlobalInsert++;
62  }
63  }
64 
65 
66  // For all in listA see if they are present
67  label nInsert = 0;
68 
69  forAll(listA, i)
70  {
71  label elem = listA[i];
72 
73  if (elem != global0 && elem != global1)
74  {
75  if (findSortedIndex(listB, elem) == -1)
76  {
77  nInsert++;
78  }
79  }
80  }
81 
82  // Extend B with nInsert and whether global0,global1 need to be inserted.
83  labelList result(listB.size() + nGlobalInsert + nInsert);
84 
85  label resultI = 0;
86 
87  // Insert global0,1 first
88  if (global0 != -1)
89  {
90  result[resultI++] = global0;
91  }
92  if (global1 != -1)
93  {
94  result[resultI++] = global1;
95  }
96 
97 
98  // Insert listB
99  forAll(listB, i)
100  {
101  label elem = listB[i];
102 
103  if (elem != global0 && elem != global1)
104  {
105  result[resultI++] = elem;
106  }
107  }
108 
109 
110  // Insert listA
111  forAll(listA, i)
112  {
113  label elem = listA[i];
114 
115  if (elem != global0 && elem != global1)
116  {
117  if (findSortedIndex(listB, elem) == -1)
118  {
119  result[resultI++] = elem;
120  }
121  }
122  }
123 
124  if (resultI != result.size())
125  {
127  << "problem" << abort(FatalError);
128  }
129 
130  listB.transfer(result);
131 }
132 
133 
135 (
136  const label globalI,
137  const labelList& pGlobals,
138  labelList& cCells
139 )
140 {
141  labelHashSet set;
142  forAll(cCells, i)
143  {
144  if (cCells[i] != globalI)
145  {
146  set.insert(cCells[i]);
147  }
148  }
149 
150  forAll(pGlobals, i)
151  {
152  if (pGlobals[i] != globalI)
153  {
154  set.insert(pGlobals[i]);
155  }
156  }
157 
158  cCells.setSize(set.size()+1);
159  label n = 0;
160  cCells[n++] = globalI;
161 
162  forAllConstIter(labelHashSet, set, iter)
163  {
164  cCells[n++] = iter.key();
165  }
166 }
167 
168 
170 {
172 
173  isValidBFace.setSize(mesh().nFaces()-mesh().nInternalFaces(), true);
174 
175  forAll(patches, patchi)
176  {
177  const polyPatch& pp = patches[patchi];
178 
179  if (pp.coupled() || isA<emptyPolyPatch>(pp))
180  {
181  label bFacei = pp.start()-mesh().nInternalFaces();
182  forAll(pp, i)
183  {
184  isValidBFace[bFacei++] = false;
185  }
186  }
187  }
188 }
189 
190 
193 {
195 
196  label nCoupled = 0;
197 
198  forAll(patches, patchi)
199  {
200  const polyPatch& pp = patches[patchi];
201 
202  if (pp.coupled())
203  {
204  nCoupled += pp.size();
205  }
206  }
207  labelList coupledFaces(nCoupled);
208  nCoupled = 0;
209 
210  forAll(patches, patchi)
211  {
212  const polyPatch& pp = patches[patchi];
213 
214  if (pp.coupled())
215  {
216  label facei = pp.start();
217 
218  forAll(pp, i)
219  {
220  coupledFaces[nCoupled++] = facei++;
221  }
222  }
223  }
224 
226  (
228  (
230  (
231  mesh().faces(),
232  coupledFaces
233  ),
234  mesh().points()
235  )
236  );
237 }
238 
239 
240 void Foam::cellToFaceStencil::unionEqOp::operator()
241 (
242  labelList& x,
243  const labelList& y
244 ) const
245 {
246  if (y.size())
247  {
248  if (x.empty())
249  {
250  x = y;
251  }
252  else
253  {
254  labelHashSet set(x);
255  forAll(y, i)
256  {
257  set.insert(y[i]);
258  }
259  x = set.toc();
260  }
261  }
262 }
263 
264 
266 (
267  const label exclude0,
268  const label exclude1,
269  const boolList& isValidBFace,
270  const labelList& faceLabels,
271  labelHashSet& globals
272 ) const
273 {
274  const labelList& own = mesh().faceOwner();
275  const labelList& nei = mesh().faceNeighbour();
276 
277  forAll(faceLabels, i)
278  {
279  label facei = faceLabels[i];
280 
281  label globalOwn = globalNumbering().toGlobal(own[facei]);
282  if (globalOwn != exclude0 && globalOwn != exclude1)
283  {
284  globals.insert(globalOwn);
285  }
286 
287  if (mesh().isInternalFace(facei))
288  {
289  label globalNei = globalNumbering().toGlobal(nei[facei]);
290  if (globalNei != exclude0 && globalNei != exclude1)
291  {
292  globals.insert(globalNei);
293  }
294  }
295  else
296  {
297  label bFacei = facei-mesh().nInternalFaces();
298 
299  if (isValidBFace[bFacei])
300  {
301  label globalI = globalNumbering().toGlobal
302  (
303  mesh().nCells()
304  + bFacei
305  );
306 
307  if (globalI != exclude0 && globalI != exclude1)
308  {
309  globals.insert(globalI);
310  }
311  }
312  }
313  }
314 }
315 
316 
318 (
319  const boolList& isValidBFace,
320  const labelList& faceLabels,
321  labelHashSet& globals
322 ) const
323 {
324  globals.clear();
325 
327  (
328  -1,
329  -1,
330  isValidBFace,
331  faceLabels,
332  globals
333  );
334 
335  return globals.toc();
336 }
337 
338 
340 (
341  const labelListList& globalCellCells,
342  labelListList& faceStencil
343 ) const
344 {
345  // Calculates per face a list of global cell/face indices.
346 
347  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
348  const label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
349  const labelList& own = mesh_.faceOwner();
350  const labelList& nei = mesh_.faceNeighbour();
351 
352 
353  // Determine neighbouring global cell Cells
354  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355 
356  labelListList neiGlobalCellCells(nBnd);
357  forAll(patches, patchi)
358  {
359  const polyPatch& pp = patches[patchi];
360 
361  if (pp.coupled())
362  {
363  label facei = pp.start();
364 
365  forAll(pp, i)
366  {
367  neiGlobalCellCells[facei-mesh_.nInternalFaces()] =
368  globalCellCells[own[facei]];
369  facei++;
370  }
371  }
372  }
373  // syncTools::swapBoundaryFaceList(mesh_, neiGlobalCellCells);
375  (
376  mesh_,
377  neiGlobalCellCells,
378  eqOp<labelList>(),
380  );
381 
382 
383 
384  // Construct stencil in global numbering
385  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
386 
387  faceStencil.setSize(mesh_.nFaces());
388 
389  labelHashSet faceStencilSet;
390 
391  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
392  {
393  faceStencilSet.clear();
394 
395  const labelList& ownCCells = globalCellCells[own[facei]];
396  label globalOwn = ownCCells[0];
397  // Insert cellCells
398  forAll(ownCCells, i)
399  {
400  faceStencilSet.insert(ownCCells[i]);
401  }
402 
403  const labelList& neiCCells = globalCellCells[nei[facei]];
404  label globalNei = neiCCells[0];
405  // Insert cellCells
406  forAll(neiCCells, i)
407  {
408  faceStencilSet.insert(neiCCells[i]);
409  }
410 
411  // Guarantee owner first, neighbour second.
412  faceStencil[facei].setSize(faceStencilSet.size());
413  label n = 0;
414  faceStencil[facei][n++] = globalOwn;
415  faceStencil[facei][n++] = globalNei;
416  forAllConstIter(labelHashSet, faceStencilSet, iter)
417  {
418  if (iter.key() != globalOwn && iter.key() != globalNei)
419  {
420  faceStencil[facei][n++] = iter.key();
421  }
422  }
423  // Pout<< "internalface:" << facei << " toc:" << faceStencilSet.toc()
424  // << " faceStencil:" << faceStencil[facei] << endl;
425  }
426  forAll(patches, patchi)
427  {
428  const polyPatch& pp = patches[patchi];
429  label facei = pp.start();
430 
431  if (pp.coupled())
432  {
433  forAll(pp, i)
434  {
435  faceStencilSet.clear();
436 
437  const labelList& ownCCells = globalCellCells[own[facei]];
438  label globalOwn = ownCCells[0];
439  forAll(ownCCells, i)
440  {
441  faceStencilSet.insert(ownCCells[i]);
442  }
443 
444  // And the neighbours of the coupled cell
445  const labelList& neiCCells =
446  neiGlobalCellCells[facei-mesh_.nInternalFaces()];
447  label globalNei = neiCCells[0];
448  forAll(neiCCells, i)
449  {
450  faceStencilSet.insert(neiCCells[i]);
451  }
452 
453  // Guarantee owner first, neighbour second.
454  faceStencil[facei].setSize(faceStencilSet.size());
455  label n = 0;
456  faceStencil[facei][n++] = globalOwn;
457  faceStencil[facei][n++] = globalNei;
458  forAllConstIter(labelHashSet, faceStencilSet, iter)
459  {
460  if (iter.key() != globalOwn && iter.key() != globalNei)
461  {
462  faceStencil[facei][n++] = iter.key();
463  }
464  }
465 
466  // Pout<< "coupledface:" << facei
467  // << " toc:" << faceStencilSet.toc()
468  // << " faceStencil:" << faceStencil[facei] << endl;
469 
470  facei++;
471  }
472  }
473  else if (!isA<emptyPolyPatch>(pp))
474  {
475  forAll(pp, i)
476  {
477  faceStencilSet.clear();
478 
479  const labelList& ownCCells = globalCellCells[own[facei]];
480  label globalOwn = ownCCells[0];
481  forAll(ownCCells, i)
482  {
483  faceStencilSet.insert(ownCCells[i]);
484  }
485 
486  // Guarantee owner first
487  faceStencil[facei].setSize(faceStencilSet.size());
488  label n = 0;
489  faceStencil[facei][n++] = globalOwn;
490  forAllConstIter(labelHashSet, faceStencilSet, iter)
491  {
492  if (iter.key() != globalOwn)
493  {
494  faceStencil[facei][n++] = iter.key();
495  }
496  }
497 
498  // Pout<< "boundaryface:" << facei
499  // << " toc:" << faceStencilSet.toc()
500  // << " faceStencil:" << faceStencil[facei] << endl;
501 
502  facei++;
503  }
504  }
505  }
506 }
507 
508 
509 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
510 
512 :
513  mesh_(mesh),
514  globalNumbering_(mesh_.nCells()+mesh_.nFaces()-mesh_.nInternalFaces())
515 {}
516 
517 
518 // ************************************************************************* //
const fvPatchList & patches
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:453
static void syncBoundaryFaceList(const polyMesh &, UList< T > &, const CombineOp &cop, const TransformOp &top, const bool parRun=Pstream::parRun())
Synchronise values on boundary faces only.
cellToFaceStencil(const polyMesh &)
Construct from mesh.
label findSortedIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element in sorted list and return index,.
void insertFaceCells(const label exclude0, const label exclude1, const boolList &nonEmptyFace, const labelList &faceLabels, labelHashSet &globals) const
Collect cell neighbours of faces in global numbering.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
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
label nInternalFaces() const
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1243
label nFaces() const
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:111
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
const globalIndex & globalNumbering() const
Global numbering for cells and boundary faces.
Dummy transform to be used with syncTools.
scalar y
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:316
Definition: ops.H:70
const pointField & points
void clear()
Clear all entries from table.
Definition: HashTable.C:468
void sort(UList< T > &)
Definition: UList.C:115
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1237
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::polyBoundaryMesh.
const polyMesh & mesh() const
void setSize(const label)
Reset size of List.
Definition: List.C:281
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
label patchi
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:306
void calcFaceStencil(const labelListList &globalCellCells, labelListList &faceStencil) const
Collect cell neighbours into extended stencil.
label n
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
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:202
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
void validBoundaryFaces(boolList &isValidBFace) const
Valid boundary faces (not empty and not coupled)
labelList calcFaceCells(const boolList &nonEmptyFace, const labelList &faceLabels, labelHashSet &globals) const
Collect cell neighbours of faces in global numbering.
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
static void merge(const label global0, const label global1, const labelList &listA, labelList &listB)
Merge two lists.
autoPtr< indirectPrimitivePatch > allCoupledFacesPatch() const
Return patch of all coupled faces.