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-------------------------------------------------------------------------------
11License
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
30#include "syncTools.H"
31#include "emptyPolyPatch.H"
32#include "dummyTransform.H"
33
34// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35
36void 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
71void 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// ************************************************************************* //
label n
All cells connected via edge to face.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
void clear()
Clear all entries from table.
Definition: HashTable.C:678
void transfer(List< labelList > &list)
Definition: List.C:447
Base class for extended cell-to-face stencils (face values from neighbouring cells)
const polyMesh & mesh() const
labelList calcFaceCells(const boolList &nonEmptyFace, const labelList &faceLabels, labelHashSet &globals) const
Collect cell neighbours of faces in global numbering.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
label nInternalFaces() const noexcept
Number of internal faces.
const labelListList & edgeFaces() const
const labelListList & faceEdges() const
static void syncEdgeMap(const polyMesh &mesh, EdgeMap< T > &edgeValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected edges.
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
Dummy transform to be used with syncTools.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
List< label > labelList
A List of labels.
Definition: List.H:66
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
errorManip< error > abort(error &err)
Definition: errorManip.H:144
List< bool > boolList
A List of bools.
Definition: List.H:64
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
error FatalError
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333