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