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