Loading...
Searching...
No Matches
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.reserve(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{
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 }
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
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
Map from edge (expressed as its endpoints) to value. Hashing (and ==) on an edge is symmetric.
Definition edgeHashes.H:59
FECCellToFaceStencil(const polyMesh &)
Construct from all cells and boundary faces.
void transfer(List< labelList > &list)
Base class for extended cell-to-face stencils (face values from neighbouring cells).
cellToFaceStencil(const polyMesh &)
Construct from mesh.
const polyMesh & mesh() const
labelList calcFaceCells(const boolList &nonEmptyFace, const labelList &faceLabels, labelHashSet &globals) const
Collect cell neighbours of faces in global numbering.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
virtual const labelList & faceOwner() const
Return face owner.
Definition polyMesh.C:1101
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition polyMesh.C:1107
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
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, const bool parRun=UPstream::parRun())
Swap coupled boundary face values. Uses eqOp.
Definition syncTools.H:524
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
Dummy transform to be used with syncTools.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
errorManip< error > abort(error &err)
Definition errorManip.H:139
List< bool > boolList
A List of bools.
Definition List.H:60
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299