initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / conversion / meshReader / createPolyBoundary.C
blob954f8776df8557b78717c1915687f1fa81ba66bb
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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
25 Description
26     boundary faces
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 and monitoring support
35 \*---------------------------------------------------------------------------*/
37 #include "meshReader.H"
38 #include "Time.H"
39 #include "polyPatch.H"
40 #include "emptyPolyPatch.H"
41 #include "preservePatchTypes.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 void Foam::meshReader::addPolyBoundaryFace
47     const label cellId,
48     const label cellFaceId,
49     const label nCreatedFaces
52 #ifdef DEBUG_BOUNDARY
53     Info<< nCreatedFaces
54         << " add bnd for cell " << cellId
55         << " face " << cellFaceId
56         << " (original cell " << origCellId_[cellId] << ")"
57         << endl;
58 #endif
60     // standard case: volume cells
61     const face& thisFace = cellFaces_[cellId][cellFaceId];
63     // Debugging
64     if (cellPolys_[cellId][cellFaceId] > nInternalFaces_)
65     {
66         Info<< "meshReader::createPolyBoundary(): "
67             << "Problem with face: " << thisFace << endl
68             << "Probably multiple definitions "
69             << "of a single boundary face." << endl
70             << endl;
71     }
72     else if (cellPolys_[cellId][cellFaceId] >= 0)
73     {
74         Info<< "meshReader::createPolyBoundary(): "
75             << "Problem with face: " << thisFace << endl
76             << "Probably trying to define a boundary face "
77             << "on a previously matched internal face." << endl
78             << "Internal face: "
79             << meshFaces_[cellPolys_[cellId][cellFaceId]]
80             << endl;
81     }
83     meshFaces_[nCreatedFaces] = thisFace;
84     cellPolys_[cellId][cellFaceId] = nCreatedFaces;
88 void Foam::meshReader::addPolyBoundaryFace
90     const cellFaceIdentifier& identifier,
91     const label nCreatedFaces
94     addPolyBoundaryFace(identifier.cell, identifier.face, nCreatedFaces);
98 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
100 void Foam::meshReader::createPolyBoundary()
102     label nBoundaryFaces = 0;
103     label nMissingFaces = 0;
104     label nInterfaces = 0;
106     const faceListList& cFaces = cellFaces();
108     // determine number of non-patched faces:
109     forAll(cellPolys_, cellI)
110     {
111         cell& curCell = cellPolys_[cellI];
113         forAll(curCell, fI)
114         {
115             if (curCell[fI] < 0)
116             {
117                 nMissingFaces++;
118             }
119         }
120     }
122     forAll(boundaryIds_, patchI)
123     {
124         nBoundaryFaces += boundaryIds_[patchI].size();
125     }
127     Info<< nl
128         << "There are " << nMissingFaces
129         << " faces to be patched and " << nBoundaryFaces
130         << " specified - collect missed boundaries to final patch" << endl;
132     patchStarts_.setSize(boundaryIds_.size());
133     patchSizes_.setSize(boundaryIds_.size());
135     label nCreatedFaces = nInternalFaces_;
136     label baffleOffset  = cFaces.size();
137     interfaces_.setSize(baffleIds_.size());
138     nBoundaryFaces = 0;
140     forAll(boundaryIds_, patchI)
141     {
142         const List<cellFaceIdentifier>& idList = boundaryIds_[patchI];
144         patchStarts_[patchI] = nCreatedFaces;
146         // write each baffle side separately
147         if (patchPhysicalTypes_[patchI] == "baffle")
148         {
149             label count = 0;
151             for (label side = 0; side < 2; ++side)
152             {
153                 label position = nInterfaces;
155                 forAll(idList, bndI)
156                 {
157                     label baffleI = idList[bndI].cell - baffleOffset;
159                     if
160                     (
161                         baffleI >= 0
162                      && baffleI < baffleFaces_.size()
163                      && baffleIds_[baffleI].size()
164                     )
165                     {
166                         addPolyBoundaryFace
167                         (
168                             baffleIds_[baffleI][side],
169                             nCreatedFaces
170                         );
172                         // remove applied boundaries (2nd pass)
173                         if (side == 1)
174                         {
175                             baffleIds_[baffleI].clear();
176                         }
178                         interfaces_[position][side] = nCreatedFaces;
180                         nBoundaryFaces++;
181                         nCreatedFaces++;
182                         position++;
183                         count++;
184                     }
185                 }
186             }
188             nInterfaces += (count - (count % 2)) / 2;
189         }
190         else if (patchPhysicalTypes_[patchI] == "monitoring")
191         {
192             // translate the "monitoring" pseudo-boundaries to face sets
193             List<label> monitoring(idList.size());
195             label monitorI = 0;
196             forAll(idList, bndI)
197             {
198                 label cellId = idList[bndI].cell;
199                 label faceId = idList[bndI].face;
201                 // standard case: volume cells
202                 if (cellId < baffleOffset)
203                 {
204                     label faceNr = cellPolys_[cellId][faceId];
205                     if (faceNr >= 0)
206                     {
207                         monitoring[monitorI++] = faceNr;
208                     }
209                 }
210             }
212             monitoringSets_.insert(patchNames_[patchI], monitoring);
213         }
214         else
215         {
216             forAll(idList, bndI)
217             {
218                 // standard case: volume cells
219                 if (idList[bndI].cell < baffleOffset)
220                 {
221                     addPolyBoundaryFace
222                     (
223                         idList[bndI],
224                         nCreatedFaces
225                     );
227                     nBoundaryFaces++;
228                     nCreatedFaces++;
229                 }
230             }
231         }
233         patchSizes_[patchI] = nCreatedFaces - patchStarts_[patchI];
234     }
236     // add in missing faces
237     Info<< "Missing faces added to patch after face "
238         << nCreatedFaces << ":" <<endl;
239     nMissingFaces = 0;
241     // look for baffles first - keep them together at the start of the patch
242     for (label side = 0; side < 2; ++side)
243     {
244         label position = nInterfaces;
246         forAll(baffleIds_, baffleI)
247         {
248             if (baffleIds_[baffleI].size())
249             {
250                 // add each side for each baffle
251                 addPolyBoundaryFace
252                 (
253                     baffleIds_[baffleI][side],
254                     nCreatedFaces
255                 );
257                 interfaces_[position][side] = nCreatedFaces;
259                 // remove applied boundaries (2nd pass)
260                 if (side == 1)
261                 {
262                     baffleIds_[baffleI].clear();
263                 }
265                 nMissingFaces++;
266                 nCreatedFaces++;
267                 position++;
268             }
269         }
270     }
272     nInterfaces += (nMissingFaces - (nMissingFaces % 2)) / 2;
274     // scan for any other missing faces
275     forAll(cellPolys_, cellI)
276     {
277         const labelList& curFaces = cellPolys_[cellI];
279         forAll(curFaces, cellFaceI)
280         {
281             if (curFaces[cellFaceI] < 0)
282             {
283                 // just report the first few
284                 if (nMissingFaces < 4)
285                 {
286                     const face& thisFace = cFaces[cellI][cellFaceI];
288                     Info<< "  cell " << cellI << " face " << cellFaceI
289                         << " (original cell " << origCellId_[cellI] << ")"
290                         << " face: " << thisFace
291                         << endl;
292                 }
293                 else if (nMissingFaces == 5)
294                 {
295                     Info<< "  ..." << nl << endl;
296                 }
298                 addPolyBoundaryFace(cellI, cellFaceI, nCreatedFaces);
299                 nMissingFaces++;
300                 nCreatedFaces++;
301             }
302         }
303     }
305     Info<< "Added " << nMissingFaces << " unmatched faces" << endl;
307     if (nMissingFaces > 0)
308     {
309         patchSizes_[patchSizes_.size() - 1] = nMissingFaces;
310     }
311     else
312     {
313         patchStarts_.setSize(patchStarts_.size() - 1);
314     }
316     // reset the size of the face list
317     meshFaces_.setSize(nCreatedFaces);
319     // check the mesh for face mismatch
320     // (faces addressed once or more than twice)
321     labelList markupFaces(meshFaces_.size(), 0);
323     forAll(cellPolys_, cellI)
324     {
325         const labelList& curFaces = cellPolys_[cellI];
327         forAll(curFaces, faceI)
328         {
329             markupFaces[curFaces[faceI]]++;
330         }
331     }
333     for (label i = nInternalFaces_; i < markupFaces.size(); i++)
334     {
335         markupFaces[i]++;
336     }
338     label nProblemFaces = 0;
340     forAll(markupFaces, faceI)
341     {
342         if (markupFaces[faceI] != 2)
343         {
344             const face& problemFace = meshFaces_[faceI];
346             Info<< "meshReader::createPolyBoundary() : "
347                 << "problem with face " << faceI << ": addressed "
348                 << markupFaces[faceI] << " times (should be 2!). Face: "
349                 << problemFace << endl;
351             nProblemFaces++;
352         }
353     }
355     if (nProblemFaces > 0)
356     {
357         Info<< "Number of incorrectly matched faces: "
358             << nProblemFaces << endl;
359     }
361     // adjust for missing members
362     if (nInterfaces < interfaces_.size())
363     {
364         interfaces_.setSize(nInterfaces);
365     }
367     Info<< "Number of boundary faces: " << nBoundaryFaces << nl
368         << "Total number of faces: " << nCreatedFaces << nl
369         << "Number of interfaces: " << nInterfaces << endl;
373 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
375 Foam::List<Foam::polyPatch*>
376 Foam::meshReader::polyBoundaryPatches(const polyMesh& mesh)
378     label nUsed = 0, nEmpty = 0;
379     label nPatches = patchStarts_.size();
381     // avoid empty patches - move to the end of the lists and truncate
382     labelList oldToNew = identity(nPatches);
383     forAll(patchSizes_, patchI)
384     {
385         if (patchSizes_[patchI] > 0)
386         {
387             oldToNew[patchI] = nUsed++;
388         }
389         else
390         {
391             nEmpty++;
392             oldToNew[patchI] = nPatches - nEmpty;
393         }
394     }
396     nPatches = nUsed;
398     if (nEmpty)
399     {
400         Info<< "Removing " << nEmpty << " empty patches" << endl;
402         inplaceReorder(oldToNew, patchTypes_);
403         inplaceReorder(oldToNew, patchNames_);
404         inplaceReorder(oldToNew, patchStarts_);
405         inplaceReorder(oldToNew, patchSizes_);
406     }
408     patchTypes_.setSize(nPatches);
409     patchNames_.setSize(nPatches);
410     patchStarts_.setSize(nPatches);
411     patchSizes_.setSize(nPatches);
414     List<polyPatch*> p(nPatches);
416     // Default boundary patch types
417     word defaultFacesType(emptyPolyPatch::typeName);
419     // we could consider dropping this entirely
420     preservePatchTypes
421     (
422         mesh,
423         mesh.instance(),
424         mesh.meshDir(),
425         patchNames_,
426         patchTypes_,
427         "defaultFaces",
428         defaultFacesType,
429         patchPhysicalTypes_
430     );
432     forAll(patchStarts_, patchI)
433     {
434         p[patchI] = polyPatch::New
435         (
436             patchTypes_[patchI],
437             patchNames_[patchI],
438             patchSizes_[patchI],
439             patchStarts_[patchI],
440             patchI,
441             mesh.boundaryMesh()
442         ).ptr();
443     }
445     return p;
449 // ************************************************************************* //