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