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