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