FECCellToFaceStencil.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-2020 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 "FECCellToFaceStencil.H"
30 #include "syncTools.H"
31 #include "emptyPolyPatch.H"
32 #include "dummyTransform.H"
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 void Foam::FECCellToFaceStencil::calcEdgeBoundaryData
37 (
38  const boolList& isValidBFace,
39  const labelList& boundaryEdges,
40  EdgeMap<labelList>& neiGlobal
41 ) const
42 {
43  neiGlobal.resize(2*boundaryEdges.size());
44 
45  labelHashSet edgeGlobals;
46 
47  for (const label edgeI : boundaryEdges)
48  {
49  neiGlobal.insert
50  (
51  mesh().edges()[edgeI],
53  (
54  isValidBFace,
55  mesh().edgeFaces(edgeI),
56  edgeGlobals
57  )
58  );
59  }
60 
62  (
63  mesh(),
64  neiGlobal,
65  ListOps::unionEqOp(),
66  dummyTransform()
67  );
68 }
69 
70 
71 void Foam::FECCellToFaceStencil::calcFaceStencil
72 (
73  labelListList& faceStencil
74 ) const
75 {
76  const polyBoundaryMesh& patches = mesh().boundaryMesh();
77  const label nBnd = mesh().nBoundaryFaces();
78  const labelList& own = mesh().faceOwner();
79  const labelList& nei = mesh().faceNeighbour();
80 
81 
82 
83  // Determine neighbouring global cell
84  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85 
86  labelList neiGlobalCell(nBnd);
87  forAll(patches, patchi)
88  {
89  const polyPatch& pp = patches[patchi];
90 
91  if (pp.coupled())
92  {
93  label facei = pp.start();
94 
95  forAll(pp, i)
96  {
97  neiGlobalCell[facei-mesh().nInternalFaces()] =
98  globalNumbering().toGlobal(own[facei]);
99  facei++;
100  }
101  }
102  }
103  syncTools::swapBoundaryFaceList(mesh(), neiGlobalCell);
104 
105 
106 
107  // Determine on coupled edges the edge cells on the other side
108  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
109 
110  // Calculate edges on coupled patches
111  labelList boundaryEdges
112  (
113  allCoupledFacesPatch()().meshEdges
114  (
115  mesh().edges(),
116  mesh().pointEdges()
117  )
118  );
119 
120  // Mark boundary faces to be included in stencil (i.e. not coupled or empty)
121  boolList isValidBFace;
122  validBoundaryFaces(isValidBFace);
123 
124  // Swap edgeCells for coupled edges. Note: use EdgeMap for now since we've
125  // got syncTools::syncEdgeMap for those. Should be replaced with Map and
126  // syncTools functionality to handle those.
127  EdgeMap<labelList> neiGlobal;
128  calcEdgeBoundaryData
129  (
130  isValidBFace,
131  boundaryEdges,
132  neiGlobal
133  );
134 
135 
136 
137  // Construct stencil in global numbering
138  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139 
140  faceStencil.setSize(mesh().nFaces());
141 
142  // Do coupled edges first
143 
144  forAll(boundaryEdges, i)
145  {
146  label edgeI = boundaryEdges[i];
147 
148  const labelList& eGlobals = neiGlobal[mesh().edges()[edgeI]];
149 
150  // Distribute to all edgeFaces
151  const labelList& eFaces = mesh().edgeFaces(edgeI);
152 
153  forAll(eFaces, j)
154  {
155  label facei = eFaces[j];
156 
157  // Insert eGlobals into faceStencil.
158  merge(-1, -1, eGlobals, faceStencil[facei]);
159  }
160  }
161  neiGlobal.clear();
162 
163 
164  // Do remaining edges by looping over all faces
165 
166  // Work arrays
167  DynamicList<label> fEdgesSet;
168  DynamicList<label> eFacesSet;
169  labelHashSet faceStencilSet;
170 
171  for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
172  {
173  label globalOwn = globalNumbering().toGlobal(own[facei]);
174  label globalNei = globalNumbering().toGlobal(nei[facei]);
175 
176  // Convert any existing faceStencil (from coupled edges) into
177  // set and operate on this.
178 
179  faceStencilSet.clear();
180 
181  // Insert all but global owner and neighbour
182  forAll(faceStencil[facei], i)
183  {
184  label globalI = faceStencil[facei][i];
185  if (globalI != globalOwn && globalI != globalNei)
186  {
187  faceStencilSet.insert(globalI);
188  }
189  }
190  faceStencil[facei].clear();
191 
192  // Collect all edge connected (internal) cells
193  const labelList& fEdges = mesh().faceEdges(facei, fEdgesSet);
194 
195  forAll(fEdges, i)
196  {
197  label edgeI = fEdges[i];
198 
199  insertFaceCells
200  (
201  globalOwn,
202  globalNei,
203  isValidBFace,
204  mesh().edgeFaces(edgeI, eFacesSet),
205  faceStencilSet
206  );
207  }
208 
209  // Extract, guarantee owner first, neighbour second.
210  faceStencil[facei].setSize(faceStencilSet.size()+2);
211  label n = 0;
212  faceStencil[facei][n++] = globalOwn;
213  faceStencil[facei][n++] = globalNei;
214  for (const label stencili : faceStencilSet)
215  {
216  if (stencili == globalOwn || stencili == globalNei)
217  {
219  << "problem:" << faceStencilSet
220  << abort(FatalError);
221  }
222  faceStencil[facei][n++] = stencili;
223  }
224  }
225  forAll(patches, patchi)
226  {
227  const polyPatch& pp = patches[patchi];
228  label facei = pp.start();
229 
230  if (pp.coupled())
231  {
232  forAll(pp, i)
233  {
234  label globalOwn = globalNumbering().toGlobal(own[facei]);
235  label globalNei = neiGlobalCell[facei-mesh().nInternalFaces()];
236 
237  // Convert any existing faceStencil (from coupled edges) into
238  // set and operate on this.
239 
240  faceStencilSet.clear();
241 
242  // Insert all but global owner and neighbour
243  forAll(faceStencil[facei], i)
244  {
245  label globalI = faceStencil[facei][i];
246  if (globalI != globalOwn && globalI != globalNei)
247  {
248  faceStencilSet.insert(globalI);
249  }
250  }
251  faceStencil[facei].clear();
252 
253  // Collect all edge connected (internal) cells
254  const labelList& fEdges = mesh().faceEdges(facei, fEdgesSet);
255 
256  forAll(fEdges, i)
257  {
258  label edgeI = fEdges[i];
259 
260  insertFaceCells
261  (
262  globalOwn,
263  globalNei,
264  isValidBFace,
265  mesh().edgeFaces(edgeI, eFacesSet),
266  faceStencilSet
267  );
268  }
269 
270  // Extract, guarantee owner first, neighbour second.
271  faceStencil[facei].setSize(faceStencilSet.size()+2);
272  label n = 0;
273  faceStencil[facei][n++] = globalOwn;
274  faceStencil[facei][n++] = globalNei;
275  for (const label stencili : faceStencilSet)
276  {
277  if (stencili == globalOwn || stencili == globalNei)
278  {
280  << "problem:" << faceStencilSet
281  << abort(FatalError);
282  }
283  faceStencil[facei][n++] = stencili;
284  }
285 
286  if (n != faceStencil[facei].size())
287  {
289  << " size:" << faceStencil[facei].size()
290  << abort(FatalError);
291  }
292 
293  facei++;
294  }
295  }
296  else if (!isA<emptyPolyPatch>(pp))
297  {
298  forAll(pp, i)
299  {
300  label globalOwn = globalNumbering().toGlobal(own[facei]);
301 
302  // Convert any existing faceStencil (from coupled edges) into
303  // set and operate on this.
304 
305  faceStencilSet.clear();
306 
307  // Insert all but global owner and neighbour
308  forAll(faceStencil[facei], i)
309  {
310  label globalI = faceStencil[facei][i];
311  if (globalI != globalOwn)
312  {
313  faceStencilSet.insert(globalI);
314  }
315  }
316  faceStencil[facei].clear();
317 
318  // Collect all edge connected (internal) cells
319  const labelList& fEdges = mesh().faceEdges(facei, fEdgesSet);
320 
321  forAll(fEdges, i)
322  {
323  label edgeI = fEdges[i];
324 
325  insertFaceCells
326  (
327  globalOwn,
328  -1,
329  isValidBFace,
330  mesh().edgeFaces(edgeI, eFacesSet),
331  faceStencilSet
332  );
333  }
334 
335  // Extract, guarantee owner first, neighbour second.
336  faceStencil[facei].setSize(faceStencilSet.size()+1);
337  label n = 0;
338  faceStencil[facei][n++] = globalOwn;
339  for (const label stencili : faceStencilSet)
340  {
341  if (stencili == globalOwn)
342  {
344  << "problem:" << faceStencilSet
345  << abort(FatalError);
346  }
347  faceStencil[facei][n++] = stencili;
348  }
349 
350  facei++;
351  }
352  }
353  }
354 
355 
356  for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
357  {
358  label globalOwn = globalNumbering().toGlobal(own[facei]);
359  if (faceStencil[facei][0] != globalOwn)
360  {
362  << "problem:" << faceStencil[facei]
363  << " globalOwn:" << globalOwn
364  << abort(FatalError);
365  }
366  label globalNei = globalNumbering().toGlobal(nei[facei]);
367  if (faceStencil[facei][1] != globalNei)
368  {
370  << "problem:" << faceStencil[facei]
371  << " globalNei:" << globalNei
372  << abort(FatalError);
373  }
374  }
375 
376 
377  forAll(patches, patchi)
378  {
379  const polyPatch& pp = patches[patchi];
380 
381  if (pp.coupled())
382  {
383  forAll(pp, i)
384  {
385  label facei = pp.start()+i;
386 
387  label globalOwn = globalNumbering().toGlobal(own[facei]);
388  if (faceStencil[facei][0] != globalOwn)
389  {
391  << "problem:" << faceStencil[facei]
392  << " globalOwn:" << globalOwn
393  << abort(FatalError);
394  }
395  label globalNei = neiGlobalCell[facei-mesh().nInternalFaces()];
396  if (faceStencil[facei][1] != globalNei)
397  {
399  << "problem:" << faceStencil[facei]
400  << " globalNei:" << globalNei
401  << abort(FatalError);
402  }
403  }
404  }
405  else if (!isA<emptyPolyPatch>(pp))
406  {
407  forAll(pp, i)
408  {
409  label facei = pp.start()+i;
410 
411  label globalOwn = globalNumbering().toGlobal(own[facei]);
412  if (faceStencil[facei][0] != globalOwn)
413  {
415  << "problem:" << faceStencil[facei]
416  << " globalOwn:" << globalOwn
417  << abort(FatalError);
418  }
419  }
420  }
421  }
422 }
423 
424 
425 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
426 
428 :
430 {
431  // Calculate per face the (edge) connected cells (in global numbering)
432  labelListList faceStencil;
433  calcFaceStencil(faceStencil);
434 
435  // Transfer to *this
436  transfer(faceStencil);
437 }
438 
439 
440 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::cellToFaceStencil::mesh
const polyMesh & mesh() const
Definition: cellToFaceStencil.H:131
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:34
dummyTransform.H
Dummy transform to be used with syncTools.
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:505
syncTools.H
Foam::polyBoundaryMesh::start
label start() const
The start label of the boundary faces in the polyMesh face list.
Definition: polyBoundaryMesh.C:611
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:296
n
label n
Definition: TABSMDCalcMethod2.H:31
FECCellToFaceStencil.H
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::primitiveMesh::faceEdges
const labelListList & faceEdges() const
Definition: primitiveMeshEdges.C:528
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
emptyPolyPatch.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::List< labelList >
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:286
Foam::syncTools::syncEdgeMap
static void syncEdgeMap(const polyMesh &mesh, EdgeMap< T > &edgeValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected edges.
Definition: syncToolsTemplates.C:365
Foam::cellToFaceStencil
Base class for extended cell-to-face stencils (face values from neighbouring cells)
Definition: cellToFaceStencil.H:56
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
Foam::FECCellToFaceStencil::FECCellToFaceStencil
FECCellToFaceStencil(const polyMesh &)
Construct from all cells and boundary faces.
Definition: FECCellToFaceStencil.C:427
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113