1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 - use pointCells when searching for connectivity
28 - initialize the cell connectivity with '-1'
29 - find both cell faces corresponding to the baffles and mark them
30 to prevent a connection
31 - standard connectivity checks
33 - added baffle support
35 \*---------------------------------------------------------------------------*/
37 #include "meshReader.H"
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 void Foam::meshReader::createPolyCells()
43 // loop through all cell faces and create connectivity. This will produce
44 // a global face list and will describe all cells as lists of face labels
46 const faceListList& cFaces = cellFaces();
48 // count the maximum number of faces and set the size of the cellPolys_
49 cellPolys_.setSize(cFaces.size());
53 forAll(cellPolys_, cellI)
55 cellPolys_[cellI].setSize(cFaces[cellI].size(), -1);
57 maxFaces += cFaces[cellI].size();
60 Info<< "Maximum possible number of faces in mesh: " << maxFaces << endl;
62 meshFaces_.setSize(maxFaces);
64 // set reference to point-cell addressing
65 const labelListList& ptCells = pointCells();
67 // size the baffle lists and initialize to -1
68 baffleIds_.setSize(baffleFaces_.size());
69 forAll(baffleIds_, baffleI)
71 baffleIds_[baffleI].setSize(2);
74 // block off baffles first
76 // To prevent internal faces, we'll mark the cell faces
77 // with negative cell ids (offset by nCells).
79 // cellI = -(nCells + baffleI)
81 // To distinguish these from the normal '-1' marker, we require
82 // cellI = -(nCells + baffleI) < -1
84 // This condition is met provided that nCells > 1.
85 // ie., baffles require at least 2 volume cells
87 label baffleOffset = cFaces.size();
88 forAll(baffleFaces_, baffleI)
90 label cellI = -(baffleOffset + baffleI);
91 const face& curFace = baffleFaces_[baffleI];
93 // get the list of labels
94 const labelList& curPoints = curFace;
96 // a baffle is a single face - only need to match one face
97 // get the list of cells sharing this point
98 const labelList& curNeighbours = ptCells[curPoints[0]];
100 label nNeighbours = 0;
102 // For all neighbours
103 forAll(curNeighbours, neiI)
105 label curNei = curNeighbours[neiI];
107 // get the list of search faces
108 const faceList& searchFaces = cFaces[curNei];
110 forAll(searchFaces, neiFaceI)
112 int cmp = face::compare(curFace, searchFaces[neiFaceI]);
116 // maintain baffle orientation
117 // side0: baffle normal same as attached face
118 // side1: baffle normal opposite from attached face
126 #ifdef DEBUG_FACE_ORDERING
127 Info<< "cmp " << cmp << " matched " << curFace
128 << " with " << searchFaces[neiFaceI]
132 Info<< "match " << baffleI
133 << " (" << origCellId_[baffleOffset+baffleI] << ")"
135 << " against cell " << curNei
136 << " face " << neiFaceI
137 << " curFace " << curFace[1]
138 << " neiFace " << searchFaces[neiFaceI][1]
142 if (baffleIds_[baffleI][side].unused())
144 baffleIds_[baffleI][side] = cellFaceIdentifier
154 Info<< "multiple matches for side " << side
155 << " of baffle " << baffleI
156 << " (original cell "
157 << origCellId_[baffleOffset+baffleI] << ")"
163 if (nNeighbours >= 2) break;
166 if (nNeighbours == 2)
168 for (label side = 0; side < nNeighbours; ++side)
170 label neiCell = baffleIds_[baffleI][side].cell;
171 label neiFace = baffleIds_[baffleI][side].face;
173 if (baffleIds_[baffleI][side].used())
175 cellPolys_[neiCell][neiFace] = cellI;
181 Info<< "drop baffle " << baffleI
182 << " (original cell "
183 << origCellId_[baffleOffset+baffleI] << ")"
184 << " with " << nNeighbours << " neighbours" << endl;
186 baffleFaces_[baffleI].clear();
187 baffleIds_[baffleI].clear();
191 #ifdef DEBUG_CELLPOLY
192 Info<< "cellPolys_" << cellPolys_ << endl;
193 Info<< "baffleFaces_" << baffleFaces_ << endl;
194 Info<< "baffleIds_" << baffleIds_ << endl;
201 forAll(cFaces, cellI)
204 // Insertion cannot be done in one go as the faces need to be
205 // added into the list in the increasing order of neighbour
206 // cells. Therefore, all neighbours will be detected first
207 // and then added in the correct order.
209 const faceList& curFaces = cFaces[cellI];
211 // Record the neighbour cell
212 labelList neiCells(curFaces.size(), -1);
214 // Record the face of neighbour cell
215 labelList faceOfNeiCell(curFaces.size(), -1);
217 label nNeighbours = 0;
220 forAll(curFaces, faceI)
222 // Skip already matched faces or those tagged by baffles
223 if (cellPolys_[cellI][faceI] != -1) continue;
227 const face& curFace = curFaces[faceI];
229 // get the list of labels
230 const labelList& curPoints = curFace;
233 forAll(curPoints, pointI)
235 // get the list of cells sharing this point
236 const labelList& curNeighbours = ptCells[curPoints[pointI]];
238 // For all neighbours
239 forAll(curNeighbours, neiI)
241 label curNei = curNeighbours[neiI];
243 // reject neighbours with the lower label. This should
244 // also reject current cell.
247 // get the list of search faces
248 const faceList& searchFaces = cFaces[curNei];
250 forAll(searchFaces, neiFaceI)
252 if (searchFaces[neiFaceI] == curFace)
254 // Record the neighbour cell and face
255 neiCells[faceI] = curNei;
256 faceOfNeiCell[faceI] = neiFaceI;
258 #ifdef DEBUG_FACE_ORDERING
259 Info<< " cell " << cellI
261 << " point " << pointI
263 << " neiFace " << neiFaceI
275 } // End of current points
276 } // End of current faces
278 // Add the faces in the increasing order of neighbours
279 for (label neiSearch = 0; neiSearch < nNeighbours; neiSearch++)
281 // Find the lowest neighbour which is still valid
283 label minNei = cellPolys_.size();
285 forAll(neiCells, ncI)
287 if (neiCells[ncI] > -1 && neiCells[ncI] < minNei)
290 minNei = neiCells[ncI];
296 // Add the face to the list of faces
297 meshFaces_[nInternalFaces_] = curFaces[nextNei];
300 cellPolys_[cellI][nextNei] = nInternalFaces_;
302 // Mark for neighbour
303 cellPolys_[neiCells[nextNei]][faceOfNeiCell[nextNei]] =
306 // Stop the neighbour from being used again
307 neiCells[nextNei] = -1;
309 // Increment number of faces counter
314 FatalErrorIn("meshReader::createPolyCells()")
315 << "Error in internal face insertion"
316 << abort(FatalError);
321 #ifdef DEBUG_CELLPOLY
322 Info<< "cellPolys = " << cellPolys_ << endl;
325 // don't reset the size of internal faces, because more faces will be
326 // added in createPolyBoundary()
330 // ************************************************************************* //