FreeFOAM The Cross-Platform CFD Toolkit
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) 1991-2010 OpenCFD Ltd.
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 <OpenFOAM/syncTools.H>
28 #include <OpenFOAM/SortableList.H>
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 // Merge two list and guarantee global0,global1 are first.
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  {
126  FatalErrorIn("cellToFaceStencil::merge(..)")
127  << "problem" << abort(FatalError);
128  }
129 
130  listB.transfer(result);
131 }
132 
133 
134 // Merge two list and guarantee globalI is first.
136 (
137  const label globalI,
138  const labelList& pGlobals,
139  labelList& cCells
140 )
141 {
142  labelHashSet set;
143  forAll(cCells, i)
144  {
145  if (cCells[i] != globalI)
146  {
147  set.insert(cCells[i]);
148  }
149  }
150 
151  forAll(pGlobals, i)
152  {
153  if (pGlobals[i] != globalI)
154  {
155  set.insert(pGlobals[i]);
156  }
157  }
158 
159  cCells.setSize(set.size()+1);
160  label n = 0;
161  cCells[n++] = globalI;
162 
163  forAllConstIter(labelHashSet, set, iter)
164  {
165  cCells[n++] = iter.key();
166  }
167 }
168 
169 
171 {
173 
174  isValidBFace.setSize(mesh().nFaces()-mesh().nInternalFaces(), true);
175 
176  forAll(patches, patchI)
177  {
178  const polyPatch& pp = patches[patchI];
179 
180  if (pp.coupled() || isA<emptyPolyPatch>(pp))
181  {
182  label bFaceI = pp.start()-mesh().nInternalFaces();
183  forAll(pp, i)
184  {
185  isValidBFace[bFaceI++] = false;
186  }
187  }
188  }
189 }
190 
191 
194 {
196 
197  label nCoupled = 0;
198 
199  forAll(patches, patchI)
200  {
201  const polyPatch& pp = patches[patchI];
202 
203  if (pp.coupled())
204  {
205  nCoupled += pp.size();
206  }
207  }
208  labelList coupledFaces(nCoupled);
209  nCoupled = 0;
210 
211  forAll(patches, patchI)
212  {
213  const polyPatch& pp = patches[patchI];
214 
215  if (pp.coupled())
216  {
217  label faceI = pp.start();
218 
219  forAll(pp, i)
220  {
221  coupledFaces[nCoupled++] = faceI++;
222  }
223  }
224  }
225 
227  (
229  (
231  (
232  mesh().faces(),
233  coupledFaces
234  ),
235  mesh().points()
236  )
237  );
238 }
239 
240 
241 void Foam::cellToFaceStencil::unionEqOp::operator()
242 (
243  labelList& x,
244  const labelList& y
245 ) const
246 {
247  if (y.size())
248  {
249  if (x.empty())
250  {
251  x = y;
252  }
253  else
254  {
255  labelHashSet set(x);
256  forAll(y, i)
257  {
258  set.insert(y[i]);
259  }
260  x = set.toc();
261  }
262  }
263 }
264 
265 
267 (
268  const label exclude0,
269  const label exclude1,
270  const boolList& isValidBFace,
271  const labelList& faceLabels,
272  labelHashSet& globals
273 ) const
274 {
275  const labelList& own = mesh().faceOwner();
276  const labelList& nei = mesh().faceNeighbour();
277 
278  forAll(faceLabels, i)
279  {
280  label faceI = faceLabels[i];
281 
282  label globalOwn = globalNumbering().toGlobal(own[faceI]);
283  if (globalOwn != exclude0 && globalOwn != exclude1)
284  {
285  globals.insert(globalOwn);
286  }
287 
288  if (mesh().isInternalFace(faceI))
289  {
290  label globalNei = globalNumbering().toGlobal(nei[faceI]);
291  if (globalNei != exclude0 && globalNei != exclude1)
292  {
293  globals.insert(globalNei);
294  }
295  }
296  else
297  {
298  label bFaceI = faceI-mesh().nInternalFaces();
299 
300  if (isValidBFace[bFaceI])
301  {
302  label globalI = globalNumbering().toGlobal
303  (
304  mesh().nCells()
305  + bFaceI
306  );
307 
308  if (globalI != exclude0 && globalI != exclude1)
309  {
310  globals.insert(globalI);
311  }
312  }
313  }
314  }
315 }
316 
317 
319 (
320  const boolList& isValidBFace,
321  const labelList& faceLabels,
322  labelHashSet& globals
323 ) const
324 {
325  globals.clear();
326 
327  insertFaceCells
328  (
329  -1,
330  -1,
331  isValidBFace,
332  faceLabels,
333  globals
334  );
335 
336  return globals.toc();
337 }
338 
339 
340 // Calculates per face a list of global cell/face indices.
342 (
343  const labelListList& globalCellCells,
344  labelListList& faceStencil
345 ) const
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, false);
374 
375 
376 
377  // Construct stencil in global numbering
378  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
379 
380  faceStencil.setSize(mesh_.nFaces());
381 
382  labelHashSet faceStencilSet;
383 
384  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
385  {
386  faceStencilSet.clear();
387 
388  const labelList& ownCCells = globalCellCells[own[faceI]];
389  label globalOwn = ownCCells[0];
390  // Insert cellCells
391  forAll(ownCCells, i)
392  {
393  faceStencilSet.insert(ownCCells[i]);
394  }
395 
396  const labelList& neiCCells = globalCellCells[nei[faceI]];
397  label globalNei = neiCCells[0];
398  // Insert cellCells
399  forAll(neiCCells, i)
400  {
401  faceStencilSet.insert(neiCCells[i]);
402  }
403 
404  // Guarantee owner first, neighbour second.
405  faceStencil[faceI].setSize(faceStencilSet.size());
406  label n = 0;
407  faceStencil[faceI][n++] = globalOwn;
408  faceStencil[faceI][n++] = globalNei;
409  forAllConstIter(labelHashSet, faceStencilSet, iter)
410  {
411  if (iter.key() != globalOwn && iter.key() != globalNei)
412  {
413  faceStencil[faceI][n++] = iter.key();
414  }
415  }
416  //Pout<< "internalface:" << faceI << " toc:" << faceStencilSet.toc()
417  // << " faceStencil:" << faceStencil[faceI] << endl;
418  }
419  forAll(patches, patchI)
420  {
421  const polyPatch& pp = patches[patchI];
422  label faceI = pp.start();
423 
424  if (pp.coupled())
425  {
426  forAll(pp, i)
427  {
428  faceStencilSet.clear();
429 
430  const labelList& ownCCells = globalCellCells[own[faceI]];
431  label globalOwn = ownCCells[0];
432  forAll(ownCCells, i)
433  {
434  faceStencilSet.insert(ownCCells[i]);
435  }
436 
437  // And the neighbours of the coupled cell
438  const labelList& neiCCells =
439  neiGlobalCellCells[faceI-mesh_.nInternalFaces()];
440  label globalNei = neiCCells[0];
441  forAll(neiCCells, i)
442  {
443  faceStencilSet.insert(neiCCells[i]);
444  }
445 
446  // Guarantee owner first, neighbour second.
447  faceStencil[faceI].setSize(faceStencilSet.size());
448  label n = 0;
449  faceStencil[faceI][n++] = globalOwn;
450  faceStencil[faceI][n++] = globalNei;
451  forAllConstIter(labelHashSet, faceStencilSet, iter)
452  {
453  if (iter.key() != globalOwn && iter.key() != globalNei)
454  {
455  faceStencil[faceI][n++] = iter.key();
456  }
457  }
458 
459  //Pout<< "coupledface:" << faceI
460  // << " toc:" << faceStencilSet.toc()
461  // << " faceStencil:" << faceStencil[faceI] << endl;
462 
463  faceI++;
464  }
465  }
466  else if (!isA<emptyPolyPatch>(pp))
467  {
468  forAll(pp, i)
469  {
470  faceStencilSet.clear();
471 
472  const labelList& ownCCells = globalCellCells[own[faceI]];
473  label globalOwn = ownCCells[0];
474  forAll(ownCCells, i)
475  {
476  faceStencilSet.insert(ownCCells[i]);
477  }
478 
479  // Guarantee owner first
480  faceStencil[faceI].setSize(faceStencilSet.size());
481  label n = 0;
482  faceStencil[faceI][n++] = globalOwn;
483  forAllConstIter(labelHashSet, faceStencilSet, iter)
484  {
485  if (iter.key() != globalOwn)
486  {
487  faceStencil[faceI][n++] = iter.key();
488  }
489  }
490 
491  //Pout<< "boundaryface:" << faceI
492  // << " toc:" << faceStencilSet.toc()
493  // << " faceStencil:" << faceStencil[faceI] << endl;
494 
495  faceI++;
496  }
497  }
498  }
499 }
500 
501 
502 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
503 
504 Foam::cellToFaceStencil::cellToFaceStencil(const polyMesh& mesh)
505 :
506  mesh_(mesh),
507  globalNumbering_(mesh_.nCells()+mesh_.nFaces()-mesh_.nInternalFaces())
508 {}
509 
510 
511 // ************************ vim: set sw=4 sts=4 et: ************************ //