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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 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 "cellToFaceStencil.H"
30 #include "SortableList.H"
31 #include "emptyPolyPatch.H"
32 #include "syncTools.H"
33 #include "dummyTransform.H"
34 
35 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
36 
38 (
39  const label global0,
40  const label global1,
41  const labelList& listA,
42  labelList& listB
43 )
44 {
45  sort(listB);
46 
47  // See if global0, global1 already present in listB
48  label nGlobalInsert = 0;
49 
50  if (global0 != -1)
51  {
52  label index0 = findSortedIndex(listB, global0);
53  if (index0 == -1)
54  {
55  nGlobalInsert++;
56  }
57  }
58 
59  if (global1 != -1)
60  {
61  label index1 = findSortedIndex(listB, global1);
62  if (index1 == -1)
63  {
64  nGlobalInsert++;
65  }
66  }
67 
68 
69  // For all in listA see if they are present
70  label nInsert = 0;
71 
72  for (const label elem : listA)
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  for (const label elem : listB)
101  {
102  if (elem != global0 && elem != global1)
103  {
104  result[resultI++] = elem;
105  }
106  }
107 
108 
109  // Insert listA
110  for (const label elem : listA)
111  {
112  if (elem != global0 && elem != global1)
113  {
114  if (findSortedIndex(listB, elem) == -1)
115  {
116  result[resultI++] = elem;
117  }
118  }
119  }
120 
121  if (resultI != result.size())
122  {
124  << "problem" << abort(FatalError);
125  }
126 
127  listB.transfer(result);
128 }
129 
130 
132 (
133  const label globalI,
134  const labelList& pGlobals,
135  labelList& cCells
136 )
137 {
138  labelHashSet set;
139  forAll(cCells, i)
140  {
141  if (cCells[i] != globalI)
142  {
143  set.insert(cCells[i]);
144  }
145  }
146 
147  forAll(pGlobals, i)
148  {
149  if (pGlobals[i] != globalI)
150  {
151  set.insert(pGlobals[i]);
152  }
153  }
154 
155  cCells.setSize(set.size()+1);
156  label n = 0;
157  cCells[n++] = globalI;
158 
159  for (const label seti : set)
160  {
161  cCells[n++] = seti;
162  }
163 }
164 
165 
167 {
169 
170  isValidBFace.setSize(mesh().nBoundaryFaces(), true);
171 
172  forAll(patches, patchi)
173  {
174  const polyPatch& pp = patches[patchi];
175 
176  if (pp.coupled() || isA<emptyPolyPatch>(pp))
177  {
178  label bFacei = pp.start()-mesh().nInternalFaces();
179  forAll(pp, i)
180  {
181  isValidBFace[bFacei++] = false;
182  }
183  }
184  }
185 }
186 
187 
190 {
192 
193  label nCoupled = 0;
194 
195  forAll(patches, patchi)
196  {
197  const polyPatch& pp = patches[patchi];
198 
199  if (pp.coupled())
200  {
201  nCoupled += pp.size();
202  }
203  }
204  labelList coupledFaces(nCoupled);
205  nCoupled = 0;
206 
207  forAll(patches, patchi)
208  {
209  const polyPatch& pp = patches[patchi];
210 
211  if (pp.coupled())
212  {
213  label facei = pp.start();
214 
215  forAll(pp, i)
216  {
217  coupledFaces[nCoupled++] = facei++;
218  }
219  }
220  }
221 
223  (
225  (
226  mesh().faces(),
227  coupledFaces
228  ),
229  mesh().points()
230  );
231 }
232 
233 
234 void Foam::cellToFaceStencil::unionEqOp::operator()
235 (
236  labelList& x,
237  const labelList& y
238 ) const
239 {
240  if (y.size())
241  {
242  if (x.empty())
243  {
244  x = y;
245  }
246  else
247  {
248  labelHashSet set(x);
249  set.insert(y);
250  x = set.toc();
251  }
252  }
253 }
254 
255 
257 (
258  const label exclude0,
259  const label exclude1,
260  const boolList& isValidBFace,
261  const labelList& faceLabels,
262  labelHashSet& globals
263 ) const
264 {
265  const labelList& own = mesh().faceOwner();
266  const labelList& nei = mesh().faceNeighbour();
267 
268  forAll(faceLabels, i)
269  {
270  label facei = faceLabels[i];
271 
272  label globalOwn = globalNumbering().toGlobal(own[facei]);
273  if (globalOwn != exclude0 && globalOwn != exclude1)
274  {
275  globals.insert(globalOwn);
276  }
277 
278  if (mesh().isInternalFace(facei))
279  {
280  label globalNei = globalNumbering().toGlobal(nei[facei]);
281  if (globalNei != exclude0 && globalNei != exclude1)
282  {
283  globals.insert(globalNei);
284  }
285  }
286  else
287  {
288  label bFacei = facei-mesh().nInternalFaces();
289 
290  if (isValidBFace[bFacei])
291  {
292  label globalI = globalNumbering().toGlobal
293  (
294  mesh().nCells()
295  + bFacei
296  );
297 
298  if (globalI != exclude0 && globalI != exclude1)
299  {
300  globals.insert(globalI);
301  }
302  }
303  }
304  }
305 }
306 
307 
309 (
310  const boolList& isValidBFace,
311  const labelList& faceLabels,
312  labelHashSet& globals
313 ) const
314 {
315  globals.clear();
316 
317  insertFaceCells
318  (
319  -1,
320  -1,
321  isValidBFace,
322  faceLabels,
323  globals
324  );
325 
326  return globals.toc();
327 }
328 
329 
331 (
332  const labelListList& globalCellCells,
333  labelListList& faceStencil
334 ) const
335 {
336  // Calculates per face a list of global cell/face indices.
337 
338  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
339  const label nBnd = mesh_.nBoundaryFaces();
340  const labelList& own = mesh_.faceOwner();
341  const labelList& nei = mesh_.faceNeighbour();
342 
343 
344  // Determine neighbouring global cell Cells
345  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
346 
347  labelListList neiGlobalCellCells(nBnd);
348  forAll(patches, patchi)
349  {
350  const polyPatch& pp = patches[patchi];
351 
352  if (pp.coupled())
353  {
354  label facei = pp.start();
355 
356  forAll(pp, i)
357  {
358  neiGlobalCellCells[facei-mesh_.nInternalFaces()] =
359  globalCellCells[own[facei]];
360  facei++;
361  }
362  }
363  }
364  //syncTools::swapBoundaryFaceList(mesh_, neiGlobalCellCells);
366  (
367  mesh_,
368  neiGlobalCellCells,
369  eqOp<labelList>(),
371  );
372 
373 
374 
375  // Construct stencil in global numbering
376  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
377 
378  faceStencil.setSize(mesh_.nFaces());
379 
380  labelHashSet faceStencilSet;
381 
382  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
383  {
384  faceStencilSet.clear();
385 
386  const labelList& ownCCells = globalCellCells[own[facei]];
387  label globalOwn = ownCCells[0];
388  faceStencilSet.insert(ownCCells); // Insert cellCells
389 
390  const labelList& neiCCells = globalCellCells[nei[facei]];
391  label globalNei = neiCCells[0];
392  faceStencilSet.insert(neiCCells); // Insert cellCells
393 
394  // Guarantee owner first, neighbour second.
395  faceStencil[facei].setSize(faceStencilSet.size());
396  label n = 0;
397  faceStencil[facei][n++] = globalOwn;
398  faceStencil[facei][n++] = globalNei;
399  for (const label stencili : faceStencilSet)
400  {
401  if (stencili != globalOwn && stencili != globalNei)
402  {
403  faceStencil[facei][n++] = stencili;
404  }
405  }
406  //Pout<< "internalface:" << facei << " toc:" << faceStencilSet.toc()
407  // << " faceStencil:" << faceStencil[facei] << endl;
408  }
409  forAll(patches, patchi)
410  {
411  const polyPatch& pp = patches[patchi];
412  label facei = pp.start();
413 
414  if (pp.coupled())
415  {
416  forAll(pp, i)
417  {
418  faceStencilSet.clear();
419 
420  const labelList& ownCCells = globalCellCells[own[facei]];
421  label globalOwn = ownCCells[0];
422  faceStencilSet.insert(ownCCells);
423 
424  // And the neighbours of the coupled cell
425  const labelList& neiCCells =
426  neiGlobalCellCells[facei-mesh_.nInternalFaces()];
427  label globalNei = neiCCells[0];
428  faceStencilSet.insert(neiCCells);
429 
430  // Guarantee owner first, neighbour second.
431  faceStencil[facei].setSize(faceStencilSet.size());
432  label n = 0;
433  faceStencil[facei][n++] = globalOwn;
434  faceStencil[facei][n++] = globalNei;
435  for (const label stencili : faceStencilSet)
436  {
437  if (stencili != globalOwn && stencili != globalNei)
438  {
439  faceStencil[facei][n++] = stencili;
440  }
441  }
442 
443  //Pout<< "coupledface:" << facei
444  // << " toc:" << faceStencilSet.toc()
445  // << " faceStencil:" << faceStencil[facei] << endl;
446 
447  facei++;
448  }
449  }
450  else if (!isA<emptyPolyPatch>(pp))
451  {
452  forAll(pp, i)
453  {
454  faceStencilSet.clear();
455 
456  const labelList& ownCCells = globalCellCells[own[facei]];
457  label globalOwn = ownCCells[0];
458  faceStencilSet.insert(ownCCells);
459 
460  // Guarantee owner first
461  faceStencil[facei].setSize(faceStencilSet.size());
462  label n = 0;
463  faceStencil[facei][n++] = globalOwn;
464  for (const label stencili : faceStencilSet)
465  {
466  if (stencili != globalOwn)
467  {
468  faceStencil[facei][n++] = stencili;
469  }
470  }
471 
472  //Pout<< "boundaryface:" << facei
473  // << " toc:" << faceStencilSet.toc()
474  // << " faceStencil:" << faceStencil[facei] << endl;
475 
476  facei++;
477  }
478  }
479  }
480 }
481 
482 
483 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
484 
486 :
487  mesh_(mesh),
488  globalNumbering_(mesh_.nCells()+mesh_.nBoundaryFaces())
489 {}
490 
491 
492 // ************************************************************************* //
Foam::cellToFaceStencil::cellToFaceStencil
cellToFaceStencil(const polyMesh &)
Construct from mesh.
Definition: cellToFaceStencil.C:485
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Foam::cellToFaceStencil::validBoundaryFaces
void validBoundaryFaces(boolList &isValidBFace) const
Valid boundary faces (not empty and not coupled)
Definition: cellToFaceStencil.C:166
Foam::cellToFaceStencil::mesh
const polyMesh & mesh() const
Definition: cellToFaceStencil.H:138
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::HashTable::toc
List< Key > toc() const
The table of contents (the keys) in unsorted order.
Definition: HashTable.C:121
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::syncTools::syncBoundaryFaceList
static void syncBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const TransformOp &top, const bool parRun=Pstream::parRun())
Synchronize values on boundary faces only.
Definition: syncToolsTemplates.C:927
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:327
dummyTransform.H
Dummy transform to be used with syncTools.
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::dummyTransform
Definition: dummyTransform.H:46
Foam::HashSet< label, Hash< label > >
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
n
label n
Definition: TABSMDCalcMethod2.H:31
SortableList.H
Foam::label
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:62
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:241
Foam::IndirectList
A List with indirect addressing.
Definition: IndirectList.H:56
Foam::cellToFaceStencil::merge
static void merge(const label global0, const label global1, const labelList &listA, labelList &listB)
Merge two lists.
Definition: cellToFaceStencil.C:38
Foam::findSortedIndex
label findSortedIndex(const ListType &input, typename ListType::const_reference val, const label start=0)
Foam::FatalError
error FatalError
Foam::eqOp
Definition: ops.H:71
Foam::cellToFaceStencil::allCoupledFacesPatch
autoPtr< indirectPrimitivePatch > allCoupledFacesPatch() const
Return patch of all coupled faces.
Definition: cellToFaceStencil.C:189
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::cellToFaceStencil::calcFaceStencil
void calcFaceStencil(const labelListList &globalCellCells, labelListList &faceStencil) const
Collect cell neighbours into extended stencil.
Definition: cellToFaceStencil.C:331
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:311
emptyPolyPatch.H
Foam::cellToFaceStencil::insertFaceCells
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.
Definition: cellToFaceStencil.C:257
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::HashTable::clear
void clear()
Clear all entries from table.
Definition: HashTable.C:630
Foam::List< label >
Foam::cellToFaceStencil::calcFaceCells
labelList calcFaceCells(const boolList &nonEmptyFace, const labelList &faceLabels, labelHashSet &globals) const
Collect cell neighbours of faces in global numbering.
Definition: cellToFaceStencil.C:309
cellToFaceStencil.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:182
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
y
scalar y
Definition: LISASMDCalcMethod1.H:14