blockMeshTopology.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "blockMesh.H"
27 #include "blockMeshTools.H"
28 #include "Time.H"
29 #include "preservePatchTypes.H"
30 #include "emptyPolyPatch.H"
31 #include "cyclicPolyPatch.H"
32 
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 
35 template<class Source>
36 void Foam::blockMesh::checkPatchLabels
37 (
38  const Source& source,
39  const word& patchName,
40  const pointField& points,
41  faceList& patchFaces
42 ) const
43 {
44  forAll(patchFaces, facei)
45  {
46  face& f = patchFaces[facei];
47 
48  // Replace (<block> <face>) face description
49  // with the corresponding block face
50  if (f.size() == 2)
51  {
52  const label bi = f[0];
53  const label fi = f[1];
54 
55  if (bi >= size())
56  {
58  << "Block index out of range for patch face " << f << nl
59  << " Number of blocks = " << size()
60  << ", index = " << f[0] << nl
61  << " on patch " << patchName << ", face " << facei
62  << exit(FatalIOError);
63  }
64  else if (fi >= operator[](bi).blockShape().faces().size())
65  {
67  << "Block face index out of range for patch face " << f
68  << nl
69  << " Number of block faces = "
70  << operator[](bi).blockShape().faces().size()
71  << ", index = " << f[1] << nl
72  << " on patch " << patchName << ", face " << facei
73  << exit(FatalIOError);
74  }
75  else
76  {
77  f = operator[](bi).blockShape().faces()[fi];
78  }
79  }
80  else
81  {
82  forAll(f, fp)
83  {
84  if (f[fp] < 0)
85  {
87  << "Negative point label " << f[fp] << nl
88  << " on patch " << patchName << ", face " << facei
89  << exit(FatalIOError);
90  }
91  else if (f[fp] >= points.size())
92  {
94  << "Point label " << f[fp]
95  << " out of range 0.." << points.size() - 1 << nl
96  << " on patch " << patchName << ", face " << facei
97  << exit(FatalIOError);
98  }
99  }
100  }
101  }
102 }
103 
104 
105 void Foam::blockMesh::readPatches
106 (
107  const dictionary& meshDescription,
108  faceListList& tmpBlocksPatches,
109  wordList& patchNames,
110  wordList& patchTypes,
111  wordList& nbrPatchNames
112 )
113 {
114  // Collect all variables
115  dictionary varDict(meshDescription.subOrEmptyDict("namedVertices"));
116  varDict.merge(meshDescription.subOrEmptyDict("namedBlocks"));
117 
118 
119  ITstream& patchStream(meshDescription.lookup("patches"));
120 
121  // Read number of patches in mesh
122  label nPatches = 0;
123 
124  token firstToken(patchStream);
125 
126  if (firstToken.isLabel())
127  {
128  nPatches = firstToken.labelToken();
129 
130  tmpBlocksPatches.setSize(nPatches);
131  patchNames.setSize(nPatches);
132  patchTypes.setSize(nPatches);
133  nbrPatchNames.setSize(nPatches);
134  }
135  else
136  {
137  patchStream.putBack(firstToken);
138  }
139 
140  // Read beginning of blocks
141  patchStream.readBegin("patches");
142 
143  nPatches = 0;
144 
145  token lastToken(patchStream);
146  while
147  (
148  !(
149  lastToken.isPunctuation()
150  && lastToken.pToken() == token::END_LIST
151  )
152  )
153  {
154  if (tmpBlocksPatches.size() <= nPatches)
155  {
156  tmpBlocksPatches.setSize(nPatches + 1);
157  patchNames.setSize(nPatches + 1);
158  patchTypes.setSize(nPatches + 1);
159  nbrPatchNames.setSize(nPatches + 1);
160  }
161 
162  patchStream.putBack(lastToken);
163 
164  patchStream
165  >> patchTypes[nPatches]
166  >> patchNames[nPatches];
167 
168  // Read patch faces
169  tmpBlocksPatches[nPatches] = blockMeshTools::read<face>
170  (
171  patchStream,
172  varDict
173  );
174 
175 
176  // Check for multiple patches
177  for (label i = 0; i < nPatches; i++)
178  {
179  if (patchNames[nPatches] == patchNames[i])
180  {
181  FatalIOErrorInFunction(patchStream)
182  << "Duplicate patch " << patchNames[nPatches]
183  << " at line " << patchStream.lineNumber()
184  << exit(FatalIOError);
185  }
186  }
187 
188  checkPatchLabels
189  (
190  patchStream,
191  patchNames[nPatches],
192  vertices_,
193  tmpBlocksPatches[nPatches]
194  );
195 
196  nPatches++;
197 
198 
199  // Split old style cyclics
200 
201  if (patchTypes[nPatches-1] == cyclicPolyPatch::typeName)
202  {
203  word halfA = patchNames[nPatches-1] + "_half0";
204  word halfB = patchNames[nPatches-1] + "_half1";
205 
206  FatalIOErrorInFunction(patchStream)
207  << "Old-style cyclic definition."
208  << " Splitting patch "
209  << patchNames[nPatches-1] << " into two halves "
210  << halfA << " and " << halfB << endl
211  << " Alternatively use new 'boundary' dictionary syntax."
212  << exit(FatalIOError);
213 
214  // Add extra patch
215  if (tmpBlocksPatches.size() <= nPatches)
216  {
217  tmpBlocksPatches.setSize(nPatches + 1);
218  patchNames.setSize(nPatches + 1);
219  patchTypes.setSize(nPatches + 1);
220  nbrPatchNames.setSize(nPatches + 1);
221  }
222 
223  // Update halfA info
224  patchNames[nPatches-1] = halfA;
225  nbrPatchNames[nPatches-1] = halfB;
226 
227  // Update halfB info
228  patchTypes[nPatches] = patchTypes[nPatches-1];
229  patchNames[nPatches] = halfB;
230  nbrPatchNames[nPatches] = halfA;
231 
232  // Split faces
233  if ((tmpBlocksPatches[nPatches-1].size() % 2) != 0)
234  {
235  FatalIOErrorInFunction(patchStream)
236  << "Size of cyclic faces is not a multiple of 2 :"
237  << tmpBlocksPatches[nPatches-1]
238  << exit(FatalIOError);
239  }
240  label sz = tmpBlocksPatches[nPatches-1].size()/2;
241  faceList unsplitFaces(tmpBlocksPatches[nPatches-1], true);
242  tmpBlocksPatches[nPatches-1] = faceList
243  (
244  SubList<face>(unsplitFaces, sz)
245  );
246  tmpBlocksPatches[nPatches] = faceList
247  (
248  SubList<face>(unsplitFaces, sz, sz)
249  );
250 
251  nPatches++;
252  }
253 
254  patchStream >> lastToken;
255  }
256  patchStream.putBack(lastToken);
257 
258  // Read end of blocks
259  patchStream.readEnd("patches");
260 }
261 
262 
263 void Foam::blockMesh::readBoundary
264 (
265  const dictionary& meshDescription,
266  wordList& patchNames,
267  faceListList& tmpBlocksPatches,
268  PtrList<dictionary>& patchDicts
269 )
270 {
271  // Collect all variables
272  dictionary varDict(meshDescription.subOrEmptyDict("namedVertices"));
273  varDict.merge(meshDescription.subOrEmptyDict("namedBlocks"));
274 
275 
276  // Read like boundary file
277  const PtrList<entry> patchesInfo
278  (
279  meshDescription.lookup("boundary")
280  );
281 
282  patchNames.setSize(patchesInfo.size());
283  tmpBlocksPatches.setSize(patchesInfo.size());
284  patchDicts.setSize(patchesInfo.size());
285 
286  forAll(tmpBlocksPatches, patchi)
287  {
288  const entry& patchInfo = patchesInfo[patchi];
289 
290  if (!patchInfo.isDict())
291  {
292  FatalIOErrorInFunction(meshDescription)
293  << "Entry " << patchInfo << " in boundary section is not a"
294  << " valid dictionary."
295  << exit(FatalIOError);
296  }
297 
298  patchNames[patchi] = patchInfo.keyword();
299 
300  // Construct patch dictionary
301  patchDicts.set(patchi, new dictionary(patchInfo.dict()));
302 
303  // Read block faces
304  tmpBlocksPatches[patchi] = blockMeshTools::read<face>
305  (
306  patchDicts[patchi].lookup("faces"),
307  varDict
308  );
309 
310 
311  checkPatchLabels
312  (
313  patchInfo.dict(),
314  patchNames[patchi],
315  vertices_,
316  tmpBlocksPatches[patchi]
317  );
318  }
319 }
320 
321 
322 void Foam::blockMesh::createCellShapes
323 (
324  cellShapeList& tmpBlockCells
325 )
326 {
327  const blockMesh& blocks = *this;
328 
329  tmpBlockCells.setSize(blocks.size());
330  forAll(blocks, blocki)
331  {
332  tmpBlockCells[blocki] = blocks[blocki].blockShape();
333  }
334 }
335 
336 
337 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
338 
339 Foam::polyMesh* Foam::blockMesh::createTopology
340 (
341  const IOdictionary& meshDescription,
342  const word& regionName
343 )
344 {
345  checkBlockFaceOrientation = meshDescription.lookupOrDefault<Switch>
346  (
347  "checkBlockFaceOrientation",
348  true
349  );
350 
351  blockList& blocks = *this;
352 
353  word defaultPatchName = "defaultFaces";
354  word defaultPatchType = emptyPolyPatch::typeName;
355 
356  // Read the names/types for the unassigned patch faces
357  // this is a bit heavy handed (and ugly), but there is currently
358  // no easy way to rename polyMesh patches subsequently
359  if (const dictionary* dictPtr = meshDescription.subDictPtr("defaultPatch"))
360  {
361  dictPtr->readIfPresent("name", defaultPatchName);
362  dictPtr->readIfPresent("type", defaultPatchType);
363  }
364 
365  // Optional 'convertToMeters' or 'scale' scaling factor
366  if (!meshDescription.readIfPresent("convertToMeters", scaleFactor_))
367  {
368  meshDescription.readIfPresent("scale", scaleFactor_);
369  }
370 
371  // Read the block edges
372  if (meshDescription.found("edges"))
373  {
374  if (verboseOutput)
375  {
376  Info<< "Creating block edges" << endl;
377  }
378 
380  (
381  meshDescription.lookup("edges"),
382  blockEdge::iNew(meshDescription, geometry_, vertices_)
383  );
384 
385  edges_.transfer(edges);
386  }
387  else if (verboseOutput)
388  {
389  Info<< "No non-linear block edges defined" << endl;
390  }
391 
392 
393  // Read the block faces
394  if (meshDescription.found("faces"))
395  {
396  if (verboseOutput)
397  {
398  Info<< "Creating block faces" << endl;
399  }
400 
402  (
403  meshDescription.lookup("faces"),
404  blockFace::iNew(meshDescription, geometry_)
405  );
406 
407  faces_.transfer(faces);
408  }
409  else if (verboseOutput)
410  {
411  Info<< "No non-planar block faces defined" << endl;
412  }
413 
414 
415  // Create the blocks
416  if (verboseOutput)
417  {
418  Info<< "Creating topology blocks" << endl;
419  }
420  {
421  blockList blocks
422  (
423  meshDescription.lookup("blocks"),
424  block::iNew(meshDescription, vertices_, edges_, faces_)
425  );
426 
427  transfer(blocks);
428  }
429 
430 
431 
432  polyMesh* blockMeshPtr = nullptr;
433 
434  // Create the patches
435 
436  if (verboseOutput)
437  {
438  Info<< "Creating topology patches" << endl;
439  }
440 
441  if (meshDescription.found("patches"))
442  {
443  Info<< nl << "Reading patches section" << endl;
444 
445  faceListList tmpBlocksPatches;
448  wordList nbrPatchNames;
449 
450  readPatches
451  (
452  meshDescription,
453  tmpBlocksPatches,
454  patchNames,
455  patchTypes,
456  nbrPatchNames
457  );
458 
459  Info<< nl << "Creating block mesh topology" << endl;
460 
461  cellShapeList tmpBlockCells(blocks.size());
462  createCellShapes(tmpBlockCells);
463 
464 
465  Info<< nl << "Reading physicalType from existing boundary file" << endl;
466 
467  PtrList<dictionary> patchDicts(patchNames.size());
468  word defaultFacesType;
469 
471  (
472  meshDescription.time(),
473  meshDescription.time().constant(),
475  patchNames,
476  patchDicts,
477  defaultPatchName,
478  defaultPatchType
479  );
480 
481 
482  // Add cyclic info (might not be present from older file)
483  forAll(patchDicts, patchi)
484  {
485  if (!patchDicts.set(patchi))
486  {
487  patchDicts.set(patchi, new dictionary());
488  }
489 
490  dictionary& dict = patchDicts[patchi];
491 
492  // Add but not override type
493  if (!dict.found("type"))
494  {
495  dict.add("type", patchTypes[patchi], false);
496  }
497  else if (word(dict.lookup("type")) != patchTypes[patchi])
498  {
499  FatalIOErrorInFunction(meshDescription)
500  << "For patch " << patchNames[patchi]
501  << " overriding type '" << patchTypes[patchi]
502  << "' with '" << word(dict.lookup("type"))
503  << "' (read from boundary file)"
504  << exit(FatalIOError);
505  }
506 
507  // Override neighbourpatch name
508  if (nbrPatchNames[patchi] != word::null)
509  {
510  dict.set("neighbourPatch", nbrPatchNames[patchi]);
511  }
512  }
513 
514  blockMeshPtr = new polyMesh
515  (
516  IOobject
517  (
518  regionName,
519  meshDescription.time().constant(),
520  meshDescription.time(),
523  false
524  ),
525  clone(vertices_), // Copy these points, do NOT move
526  tmpBlockCells,
527  tmpBlocksPatches,
528  patchNames,
529  patchDicts,
530  defaultPatchName,
531  defaultPatchType
532  );
533  }
534  else if (meshDescription.found("boundary"))
535  {
537  faceListList tmpBlocksPatches;
538  PtrList<dictionary> patchDicts;
539 
540  readBoundary
541  (
542  meshDescription,
543  patchNames,
544  tmpBlocksPatches,
545  patchDicts
546  );
547 
548  Info<< nl << "Creating block mesh topology" << endl;
549 
550  cellShapeList tmpBlockCells(blocks.size());
551  createCellShapes(tmpBlockCells);
552 
553  blockMeshPtr = new polyMesh
554  (
555  IOobject
556  (
557  regionName,
558  meshDescription.time().constant(),
559  meshDescription.time(),
562  false
563  ),
564  clone(vertices_), // Copy these points, do NOT move
565  tmpBlockCells,
566  tmpBlocksPatches,
567  patchNames,
568  patchDicts,
569  defaultPatchName,
570  defaultPatchType
571  );
572  }
573 
574  check(*blockMeshPtr, meshDescription);
575 
576  return blockMeshPtr;
577 }
578 
579 
580 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:402
word defaultFacesType
Definition: readKivaGrid.H:461
List< faceList > faceListList
Definition: faceListFwd.H:45
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
const blockFaceList & faces() const
Return the curved faces.
Definition: blockMesh.H:250
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
PtrList< blockFace > blockFaceList
A PtrList of blockFaces.
Definition: blockFaceList.H:45
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:312
wordList patchTypes(nPatches)
List< face > faceList
Definition: faceListFwd.H:43
const T & operator[](const label) const
Return element const reference.
Definition: UPtrListI.H:96
PtrList< block > blockList
A PtrList of blocks.
Definition: blockList.H:45
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
T clone(const T &t)
Definition: List.H:54
List< cellShape > cellShapeList
List of cellShapes and PtrList of List of cellShape.
Definition: cellShapeList.H:43
static const word null
An empty word.
Definition: word.H:77
const blockEdgeList & edges() const
Return the curved edges.
Definition: blockMesh.H:244
preservePatchTypes
static const char nl
Definition: Ostream.H:260
PtrList< dictionary > patchDicts() const
Get patch information from the topology mesh.
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.
static Switch checkBlockFaceOrientation
Switch checking block face orientation.
Definition: blockMesh.H:207
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
List< word > wordList
A List of words.
Definition: fileName.H:54
label patchi
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
PtrList< blockEdge > blockEdgeList
A PtrList of blockEdges.
Definition: blockEdgeList.H:45
void transfer(PtrList< T > &)
Transfer the contents of the argument PtrList into this PtrList.
Definition: PtrList.C:189
messageStream Info
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
wordList patchNames() const
Return patch names.
IOerror FatalIOError