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