createPolyBoundary.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  boundary faces
29  - use pointCells when searching for connectivity
30  - initialize the cell connectivity with '-1'
31  - find both cell faces corresponding to the baffles and mark them
32  to prevent a connection
33  - standard connectivity checks
34 
35  - added baffle and monitoring support
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #include "meshReader.H"
40 #include "Time.H"
41 #include "polyPatch.H"
42 #include "emptyPolyPatch.H"
43 #include "preservePatchTypes.H"
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 void Foam::meshReader::addPolyBoundaryFace
48 (
49  const label cellId,
50  const label cellFaceId,
51  const label nCreatedFaces
52 )
53 {
54 #ifdef DEBUG_BOUNDARY
55  Info<< nCreatedFaces
56  << " add bnd for cell " << cellId
57  << " face " << cellFaceId
58  << " (original cell " << origCellId_[cellId] << ")"
59  << endl;
60 #endif
61 
62  // standard case: volume cells
63  const face& thisFace = cellFaces_[cellId][cellFaceId];
64 
65  // Debugging
66  if (cellPolys_[cellId][cellFaceId] > nInternalFaces_)
67  {
69  << "Problem with face: " << thisFace << endl
70  << "Probably multiple definitions "
71  << "of a single boundary face." << endl
72  << endl;
73  }
74  else if (cellPolys_[cellId][cellFaceId] >= 0)
75  {
77  << "Problem with face: " << thisFace << endl
78  << "Probably trying to define a boundary face "
79  << "on a previously matched internal face." << endl
80  << "Internal face: "
81  << meshFaces_[cellPolys_[cellId][cellFaceId]]
82  << endl;
83  }
84 
85  meshFaces_[nCreatedFaces] = thisFace;
86  cellPolys_[cellId][cellFaceId] = nCreatedFaces;
87 }
88 
89 
90 void Foam::meshReader::addPolyBoundaryFace
91 (
92  const cellFaceIdentifier& identifier,
93  const label nCreatedFaces
94 )
95 {
96  addPolyBoundaryFace
97  (
98  identifier.cellId(),
99  identifier.faceId(),
100  nCreatedFaces
101  );
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
106 
107 void Foam::meshReader::createPolyBoundary()
108 {
109  label nBoundaryFaces = 0;
110  label nMissingFaces = 0;
111  label nInterfaces = 0;
112 
113  const faceListList& cFaces = cellFaces();
114 
115  // determine number of non-patched faces:
116  forAll(cellPolys_, celli)
117  {
118  cell& curCell = cellPolys_[celli];
119 
120  forAll(curCell, fI)
121  {
122  if (curCell[fI] < 0)
123  {
124  nMissingFaces++;
125  }
126  }
127  }
128 
129  forAll(boundaryIds_, patchi)
130  {
131  nBoundaryFaces += boundaryIds_[patchi].size();
132  }
133 
134  Info<< nl
135  << "There are " << nMissingFaces
136  << " faces to be patched and " << nBoundaryFaces
137  << " specified - collect missed boundaries to final patch" << endl;
138 
139  patchStarts_.setSize(boundaryIds_.size());
140  patchSizes_.setSize(boundaryIds_.size());
141 
142  label nCreatedFaces = nInternalFaces_;
143  label baffleOffset = cFaces.size();
144  interfaces_.setSize(baffleIds_.size());
145  nBoundaryFaces = 0;
146 
147  forAll(boundaryIds_, patchi)
148  {
149  const List<cellFaceIdentifier>& idList = boundaryIds_[patchi];
150 
151  patchStarts_[patchi] = nCreatedFaces;
152 
153  // write each baffle side separately
154  if (patchPhysicalTypes_[patchi] == "baffle")
155  {
156  label count = 0;
157 
158  for (label side = 0; side < 2; ++side)
159  {
160  label position = nInterfaces;
161 
162  forAll(idList, bndI)
163  {
164  label baffleI = idList[bndI].cellId() - baffleOffset;
165 
166  if
167  (
168  baffleI >= 0
169  && baffleI < baffleFaces_.size()
170  && baffleIds_[baffleI].size()
171  )
172  {
173  addPolyBoundaryFace
174  (
175  baffleIds_[baffleI][side],
176  nCreatedFaces
177  );
178 
179  // remove applied boundaries (2nd pass)
180  if (side == 1)
181  {
182  baffleIds_[baffleI].clear();
183  }
184 
185  interfaces_[position][side] = nCreatedFaces;
186 
187  nBoundaryFaces++;
188  nCreatedFaces++;
189  position++;
190  count++;
191  }
192  }
193  }
194 
195  nInterfaces += (count - (count % 2)) / 2;
196  }
197  else if (patchPhysicalTypes_[patchi] == "monitoring")
198  {
199  // translate the "monitoring" pseudo-boundaries to face sets
200  labelList monitoring(idList.size());
201 
202  label monitorI = 0;
203  forAll(idList, bndI)
204  {
205  label cellId = idList[bndI].cellId();
206  label faceId = idList[bndI].faceId();
207 
208  // standard case: volume cells
209  if (cellId < baffleOffset)
210  {
211  label faceNr = cellPolys_[cellId][faceId];
212  if (faceNr >= 0)
213  {
214  monitoring[monitorI++] = faceNr;
215  }
216  }
217  }
218 
219  monitoringSets_.insert(patchNames_[patchi], monitoring);
220  }
221  else
222  {
223  forAll(idList, bndI)
224  {
225  // standard case: volume cells
226  if (idList[bndI].cellId() < baffleOffset)
227  {
228  addPolyBoundaryFace
229  (
230  idList[bndI],
231  nCreatedFaces
232  );
233 
234  nBoundaryFaces++;
235  nCreatedFaces++;
236  }
237  }
238  }
239 
240  patchSizes_[patchi] = nCreatedFaces - patchStarts_[patchi];
241  }
242 
243  // add in missing faces
244  Info<< "Missing faces added to patch after face "
245  << nCreatedFaces << ":" <<endl;
246  nMissingFaces = 0;
247 
248  // look for baffles first - keep them together at the start of the patch
249  for (label side = 0; side < 2; ++side)
250  {
251  label position = nInterfaces;
252 
253  forAll(baffleIds_, baffleI)
254  {
255  if (baffleIds_[baffleI].size())
256  {
257  // add each side for each baffle
258  addPolyBoundaryFace
259  (
260  baffleIds_[baffleI][side],
261  nCreatedFaces
262  );
263 
264  interfaces_[position][side] = nCreatedFaces;
265 
266  // remove applied boundaries (2nd pass)
267  if (side == 1)
268  {
269  baffleIds_[baffleI].clear();
270  }
271 
272  nMissingFaces++;
273  nCreatedFaces++;
274  position++;
275  }
276  }
277  }
278 
279  nInterfaces += (nMissingFaces - (nMissingFaces % 2)) / 2;
280 
281  // scan for any other missing faces
282  forAll(cellPolys_, celli)
283  {
284  const labelList& curFaces = cellPolys_[celli];
285 
286  forAll(curFaces, cellFacei)
287  {
288  if (curFaces[cellFacei] < 0)
289  {
290  // just report the first few
291  if (nMissingFaces < 4)
292  {
293  const face& thisFace = cFaces[celli][cellFacei];
294 
295  Info<< " cell " << celli << " face " << cellFacei
296  << " (original cell " << origCellId_[celli] << ")"
297  << " face: " << thisFace
298  << endl;
299  }
300  else if (nMissingFaces == 5)
301  {
302  Info<< " ..." << nl << endl;
303  }
304 
305  addPolyBoundaryFace(celli, cellFacei, nCreatedFaces);
306  nMissingFaces++;
307  nCreatedFaces++;
308  }
309  }
310  }
311 
312  Info<< "Added " << nMissingFaces << " unmatched faces" << endl;
313 
314  // Add missing faces to last patch ('Default_Empty' etc.)
315  if (nMissingFaces > 0)
316  {
317  patchSizes_.last() = nMissingFaces;
318  }
319 
320 
321  // reset the size of the face list
322  meshFaces_.setSize(nCreatedFaces);
323 
324  // check the mesh for face mismatch
325  // (faces addressed once or more than twice)
326  labelList markupFaces(meshFaces_.size(), Zero);
327 
328  forAll(cellPolys_, celli)
329  {
330  const labelList& curFaces = cellPolys_[celli];
331 
332  forAll(curFaces, facei)
333  {
334  markupFaces[curFaces[facei]]++;
335  }
336  }
337 
338  for (label i = nInternalFaces_; i < markupFaces.size(); i++)
339  {
340  markupFaces[i]++;
341  }
342 
343  label nProblemFaces = 0;
344 
345  forAll(markupFaces, facei)
346  {
347  if (markupFaces[facei] != 2)
348  {
349  const face& problemFace = meshFaces_[facei];
350 
352  << "Problem with face " << facei << ": addressed "
353  << markupFaces[facei] << " times (should be 2!). Face: "
354  << problemFace << endl;
355 
356  nProblemFaces++;
357  }
358  }
359 
360  if (nProblemFaces > 0)
361  {
362  Info<< "Number of incorrectly matched faces: "
363  << nProblemFaces << endl;
364  }
365 
366  // adjust for missing members
367  if (nInterfaces < interfaces_.size())
368  {
369  interfaces_.setSize(nInterfaces);
370  }
371 
372  Info<< "Number of boundary faces: " << nBoundaryFaces << nl
373  << "Total number of faces: " << nCreatedFaces << nl
374  << "Number of interfaces: " << nInterfaces << endl;
375 }
376 
377 
378 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
379 
381 Foam::meshReader::polyBoundaryPatches(const polyMesh& mesh)
382 {
383  label nUsed = 0, nEmpty = 0;
384  label nPatches = patchStarts_.size();
385 
386  // avoid empty patches - move to the end of the lists and truncate
387  labelList oldToNew = identity(nPatches);
388  forAll(patchSizes_, patchi)
389  {
390  if (patchSizes_[patchi] > 0)
391  {
392  oldToNew[patchi] = nUsed++;
393  }
394  else
395  {
396  nEmpty++;
397  oldToNew[patchi] = nPatches - nEmpty;
398  }
399  }
400 
401  nPatches = nUsed;
402 
403  if (nEmpty)
404  {
405  Info<< "Removing " << nEmpty << " empty patches" << endl;
406 
407  inplaceReorder(oldToNew, patchTypes_);
408  inplaceReorder(oldToNew, patchNames_);
409  inplaceReorder(oldToNew, patchStarts_);
410  inplaceReorder(oldToNew, patchSizes_);
411  }
412 
413  patchTypes_.setSize(nPatches);
414  patchNames_.setSize(nPatches);
415  patchStarts_.setSize(nPatches);
416  patchSizes_.setSize(nPatches);
417 
418 
419  List<polyPatch*> p(nPatches);
420 
421  // All patch dictionaries
422  PtrList<dictionary> patchDicts(patchNames_.size());
423  // Default boundary patch types
424  word defaultFacesType(emptyPolyPatch::typeName);
425 
426  // we could consider dropping this entirely
428  (
429  mesh,
430  mesh.instance(),
431  mesh.meshDir(),
432  patchNames_,
433  patchDicts,
434  "defaultFaces",
436  );
437  forAll(patchDicts, patchi)
438  {
439  if (!patchDicts.set(patchi))
440  {
441  patchDicts.set(patchi, new dictionary());
442  }
443  dictionary& patchDict = patchDicts[patchi];
444 
445  // Add but not override 'type'
446  if (!patchDict.found("type"))
447  {
448  patchDict.add("type", patchTypes_[patchi], false);
449  }
450 
451  // Add but not override 'physicalType' but only if it differs
452  // from 'type'
453  if
454  (
455  patchi < patchPhysicalTypes_.size()
456  && patchPhysicalTypes_[patchi].size()
457  && patchPhysicalTypes_[patchi] != patchTypes_[patchi]
458  && !patchDict.found("physicalType")
459  )
460  {
461  patchDict.add("physicalType", patchPhysicalTypes_[patchi], false);
462  }
463 
464  // Overwrite sizes and start
465  patchDict.add("nFaces", patchSizes_[patchi], true);
466  patchDict.add("startFace", patchStarts_[patchi], true);
467  }
468 
469 
470  forAll(patchStarts_, patchi)
471  {
472  p[patchi] = polyPatch::New
473  (
474  patchNames_[patchi],
475  patchDicts[patchi],
476  patchi,
478  ).ptr();
479  }
480 
481  return p;
482 }
483 
484 
485 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:350
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::IOobject::instance
const fileName & instance() const noexcept
Definition: IOobjectI.H:196
polyPatch.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::preservePatchTypes
void preservePatchTypes(const objectRegistry &obr, const word &meshInstance, const fileName &meshDir, const wordList &patchNames, PtrList< dictionary > &patchDicts, const word &defaultFacesName, word &defaultFacesType)
Preserve patch types.
Definition: preservePatchTypes.C:35
preservePatchTypes.H
preservePatchTypes
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
defaultFacesType
word defaultFacesType
Definition: readKivaGrid.H:456
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
patchDicts
PtrList< dictionary > patchDicts
Definition: readKivaGrid.H:532
Foam::meshReader::origCellId_
labelList origCellId_
Lookup original Cell number for a given cell.
Definition: meshReader.H:219
nPatches
const label nPatches
Definition: printMeshSummary.H:30
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
faceId
label faceId(-1)
Foam::polyPatch::New
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return pointer to a new patch created on freestore from components.
Definition: polyPatchNew.C:35
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
emptyPolyPatch.H
Foam::polyMesh::meshDir
fileName meshDir() const
Return the local mesh directory (dbDir()/meshSubDir)
Definition: polyMesh.C:840
cellId
label cellId
Definition: interrogateWallPatches.H:67
Foam::meshReader::meshFaces_
faceList meshFaces_
Global face list for polyMesh.
Definition: meshReader.H:242
Time.H
Foam::faceListList
List< faceList > faceListList
A List of faceList.
Definition: faceListFwd.H:49
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:77
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
meshReader.H
Foam::meshReader::nInternalFaces_
label nInternalFaces_
Number of internal faces for polyMesh.
Definition: meshReader.H:239
Foam::meshReader::cellFaces_
faceListList cellFaces_
List of faces for every cell.
Definition: meshReader.H:245