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/>.
26 - use pointCells when searching for connectivity
27 - initialize the cell connectivity with '-1'
28 - find both cell faces corresponding to the baffles and mark them
29 to prevent a connection
30 - standard connectivity checks
32 - added baffle support
34 \*---------------------------------------------------------------------------*/
36 #include "meshReader.H"
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 void Foam::meshReader::createPolyCells()
42 // loop through all cell faces and create connectivity. This will produce
43 // a global face list and will describe all cells as lists of face labels
45 const faceListList& cFaces = cellFaces();
47 // count the maximum number of faces and set the size of the cellPolys_
48 cellPolys_.setSize(cFaces.size());
52 forAll(cellPolys_, cellI)
54 cellPolys_[cellI].setSize(cFaces[cellI].size(), -1);
56 maxFaces += cFaces[cellI].size();
59 Info<< "Maximum possible number of faces in mesh: " << maxFaces << endl;
61 meshFaces_.setSize(maxFaces);
63 // set reference to point-cell addressing
64 const labelListList& ptCells = pointCells();
66 // size the baffle lists and initialize to -1
67 baffleIds_.setSize(baffleFaces_.size());
68 forAll(baffleIds_, baffleI)
70 baffleIds_[baffleI].setSize(2);
73 // block off baffles first
75 // To prevent internal faces, we'll mark the cell faces
76 // with negative cell ids (offset by nCells).
78 // cellI = -(nCells + baffleI)
80 // To distinguish these from the normal '-1' marker, we require
81 // cellI = -(nCells + baffleI) < -1
83 // This condition is met provided that nCells > 1.
84 // ie., baffles require at least 2 volume cells
86 label baffleOffset = cFaces.size();
87 forAll(baffleFaces_, baffleI)
89 label cellI = -(baffleOffset + baffleI);
90 const face& curFace = baffleFaces_[baffleI];
92 // get the list of labels
93 const labelList& curPoints = curFace;
95 // a baffle is a single face - only need to match one face
96 // get the list of cells sharing this point
97 const labelList& curNeighbours = ptCells[curPoints[0]];
99 label nNeighbours = 0;
101 // For all neighbours
102 forAll(curNeighbours, neiI)
104 label curNei = curNeighbours[neiI];
106 // get the list of search faces
107 const faceList& searchFaces = cFaces[curNei];
109 forAll(searchFaces, neiFaceI)
111 int cmp = face::compare(curFace, searchFaces[neiFaceI]);
115 // maintain baffle orientation
116 // side0: baffle normal same as attached face
117 // side1: baffle normal opposite from attached face
125 #ifdef DEBUG_FACE_ORDERING
126 Info<< "cmp " << cmp << " matched " << curFace
127 << " with " << searchFaces[neiFaceI]
131 Info<< "match " << baffleI
132 << " (" << origCellId_[baffleOffset+baffleI] << ")"
134 << " against cell " << curNei
135 << " face " << neiFaceI
136 << " curFace " << curFace[1]
137 << " neiFace " << searchFaces[neiFaceI][1]
141 if (baffleIds_[baffleI][side].unused())
143 baffleIds_[baffleI][side] = cellFaceIdentifier
153 Info<< "multiple matches for side " << side
154 << " of baffle " << baffleI
155 << " (original cell "
156 << origCellId_[baffleOffset+baffleI] << ")"
162 if (nNeighbours >= 2) break;
165 if (nNeighbours == 2)
167 for (label side = 0; side < nNeighbours; ++side)
169 label neiCell = baffleIds_[baffleI][side].cell;
170 label neiFace = baffleIds_[baffleI][side].face;
172 if (baffleIds_[baffleI][side].used())
174 cellPolys_[neiCell][neiFace] = cellI;
180 Info<< "drop baffle " << baffleI
181 << " (original cell "
182 << origCellId_[baffleOffset+baffleI] << ")"
183 << " with " << nNeighbours << " neighbours" << endl;
185 baffleFaces_[baffleI].clear();
186 baffleIds_[baffleI].clear();
190 #ifdef DEBUG_CELLPOLY
191 Info<< "cellPolys_" << cellPolys_ << endl;
192 Info<< "baffleFaces_" << baffleFaces_ << endl;
193 Info<< "baffleIds_" << baffleIds_ << endl;
200 forAll(cFaces, cellI)
203 // Insertion cannot be done in one go as the faces need to be
204 // added into the list in the increasing order of neighbour
205 // cells. Therefore, all neighbours will be detected first
206 // and then added in the correct order.
208 const faceList& curFaces = cFaces[cellI];
210 // Record the neighbour cell
211 labelList neiCells(curFaces.size(), -1);
213 // Record the face of neighbour cell
214 labelList faceOfNeiCell(curFaces.size(), -1);
216 label nNeighbours = 0;
219 forAll(curFaces, faceI)
221 // Skip already matched faces or those tagged by baffles
222 if (cellPolys_[cellI][faceI] != -1) continue;
226 const face& curFace = curFaces[faceI];
228 // get the list of labels
229 const labelList& curPoints = curFace;
232 forAll(curPoints, pointI)
234 // get the list of cells sharing this point
235 const labelList& curNeighbours = ptCells[curPoints[pointI]];
237 // For all neighbours
238 forAll(curNeighbours, neiI)
240 label curNei = curNeighbours[neiI];
242 // reject neighbours with the lower label. This should
243 // also reject current cell.
246 // get the list of search faces
247 const faceList& searchFaces = cFaces[curNei];
249 forAll(searchFaces, neiFaceI)
251 if (searchFaces[neiFaceI] == curFace)
253 // Record the neighbour cell and face
254 neiCells[faceI] = curNei;
255 faceOfNeiCell[faceI] = neiFaceI;
257 #ifdef DEBUG_FACE_ORDERING
258 Info<< " cell " << cellI
260 << " point " << pointI
262 << " neiFace " << neiFaceI
274 } // End of current points
275 } // End of current faces
277 // Add the faces in the increasing order of neighbours
278 for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++)
280 // Find the lowest neighbour which is still valid
282 label minNei = cellPolys_.size();
284 forAll(neiCells, ncI)
286 if (neiCells[ncI] > -1 && neiCells[ncI] < minNei)
289 minNei = neiCells[ncI];
295 // Add the face to the list of faces
296 meshFaces_[nInternalFaces_] = curFaces[nextNei];
299 cellPolys_[cellI][nextNei] = nInternalFaces_;
301 // Mark for neighbour
302 cellPolys_[neiCells[nextNei]][faceOfNeiCell[nextNei]] =
305 // Stop the neighbour from being used again
306 neiCells[nextNei] = -1;
308 // Increment number of faces counter
313 FatalErrorIn("meshReader::createPolyCells()")
314 << "Error in internal face insertion"
315 << abort(FatalError);
320 #ifdef DEBUG_CELLPOLY
321 Info<< "cellPolys = " << cellPolys_ << endl;
324 // don't reset the size of internal faces, because more faces will be
325 // added in createPolyBoundary()
329 // ************************************************************************* //