1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "FECCellToFaceStencil.H"
27 #include "syncTools.H"
28 #include "emptyPolyPatch.H"
29 #include "dummyTransform.H"
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 // Calculates per edge the neighbour data (= edgeCells)
34 void Foam::FECCellToFaceStencil::calcEdgeBoundaryData
36 const boolList& isValidBFace,
37 const labelList& boundaryEdges,
38 EdgeMap<labelList>& neiGlobal
41 neiGlobal.resize(2*boundaryEdges.size());
43 labelHashSet edgeGlobals;
45 forAll(boundaryEdges, i)
47 label edgeI = boundaryEdges[i];
51 mesh().edges()[edgeI],
55 mesh().edgeFaces(edgeI),
61 syncTools::syncEdgeMap(mesh(), neiGlobal, unionEqOp(), dummyTransform());
65 // Calculates per face the edge connected data (= cell or boundary in global
67 void Foam::FECCellToFaceStencil::calcFaceStencil
69 labelListList& faceStencil
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();
79 // Determine neighbouring global cell
80 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82 labelList neiGlobalCell(nBnd);
83 forAll(patches, patchI)
85 const polyPatch& pp = patches[patchI];
89 label faceI = pp.start();
93 neiGlobalCell[faceI-mesh().nInternalFaces()] =
94 globalNumbering().toGlobal(own[faceI]);
99 syncTools::swapBoundaryFaceList(mesh(), neiGlobalCell);
103 // Determine on coupled edges the edge cells on the other side
104 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106 // Calculate edges on coupled patches
107 labelList boundaryEdges
109 allCoupledFacesPatch()().meshEdges
116 // Mark boundary faces to be included in stencil (i.e. not coupled or empty)
117 boolList isValidBFace;
118 validBoundaryFaces(isValidBFace);
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;
133 // Construct stencil in global numbering
134 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
136 faceStencil.setSize(mesh().nFaces());
138 // Do coupled edges first
140 forAll(boundaryEdges, i)
142 label edgeI = boundaryEdges[i];
144 const labelList& eGlobals = neiGlobal[mesh().edges()[edgeI]];
146 // Distribute to all edgeFaces
147 const labelList& eFaces = mesh().edgeFaces(edgeI);
151 label faceI = eFaces[j];
153 // Insert eGlobals into faceStencil.
154 merge(-1, -1, eGlobals, faceStencil[faceI]);
160 // Do remaining edges by looping over all faces
163 DynamicList<label> fEdgesSet;
164 DynamicList<label> eFacesSet;
165 labelHashSet faceStencilSet;
167 for (label faceI = 0; faceI < mesh().nInternalFaces(); faceI++)
169 label globalOwn = globalNumbering().toGlobal(own[faceI]);
170 label globalNei = globalNumbering().toGlobal(nei[faceI]);
172 // Convert any existing faceStencil (from coupled edges) into
173 // set and operate on this.
175 faceStencilSet.clear();
177 // Insert all but global owner and neighbour
178 forAll(faceStencil[faceI], i)
180 label globalI = faceStencil[faceI][i];
181 if (globalI != globalOwn && globalI != globalNei)
183 faceStencilSet.insert(globalI);
186 faceStencil[faceI].clear();
188 // Collect all edge connected (internal) cells
189 const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
193 label edgeI = fEdges[i];
200 mesh().edgeFaces(edgeI, eFacesSet),
205 // Extract, guarantee owner first, neighbour second.
206 faceStencil[faceI].setSize(faceStencilSet.size()+2);
208 faceStencil[faceI][n++] = globalOwn;
209 faceStencil[faceI][n++] = globalNei;
210 forAllConstIter(labelHashSet, faceStencilSet, iter)
212 if (iter.key() == globalOwn || iter.key() == globalNei)
214 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
215 << "problem:" << faceStencilSet
216 << abort(FatalError);
218 faceStencil[faceI][n++] = iter.key();
221 forAll(patches, patchI)
223 const polyPatch& pp = patches[patchI];
224 label faceI = pp.start();
230 label globalOwn = globalNumbering().toGlobal(own[faceI]);
231 label globalNei = neiGlobalCell[faceI-mesh().nInternalFaces()];
233 // Convert any existing faceStencil (from coupled edges) into
234 // set and operate on this.
236 faceStencilSet.clear();
238 // Insert all but global owner and neighbour
239 forAll(faceStencil[faceI], i)
241 label globalI = faceStencil[faceI][i];
242 if (globalI != globalOwn && globalI != globalNei)
244 faceStencilSet.insert(globalI);
247 faceStencil[faceI].clear();
249 // Collect all edge connected (internal) cells
250 const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
254 label edgeI = fEdges[i];
261 mesh().edgeFaces(edgeI, eFacesSet),
266 // Extract, guarantee owner first, neighbour second.
267 faceStencil[faceI].setSize(faceStencilSet.size()+2);
269 faceStencil[faceI][n++] = globalOwn;
270 faceStencil[faceI][n++] = globalNei;
271 forAllConstIter(labelHashSet, faceStencilSet, iter)
273 if (iter.key() == globalOwn || iter.key() == globalNei)
277 "FECCellToFaceStencil::calcFaceStencil(..)"
278 ) << "problem:" << faceStencilSet
279 << abort(FatalError);
281 faceStencil[faceI][n++] = iter.key();
284 if (n != faceStencil[faceI].size())
286 FatalErrorIn("problem") << "n:" << n
287 << " size:" << faceStencil[faceI].size()
288 << abort(FatalError);
294 else if (!isA<emptyPolyPatch>(pp))
298 label globalOwn = globalNumbering().toGlobal(own[faceI]);
300 // Convert any existing faceStencil (from coupled edges) into
301 // set and operate on this.
303 faceStencilSet.clear();
305 // Insert all but global owner and neighbour
306 forAll(faceStencil[faceI], i)
308 label globalI = faceStencil[faceI][i];
309 if (globalI != globalOwn)
311 faceStencilSet.insert(globalI);
314 faceStencil[faceI].clear();
316 // Collect all edge connected (internal) cells
317 const labelList& fEdges = mesh().faceEdges(faceI, fEdgesSet);
321 label edgeI = fEdges[i];
328 mesh().edgeFaces(edgeI, eFacesSet),
333 // Extract, guarantee owner first, neighbour second.
334 faceStencil[faceI].setSize(faceStencilSet.size()+1);
336 faceStencil[faceI][n++] = globalOwn;
337 forAllConstIter(labelHashSet, faceStencilSet, iter)
339 if (iter.key() == globalOwn)
343 "FECCellToFaceStencil::calcFaceStencil(..)"
344 ) << "problem:" << faceStencilSet
345 << abort(FatalError);
347 faceStencil[faceI][n++] = iter.key();
356 for (label faceI = 0; faceI < mesh().nInternalFaces(); faceI++)
358 label globalOwn = globalNumbering().toGlobal(own[faceI]);
359 if (faceStencil[faceI][0] != globalOwn)
361 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
362 << "problem:" << faceStencil[faceI]
363 << " globalOwn:" << globalOwn
364 << abort(FatalError);
366 label globalNei = globalNumbering().toGlobal(nei[faceI]);
367 if (faceStencil[faceI][1] != globalNei)
369 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
370 << "problem:" << faceStencil[faceI]
371 << " globalNei:" << globalNei
372 << abort(FatalError);
377 forAll(patches, patchI)
379 const polyPatch& pp = patches[patchI];
385 label faceI = pp.start()+i;
387 label globalOwn = globalNumbering().toGlobal(own[faceI]);
388 if (faceStencil[faceI][0] != globalOwn)
390 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
391 << "problem:" << faceStencil[faceI]
392 << " globalOwn:" << globalOwn
393 << abort(FatalError);
395 label globalNei = neiGlobalCell[faceI-mesh().nInternalFaces()];
396 if (faceStencil[faceI][1] != globalNei)
398 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
399 << "problem:" << faceStencil[faceI]
400 << " globalNei:" << globalNei
401 << abort(FatalError);
405 else if (!isA<emptyPolyPatch>(pp))
409 label faceI = pp.start()+i;
411 label globalOwn = globalNumbering().toGlobal(own[faceI]);
412 if (faceStencil[faceI][0] != globalOwn)
414 FatalErrorIn("FECCellToFaceStencil::calcFaceStencil(..)")
415 << "problem:" << faceStencil[faceI]
416 << " globalOwn:" << globalOwn
417 << abort(FatalError);
425 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
427 Foam::FECCellToFaceStencil::FECCellToFaceStencil(const polyMesh& mesh)
429 cellToFaceStencil(mesh)
431 // Calculate per face the (edge) connected cells (in global numbering)
432 labelListList faceStencil;
433 calcFaceStencil(faceStencil);
436 transfer(faceStencil);
440 // ************************************************************************* //