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 and monitoring support
34 \*---------------------------------------------------------------------------*/
36 #include "meshReader.H"
38 #include "polyPatch.H"
39 #include "emptyPolyPatch.H"
40 #include "preservePatchTypes.H"
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 void Foam::meshReader::addPolyBoundaryFace
47 const label cellFaceId,
48 const label nCreatedFaces
53 << " add bnd for cell " << cellId
54 << " face " << cellFaceId
55 << " (original cell " << origCellId_[cellId] << ")"
59 // standard case: volume cells
60 const face& thisFace = cellFaces_[cellId][cellFaceId];
63 if (cellPolys_[cellId][cellFaceId] > nInternalFaces_)
65 Info<< "meshReader::createPolyBoundary(): "
66 << "Problem with face: " << thisFace << endl
67 << "Probably multiple definitions "
68 << "of a single boundary face." << endl
71 else if (cellPolys_[cellId][cellFaceId] >= 0)
73 Info<< "meshReader::createPolyBoundary(): "
74 << "Problem with face: " << thisFace << endl
75 << "Probably trying to define a boundary face "
76 << "on a previously matched internal face." << endl
78 << meshFaces_[cellPolys_[cellId][cellFaceId]]
82 meshFaces_[nCreatedFaces] = thisFace;
83 cellPolys_[cellId][cellFaceId] = nCreatedFaces;
87 void Foam::meshReader::addPolyBoundaryFace
89 const cellFaceIdentifier& identifier,
90 const label nCreatedFaces
93 addPolyBoundaryFace(identifier.cell, identifier.face, nCreatedFaces);
97 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
99 void Foam::meshReader::createPolyBoundary()
101 label nBoundaryFaces = 0;
102 label nMissingFaces = 0;
103 label nInterfaces = 0;
105 const faceListList& cFaces = cellFaces();
107 // determine number of non-patched faces:
108 forAll(cellPolys_, cellI)
110 cell& curCell = cellPolys_[cellI];
121 forAll(boundaryIds_, patchI)
123 nBoundaryFaces += boundaryIds_[patchI].size();
127 << "There are " << nMissingFaces
128 << " faces to be patched and " << nBoundaryFaces
129 << " specified - collect missed boundaries to final patch" << endl;
131 patchStarts_.setSize(boundaryIds_.size());
132 patchSizes_.setSize(boundaryIds_.size());
134 label nCreatedFaces = nInternalFaces_;
135 label baffleOffset = cFaces.size();
136 interfaces_.setSize(baffleIds_.size());
139 forAll(boundaryIds_, patchI)
141 const List<cellFaceIdentifier>& idList = boundaryIds_[patchI];
143 patchStarts_[patchI] = nCreatedFaces;
145 // write each baffle side separately
146 if (patchPhysicalTypes_[patchI] == "baffle")
150 for (label side = 0; side < 2; ++side)
152 label position = nInterfaces;
156 label baffleI = idList[bndI].cell - baffleOffset;
161 && baffleI < baffleFaces_.size()
162 && baffleIds_[baffleI].size()
167 baffleIds_[baffleI][side],
171 // remove applied boundaries (2nd pass)
174 baffleIds_[baffleI].clear();
177 interfaces_[position][side] = nCreatedFaces;
187 nInterfaces += (count - (count % 2)) / 2;
189 else if (patchPhysicalTypes_[patchI] == "monitoring")
191 // translate the "monitoring" pseudo-boundaries to face sets
192 List<label> monitoring(idList.size());
197 label cellId = idList[bndI].cell;
198 label faceId = idList[bndI].face;
200 // standard case: volume cells
201 if (cellId < baffleOffset)
203 label faceNr = cellPolys_[cellId][faceId];
206 monitoring[monitorI++] = faceNr;
211 monitoringSets_.insert(patchNames_[patchI], monitoring);
217 // standard case: volume cells
218 if (idList[bndI].cell < baffleOffset)
232 patchSizes_[patchI] = nCreatedFaces - patchStarts_[patchI];
235 // add in missing faces
236 Info<< "Missing faces added to patch after face "
237 << nCreatedFaces << ":" <<endl;
240 // look for baffles first - keep them together at the start of the patch
241 for (label side = 0; side < 2; ++side)
243 label position = nInterfaces;
245 forAll(baffleIds_, baffleI)
247 if (baffleIds_[baffleI].size())
249 // add each side for each baffle
252 baffleIds_[baffleI][side],
256 interfaces_[position][side] = nCreatedFaces;
258 // remove applied boundaries (2nd pass)
261 baffleIds_[baffleI].clear();
271 nInterfaces += (nMissingFaces - (nMissingFaces % 2)) / 2;
273 // scan for any other missing faces
274 forAll(cellPolys_, cellI)
276 const labelList& curFaces = cellPolys_[cellI];
278 forAll(curFaces, cellFaceI)
280 if (curFaces[cellFaceI] < 0)
282 // just report the first few
283 if (nMissingFaces < 4)
285 const face& thisFace = cFaces[cellI][cellFaceI];
287 Info<< " cell " << cellI << " face " << cellFaceI
288 << " (original cell " << origCellId_[cellI] << ")"
289 << " face: " << thisFace
292 else if (nMissingFaces == 5)
294 Info<< " ..." << nl << endl;
297 addPolyBoundaryFace(cellI, cellFaceI, nCreatedFaces);
304 Info<< "Added " << nMissingFaces << " unmatched faces" << endl;
306 if (nMissingFaces > 0)
308 patchSizes_.last() = nMissingFaces;
312 patchStarts_.setSize(patchStarts_.size() - 1);
315 // reset the size of the face list
316 meshFaces_.setSize(nCreatedFaces);
318 // check the mesh for face mismatch
319 // (faces addressed once or more than twice)
320 labelList markupFaces(meshFaces_.size(), 0);
322 forAll(cellPolys_, cellI)
324 const labelList& curFaces = cellPolys_[cellI];
326 forAll(curFaces, faceI)
328 markupFaces[curFaces[faceI]]++;
332 for (label i = nInternalFaces_; i < markupFaces.size(); i++)
337 label nProblemFaces = 0;
339 forAll(markupFaces, faceI)
341 if (markupFaces[faceI] != 2)
343 const face& problemFace = meshFaces_[faceI];
345 Info<< "meshReader::createPolyBoundary() : "
346 << "problem with face " << faceI << ": addressed "
347 << markupFaces[faceI] << " times (should be 2!). Face: "
348 << problemFace << endl;
354 if (nProblemFaces > 0)
356 Info<< "Number of incorrectly matched faces: "
357 << nProblemFaces << endl;
360 // adjust for missing members
361 if (nInterfaces < interfaces_.size())
363 interfaces_.setSize(nInterfaces);
366 Info<< "Number of boundary faces: " << nBoundaryFaces << nl
367 << "Total number of faces: " << nCreatedFaces << nl
368 << "Number of interfaces: " << nInterfaces << endl;
372 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
374 Foam::List<Foam::polyPatch*>
375 Foam::meshReader::polyBoundaryPatches(const polyMesh& mesh)
377 label nUsed = 0, nEmpty = 0;
378 label nPatches = patchStarts_.size();
380 // avoid empty patches - move to the end of the lists and truncate
381 labelList oldToNew = identity(nPatches);
382 forAll(patchSizes_, patchI)
384 if (patchSizes_[patchI] > 0)
386 oldToNew[patchI] = nUsed++;
391 oldToNew[patchI] = nPatches - nEmpty;
399 Info<< "Removing " << nEmpty << " empty patches" << endl;
401 inplaceReorder(oldToNew, patchTypes_);
402 inplaceReorder(oldToNew, patchNames_);
403 inplaceReorder(oldToNew, patchStarts_);
404 inplaceReorder(oldToNew, patchSizes_);
407 patchTypes_.setSize(nPatches);
408 patchNames_.setSize(nPatches);
409 patchStarts_.setSize(nPatches);
410 patchSizes_.setSize(nPatches);
413 List<polyPatch*> p(nPatches);
415 // All patch dictionaries
416 PtrList<dictionary> patchDicts(patchNames_.size());
417 // Default boundary patch types
418 word defaultFacesType(emptyPolyPatch::typeName);
420 // we could consider dropping this entirely
431 forAll(patchDicts, patchI)
433 if (!patchDicts.set(patchI))
435 patchDicts.set(patchI, new dictionary());
437 dictionary& patchDict = patchDicts[patchI];
439 // add but not overwrite type
440 patchDict.add("type", patchTypes_[patchI], false);
441 if (patchPhysicalTypes_.size() && patchPhysicalTypes_[patchI].size())
443 patchDict.add("startFace", patchPhysicalTypes_[patchI], false);
446 // overwrite sizes and start
447 patchDict.add("nFaces", patchSizes_[patchI], true);
448 patchDict.add("startFace", patchStarts_[patchI], true);
452 forAll(patchStarts_, patchI)
454 p[patchI] = polyPatch::New
467 // ************************************************************************* //