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  blockList& blocks = *this;
346 
347  word defaultPatchName = "defaultFaces";
348  word defaultPatchType = emptyPolyPatch::typeName;
349 
350  // Read the names/types for the unassigned patch faces
351  // this is a bit heavy handed (and ugly), but there is currently
352  // no easy way to rename polyMesh patches subsequently
353  if (const dictionary* dictPtr = meshDescription.subDictPtr("defaultPatch"))
354  {
355  dictPtr->readIfPresent("name", defaultPatchName);
356  dictPtr->readIfPresent("type", defaultPatchType);
357  }
358 
359  // Optional 'convertToMeters' or 'scale' scaling factor
360  if (!meshDescription.readIfPresent("convertToMeters", scaleFactor_))
361  {
362  meshDescription.readIfPresent("scale", scaleFactor_);
363  }
364 
365  // Read the block edges
366  if (meshDescription.found("edges"))
367  {
368  if (verboseOutput)
369  {
370  Info<< "Creating block edges" << endl;
371  }
372 
374  (
375  meshDescription.lookup("edges"),
376  blockEdge::iNew(meshDescription, geometry_, vertices_)
377  );
378 
379  edges_.transfer(edges);
380  }
381  else if (verboseOutput)
382  {
383  Info<< "No non-linear block edges defined" << endl;
384  }
385 
386 
387  // Read the block faces
388  if (meshDescription.found("faces"))
389  {
390  if (verboseOutput)
391  {
392  Info<< "Creating block faces" << endl;
393  }
394 
396  (
397  meshDescription.lookup("faces"),
398  blockFace::iNew(meshDescription, geometry_)
399  );
400 
401  faces_.transfer(faces);
402  }
403  else if (verboseOutput)
404  {
405  Info<< "No non-planar block faces defined" << endl;
406  }
407 
408 
409  // Create the blocks
410  if (verboseOutput)
411  {
412  Info<< "Creating topology blocks" << endl;
413  }
414  {
415  blockList blocks
416  (
417  meshDescription.lookup("blocks"),
418  block::iNew(meshDescription, vertices_, edges_, faces_)
419  );
420 
421  transfer(blocks);
422  }
423 
424 
425 
426  polyMesh* blockMeshPtr = nullptr;
427 
428  // Create the patches
429 
430  if (verboseOutput)
431  {
432  Info<< "Creating topology patches" << endl;
433  }
434 
435  if (meshDescription.found("patches"))
436  {
437  Info<< nl << "Reading patches section" << endl;
438 
439  faceListList tmpBlocksPatches;
442  wordList nbrPatchNames;
443 
444  readPatches
445  (
446  meshDescription,
447  tmpBlocksPatches,
448  patchNames,
449  patchTypes,
450  nbrPatchNames
451  );
452 
453  Info<< nl << "Creating block mesh topology" << endl;
454 
455  cellShapeList tmpBlockCells(blocks.size());
456  createCellShapes(tmpBlockCells);
457 
458 
459  Info<< nl << "Reading physicalType from existing boundary file" << endl;
460 
461  PtrList<dictionary> patchDicts(patchNames.size());
462  word defaultFacesType;
463 
465  (
466  meshDescription.time(),
467  meshDescription.time().constant(),
469  patchNames,
470  patchDicts,
471  defaultPatchName,
472  defaultPatchType
473  );
474 
475 
476  // Add cyclic info (might not be present from older file)
477  forAll(patchDicts, patchi)
478  {
479  if (!patchDicts.set(patchi))
480  {
481  patchDicts.set(patchi, new dictionary());
482  }
483 
484  dictionary& dict = patchDicts[patchi];
485 
486  // Add but not override type
487  if (!dict.found("type"))
488  {
489  dict.add("type", patchTypes[patchi], false);
490  }
491  else if (word(dict.lookup("type")) != patchTypes[patchi])
492  {
493  FatalIOErrorInFunction(meshDescription)
494  << "For patch " << patchNames[patchi]
495  << " overriding type '" << patchTypes[patchi]
496  << "' with '" << word(dict.lookup("type"))
497  << "' (read from boundary file)"
498  << exit(FatalIOError);
499  }
500 
501  // Override neighbourpatch name
502  if (nbrPatchNames[patchi] != word::null)
503  {
504  dict.set("neighbourPatch", nbrPatchNames[patchi]);
505  }
506  }
507 
508  blockMeshPtr = new polyMesh
509  (
510  IOobject
511  (
512  regionName,
513  meshDescription.time().constant(),
514  meshDescription.time(),
517  false
518  ),
519  clone(vertices_), // Copy these points, do NOT move
520  tmpBlockCells,
521  tmpBlocksPatches,
522  patchNames,
523  patchDicts,
524  defaultPatchName,
525  defaultPatchType
526  );
527  }
528  else if (meshDescription.found("boundary"))
529  {
531  faceListList tmpBlocksPatches;
532  PtrList<dictionary> patchDicts;
533 
534  readBoundary
535  (
536  meshDescription,
537  patchNames,
538  tmpBlocksPatches,
539  patchDicts
540  );
541 
542  Info<< nl << "Creating block mesh topology" << endl;
543 
544  cellShapeList tmpBlockCells(blocks.size());
545  createCellShapes(tmpBlockCells);
546 
547  blockMeshPtr = new polyMesh
548  (
549  IOobject
550  (
551  regionName,
552  meshDescription.time().constant(),
553  meshDescription.time(),
556  false
557  ),
558  clone(vertices_), // Copy these points, do NOT move
559  tmpBlockCells,
560  tmpBlocksPatches,
561  patchNames,
562  patchDicts,
563  defaultPatchName,
564  defaultPatchType
565  );
566  }
567 
568  check(*blockMeshPtr, meshDescription);
569 
570  return blockMeshPtr;
571 }
572 
573 
574 // ************************************************************************* //
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:244
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:256
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:238
preservePatchTypes
static const char nl
Definition: Ostream.H:265
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.
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