blockMeshMerge.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-2017 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "blockMesh.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 void Foam::blockMesh::calcMergeInfo()
33 {
34  const blockList& blocks = *this;
35 
36  if (verboseOutput)
37  {
38  Info<< "Creating block offsets" << endl;
39  }
40 
41  blockOffsets_.setSize(blocks.size());
42 
43  nPoints_ = 0;
44  nCells_ = 0;
45 
46  forAll(blocks, blocki)
47  {
48  blockOffsets_[blocki] = nPoints_;
49 
50  nPoints_ += blocks[blocki].nPoints();
51  nCells_ += blocks[blocki].nCells();
52  }
53 
54 
55  if (verboseOutput)
56  {
57  Info<< "Creating merge list.." << flush;
58  }
59 
60  // set unused to -1
61  mergeList_.setSize(nPoints_);
62  mergeList_ = -1;
63 
64 
65  const pointField& blockPoints = topology().points();
66  const cellList& blockCells = topology().cells();
67  const faceList& blockFaces = topology().faces();
68  const labelList& faceOwnerBlocks = topology().faceOwner();
69 
70  // For efficiency, create merge pairs in the first pass
71  labelListListList glueMergePairs(blockFaces.size());
72 
73  const labelList& faceNeighbourBlocks = topology().faceNeighbour();
74 
75 
76  forAll(blockFaces, blockFaceLabel)
77  {
78  label blockPlabel = faceOwnerBlocks[blockFaceLabel];
79  const pointField& blockPpoints = blocks[blockPlabel].points();
80  const labelList& blockPfaces = blockCells[blockPlabel];
81 
82  bool foundFace = false;
83  label blockPfaceLabel;
84  for
85  (
86  blockPfaceLabel = 0;
87  blockPfaceLabel < blockPfaces.size();
88  blockPfaceLabel++
89  )
90  {
91  if (blockPfaces[blockPfaceLabel] == blockFaceLabel)
92  {
93  foundFace = true;
94  break;
95  }
96  }
97 
98  if (!foundFace)
99  {
101  << "Cannot find merge face for block " << blockPlabel
102  << exit(FatalError);
103  }
104 
105  const List<FixedList<label, 4>>& blockPfaceFaces =
106  blocks[blockPlabel].boundaryPatches()[blockPfaceLabel];
107 
108  labelListList& curPairs = glueMergePairs[blockFaceLabel];
109  curPairs.setSize(blockPfaceFaces.size());
110 
111  // Calculate sqr of the merge tolerance as 1/10th of the min sqr
112  // point to point distance on the block face.
113  // At the same time merge collated points on the block's faces
114  // (removes boundary poles etc.)
115  // Collated points detected by initially taking a constant factor of
116  // the size of the block.
117 
118  boundBox bb(blockCells[blockPlabel].points(blockFaces, blockPoints));
119  const scalar mergeSqrDist = magSqr(10*SMALL*bb.span());
120 
121  // This is an N^2 algorithm
122 
123  scalar sqrMergeTol = GREAT;
124 
125  forAll(blockPfaceFaces, blockPfaceFaceLabel)
126  {
127  const FixedList<label, 4>& blockPfaceFacePoints
128  = blockPfaceFaces[blockPfaceFaceLabel];
129 
130  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
131  {
132  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel2)
133  {
134  if (blockPfaceFacePointLabel != blockPfaceFacePointLabel2)
135  {
136  scalar magSqrDist = magSqr
137  (
138  blockPpoints[blockPfaceFacePoints
139  [blockPfaceFacePointLabel]]
140  - blockPpoints[blockPfaceFacePoints
141  [blockPfaceFacePointLabel2]]
142  );
143 
144  if (magSqrDist < mergeSqrDist)
145  {
146  label PpointLabel =
147  blockPfaceFacePoints[blockPfaceFacePointLabel]
148  + blockOffsets_[blockPlabel];
149 
150  label PpointLabel2 =
151  blockPfaceFacePoints[blockPfaceFacePointLabel2]
152  + blockOffsets_[blockPlabel];
153 
154  label minPP2 = min(PpointLabel, PpointLabel2);
155 
156  if (mergeList_[PpointLabel] != -1)
157  {
158  minPP2 = min(minPP2, mergeList_[PpointLabel]);
159  }
160 
161  if (mergeList_[PpointLabel2] != -1)
162  {
163  minPP2 = min(minPP2, mergeList_[PpointLabel2]);
164  }
165 
166  mergeList_[PpointLabel] = mergeList_[PpointLabel2]
167  = minPP2;
168  }
169  else
170  {
171  sqrMergeTol = min(sqrMergeTol, magSqrDist);
172  }
173  }
174  }
175  }
176  }
177 
178  sqrMergeTol /= 10.0;
179 
180 
181  if (topology().isInternalFace(blockFaceLabel))
182  {
183  label blockNlabel = faceNeighbourBlocks[blockFaceLabel];
184  const pointField& blockNpoints = blocks[blockNlabel].points();
185  const labelList& blockNfaces = blockCells[blockNlabel];
186 
187  foundFace = false;
188  label blockNfaceLabel;
189  for
190  (
191  blockNfaceLabel = 0;
192  blockNfaceLabel < blockNfaces.size();
193  blockNfaceLabel++
194  )
195  {
196  if
197  (
198  blockFaces[blockNfaces[blockNfaceLabel]]
199  == blockFaces[blockFaceLabel]
200  )
201  {
202  foundFace = true;
203  break;
204  }
205  }
206 
207  if (!foundFace)
208  {
210  << "Cannot find merge face for block " << blockNlabel
211  << exit(FatalError);
212  }
213 
214  const List<FixedList<label, 4>>& blockNfaceFaces =
215  blocks[blockNlabel].boundaryPatches()[blockNfaceLabel];
216 
217  if
218  (
219  checkFaceCorrespondence_
220  && blockPfaceFaces.size() != blockNfaceFaces.size()
221  )
222  {
224  << "Inconsistent number of faces between block pair "
225  << blockPlabel << " and " << blockNlabel
226  << exit(FatalError);
227  }
228 
229 
230  // N-squared point search over all points of all faces of
231  // master block over all point of all faces of slave block
232  forAll(blockPfaceFaces, blockPfaceFaceLabel)
233  {
234  const FixedList<label, 4>& blockPfaceFacePoints
235  = blockPfaceFaces[blockPfaceFaceLabel];
236 
237  labelList& cp = curPairs[blockPfaceFaceLabel];
238  cp.setSize(blockPfaceFacePoints.size());
239  cp = -1;
240 
241  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
242  {
243  forAll(blockNfaceFaces, blockNfaceFaceLabel)
244  {
245  const FixedList<label, 4>& blockNfaceFacePoints
246  = blockNfaceFaces[blockNfaceFaceLabel];
247 
248  forAll(blockNfaceFacePoints, blockNfaceFacePointLabel)
249  {
250  if
251  (
252  magSqr
253  (
254  blockPpoints
255  [blockPfaceFacePoints[blockPfaceFacePointLabel]]
256  - blockNpoints
257  [blockNfaceFacePoints[blockNfaceFacePointLabel]]
258  ) < sqrMergeTol
259  )
260  {
261  // Found a new pair
262 
263  cp[blockPfaceFacePointLabel] =
264  blockNfaceFacePoints[blockNfaceFacePointLabel];
265 
266  label PpointLabel =
267  blockPfaceFacePoints[blockPfaceFacePointLabel]
268  + blockOffsets_[blockPlabel];
269 
270  label NpointLabel =
271  blockNfaceFacePoints[blockNfaceFacePointLabel]
272  + blockOffsets_[blockNlabel];
273 
274  label minPN = min(PpointLabel, NpointLabel);
275 
276  if (mergeList_[PpointLabel] != -1)
277  {
278  minPN = min(minPN, mergeList_[PpointLabel]);
279  }
280 
281  if (mergeList_[NpointLabel] != -1)
282  {
283  minPN = min(minPN, mergeList_[NpointLabel]);
284  }
285 
286  mergeList_[PpointLabel] = mergeList_[NpointLabel]
287  = minPN;
288  }
289  }
290  }
291  }
292  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
293  {
294  if (cp[blockPfaceFacePointLabel] == -1)
295  {
297  << "Inconsistent point locations between block pair "
298  << blockPlabel << " and " << blockNlabel << nl
299  << " probably due to inconsistent grading."
300  << exit(FatalError);
301  }
302  }
303  }
304  }
305  }
306 
307 
308  const faceList::subList blockinternalFaces
309  (
310  blockFaces,
311  topology().nInternalFaces()
312  );
313 
314  bool changedPointMerge = false;
315  label nPasses = 0;
316 
317  do
318  {
319  changedPointMerge = false;
320  nPasses++;
321 
322  forAll(blockinternalFaces, blockFaceLabel)
323  {
324  label blockPlabel = faceOwnerBlocks[blockFaceLabel];
325  label blockNlabel = faceNeighbourBlocks[blockFaceLabel];
326 
327  const labelList& blockPfaces = blockCells[blockPlabel];
328  const labelList& blockNfaces = blockCells[blockNlabel];
329 
330  const labelListList& curPairs = glueMergePairs[blockFaceLabel];
331 
332  label blockPfaceLabel;
333  for
334  (
335  blockPfaceLabel = 0;
336  blockPfaceLabel < blockPfaces.size();
337  blockPfaceLabel++
338  )
339  {
340  if
341  (
342  blockFaces[blockPfaces[blockPfaceLabel]]
343  == blockinternalFaces[blockFaceLabel]
344  )
345  {
346  break;
347  }
348  }
349 
350 
351  label blockNfaceLabel;
352  for
353  (
354  blockNfaceLabel = 0;
355  blockNfaceLabel < blockNfaces.size();
356  blockNfaceLabel++
357  )
358  {
359  if
360  (
361  blockFaces[blockNfaces[blockNfaceLabel]]
362  == blockinternalFaces[blockFaceLabel]
363  )
364  {
365  break;
366  }
367  }
368 
369 
370  const List<FixedList<label, 4>>& blockPfaceFaces =
371  blocks[blockPlabel].boundaryPatches()[blockPfaceLabel];
372 
373  forAll(blockPfaceFaces, blockPfaceFaceLabel)
374  {
375  const FixedList<label, 4>& blockPfaceFacePoints
376  = blockPfaceFaces[blockPfaceFaceLabel];
377 
378  const labelList& cp = curPairs[blockPfaceFaceLabel];
379 
380  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
381  {
382  label PpointLabel =
383  blockPfaceFacePoints[blockPfaceFacePointLabel]
384  + blockOffsets_[blockPlabel];
385 
386  label NpointLabel =
387  cp[blockPfaceFacePointLabel]
388  + blockOffsets_[blockNlabel];
389 
390  if
391  (
392  mergeList_[PpointLabel]
393  != mergeList_[NpointLabel]
394  )
395  {
396  changedPointMerge = true;
397 
398  mergeList_[PpointLabel]
399  = mergeList_[NpointLabel]
400  = min
401  (
402  mergeList_[PpointLabel],
403  mergeList_[NpointLabel]
404  );
405  }
406  }
407  }
408  }
409  if (verboseOutput)
410  {
411  Info<< '.' << flush;
412  }
413 
414  if (nPasses > 100)
415  {
417  << "Point merging failed after max number of passes."
418  << exit(FatalError);
419  }
420  }
421  while (changedPointMerge);
422 
423  if (verboseOutput)
424  {
425  Info<< endl;
426  }
427 
428  forAll(blockinternalFaces, blockFaceLabel)
429  {
430  label blockPlabel = faceOwnerBlocks[blockFaceLabel];
431  label blockNlabel = faceNeighbourBlocks[blockFaceLabel];
432 
433  const labelList& blockPfaces = blockCells[blockPlabel];
434  const labelList& blockNfaces = blockCells[blockNlabel];
435 
436  const pointField& blockPpoints = blocks[blockPlabel].points();
437  const pointField& blockNpoints = blocks[blockNlabel].points();
438 
439  bool foundFace = false;
440  label blockPfaceLabel;
441  for
442  (
443  blockPfaceLabel = 0;
444  blockPfaceLabel < blockPfaces.size();
445  blockPfaceLabel++
446  )
447  {
448  if
449  (
450  blockFaces[blockPfaces[blockPfaceLabel]]
451  == blockinternalFaces[blockFaceLabel]
452  )
453  {
454  foundFace = true;
455  break;
456  }
457  }
458 
459  if (!foundFace)
460  {
462  << "Cannot find merge face for block " << blockPlabel
463  << exit(FatalError);
464  }
465 
466  foundFace = false;
467  label blockNfaceLabel;
468  for
469  (
470  blockNfaceLabel = 0;
471  blockNfaceLabel < blockNfaces.size();
472  blockNfaceLabel++
473  )
474  {
475  if
476  (
477  blockFaces[blockNfaces[blockNfaceLabel]]
478  == blockinternalFaces[blockFaceLabel]
479  )
480  {
481  foundFace = true;
482  break;
483  }
484  }
485 
486  if (!foundFace)
487  {
489  << "Cannot find merge face for block " << blockNlabel
490  << exit(FatalError);
491  }
492 
493  const List<FixedList<label, 4>>& blockPfaceFaces =
494  blocks[blockPlabel].boundaryPatches()[blockPfaceLabel];
495 
496  const List<FixedList<label, 4>>& blockNfaceFaces =
497  blocks[blockNlabel].boundaryPatches()[blockNfaceLabel];
498 
499  forAll(blockPfaceFaces, blockPfaceFaceLabel)
500  {
501  const FixedList<label, 4>& blockPfaceFacePoints
502  = blockPfaceFaces[blockPfaceFaceLabel];
503 
504  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
505  {
506  label PpointLabel =
507  blockPfaceFacePoints[blockPfaceFacePointLabel]
508  + blockOffsets_[blockPlabel];
509 
510  if (mergeList_[PpointLabel] == -1)
511  {
513  << "Unable to merge point "
514  << blockPfaceFacePointLabel
515  << ' ' << blockPpoints[blockPfaceFacePointLabel]
516  << " of face "
517  << blockPfaceLabel
518  << " of block "
519  << blockPlabel
520  << exit(FatalError);
521  }
522  }
523  }
524 
525  forAll(blockNfaceFaces, blockNfaceFaceLabel)
526  {
527  const FixedList<label, 4>& blockNfaceFacePoints
528  = blockNfaceFaces[blockNfaceFaceLabel];
529 
530  forAll(blockNfaceFacePoints, blockNfaceFacePointLabel)
531  {
532  label NpointLabel =
533  blockNfaceFacePoints[blockNfaceFacePointLabel]
534  + blockOffsets_[blockNlabel];
535 
536  if (mergeList_[NpointLabel] == -1)
537  {
539  << "unable to merge point "
540  << blockNfaceFacePointLabel
541  << ' ' << blockNpoints[blockNfaceFacePointLabel]
542  << " of face "
543  << blockNfaceLabel
544  << " of block "
545  << blockNlabel
546  << exit(FatalError);
547  }
548  }
549  }
550  }
551 
552 
553  // Sort merge list to return new point label (in new shorter list)
554  // given old point label
555  label newPointLabel = 0;
556 
557  forAll(mergeList_, pointLabel)
558  {
559  if (mergeList_[pointLabel] > pointLabel)
560  {
562  << "Merge list contains point index out of range"
563  << exit(FatalError);
564  }
565 
566  if
567  (
568  mergeList_[pointLabel] == -1
569  || mergeList_[pointLabel] == pointLabel
570  )
571  {
572  mergeList_[pointLabel] = newPointLabel;
573  newPointLabel++;
574  }
575  else
576  {
577  mergeList_[pointLabel] = mergeList_[mergeList_[pointLabel]];
578  }
579  }
580 
581  nPoints_ = newPointLabel;
582 }
583 
584 
585 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
blockMesh.H
Foam::blockMesh::topology
const polyMesh & topology() const
Return the blockMesh topology as a polyMesh.
Definition: blockMesh.C:106
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::flush
Ostream & flush(Ostream &os)
Flush stream.
Definition: Ostream.H:329
Foam::label
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:62
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
Foam::List< face >::subList
SubList< face > subList
Declare type of subList.
Definition: List.H:117
Foam::FatalError
error FatalError
Foam::labelListListList
List< labelListList > labelListListList
A List of labelListList.
Definition: labelList.H:57
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1063
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::cp
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: MSwindows.C:802
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::blockMesh::points
const pointField & points() const
The points for the entire mesh.
Definition: blockMesh.C:142
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
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::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082