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 | Copyright (C) 2011-2015 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 labelListList& 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 initally 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 labelList& 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 labelListList& blockNfaceFaces =
213  blocks[blockNlabel].boundaryPatches()[blockNfaceLabel];
214 
215  if (blockPfaceFaces.size() != blockNfaceFaces.size())
216  {
218  << "Inconsistent number of faces between block pair "
219  << blockPlabel << " and " << blockNlabel
220  << exit(FatalError);
221  }
222 
223 
224  // N-squared point search over all points of all faces of
225  // master block over all point of all faces of slave block
226  forAll(blockPfaceFaces, blockPfaceFaceLabel)
227  {
228  const labelList& blockPfaceFacePoints
229  = blockPfaceFaces[blockPfaceFaceLabel];
230 
231  labelList& cp = curPairs[blockPfaceFaceLabel];
232  cp.setSize(blockPfaceFacePoints.size());
233  cp = -1;
234 
235  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
236  {
237  forAll(blockNfaceFaces, blockNfaceFaceLabel)
238  {
239  const labelList& blockNfaceFacePoints
240  = blockNfaceFaces[blockNfaceFaceLabel];
241 
242  forAll(blockNfaceFacePoints, blockNfaceFacePointLabel)
243  {
244  if
245  (
246  magSqr
247  (
248  blockPpoints
249  [blockPfaceFacePoints[blockPfaceFacePointLabel]]
250  - blockNpoints
251  [blockNfaceFacePoints[blockNfaceFacePointLabel]]
252  ) < sqrMergeTol
253  )
254  {
255  // Found a new pair
256 
257  cp[blockPfaceFacePointLabel] =
258  blockNfaceFacePoints[blockNfaceFacePointLabel];
259 
260  label PpointLabel =
261  blockPfaceFacePoints[blockPfaceFacePointLabel]
262  + blockOffsets_[blockPlabel];
263 
264  label NpointLabel =
265  blockNfaceFacePoints[blockNfaceFacePointLabel]
266  + blockOffsets_[blockNlabel];
267 
268  label minPN = min(PpointLabel, NpointLabel);
269 
270  if (mergeList_[PpointLabel] != -1)
271  {
272  minPN = min(minPN, mergeList_[PpointLabel]);
273  }
274 
275  if (mergeList_[NpointLabel] != -1)
276  {
277  minPN = min(minPN, mergeList_[NpointLabel]);
278  }
279 
280  mergeList_[PpointLabel] = mergeList_[NpointLabel]
281  = minPN;
282  }
283  }
284  }
285  }
286  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
287  {
288  if (cp[blockPfaceFacePointLabel] == -1)
289  {
291  << "Inconsistent point locations between block pair "
292  << blockPlabel << " and " << blockNlabel << nl
293  << " probably due to inconsistent grading."
294  << exit(FatalError);
295  }
296  }
297  }
298  }
299  }
300 
301 
302  const faceList::subList blockInternalFaces
303  (
304  blockFaces,
305  topology().nInternalFaces()
306  );
307 
308  bool changedPointMerge = false;
309  label nPasses = 0;
310 
311  do
312  {
313  changedPointMerge = false;
314  nPasses++;
315 
316  forAll(blockInternalFaces, blockFaceLabel)
317  {
318  label blockPlabel = faceOwnerBlocks[blockFaceLabel];
319  label blockNlabel = faceNeighbourBlocks[blockFaceLabel];
320 
321  const labelList& blockPfaces = blockCells[blockPlabel];
322  const labelList& blockNfaces = blockCells[blockNlabel];
323 
324  const labelListList& curPairs = glueMergePairs[blockFaceLabel];
325 
326  label blockPfaceLabel;
327  for
328  (
329  blockPfaceLabel = 0;
330  blockPfaceLabel < blockPfaces.size();
331  blockPfaceLabel++
332  )
333  {
334  if
335  (
336  blockFaces[blockPfaces[blockPfaceLabel]]
337  == blockInternalFaces[blockFaceLabel]
338  )
339  {
340  break;
341  }
342  }
343 
344 
345  label blockNfaceLabel;
346  for
347  (
348  blockNfaceLabel = 0;
349  blockNfaceLabel < blockNfaces.size();
350  blockNfaceLabel++
351  )
352  {
353  if
354  (
355  blockFaces[blockNfaces[blockNfaceLabel]]
356  == blockInternalFaces[blockFaceLabel]
357  )
358  {
359  break;
360  }
361  }
362 
363 
364  const labelListList& blockPfaceFaces =
365  blocks[blockPlabel].boundaryPatches()[blockPfaceLabel];
366 
367  forAll(blockPfaceFaces, blockPfaceFaceLabel)
368  {
369  const labelList& blockPfaceFacePoints
370  = blockPfaceFaces[blockPfaceFaceLabel];
371 
372  const labelList& cp = curPairs[blockPfaceFaceLabel];
373 
374  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
375  {
376  label PpointLabel =
377  blockPfaceFacePoints[blockPfaceFacePointLabel]
378  + blockOffsets_[blockPlabel];
379 
380  label NpointLabel =
381  cp[blockPfaceFacePointLabel]
382  + blockOffsets_[blockNlabel];
383 
384  if
385  (
386  mergeList_[PpointLabel]
387  != mergeList_[NpointLabel]
388  )
389  {
390  changedPointMerge = true;
391 
392  mergeList_[PpointLabel]
393  = mergeList_[NpointLabel]
394  = min
395  (
396  mergeList_[PpointLabel],
397  mergeList_[NpointLabel]
398  );
399  }
400  }
401  }
402  }
403  if (verboseOutput)
404  {
405  Info<< "." << flush;
406  }
407 
408  if (nPasses > 100)
409  {
411  << "Point merging failed after max number of passes."
412  << exit(FatalError);
413  }
414  }
415  while (changedPointMerge);
416 
417  if (verboseOutput)
418  {
419  Info<< endl;
420  }
421 
422  forAll(blockInternalFaces, blockFaceLabel)
423  {
424  label blockPlabel = faceOwnerBlocks[blockFaceLabel];
425  label blockNlabel = faceNeighbourBlocks[blockFaceLabel];
426 
427  const labelList& blockPfaces = blockCells[blockPlabel];
428  const labelList& blockNfaces = blockCells[blockNlabel];
429 
430  const pointField& blockPpoints = blocks[blockPlabel].points();
431  const pointField& blockNpoints = blocks[blockNlabel].points();
432 
433  bool foundFace = false;
434  label blockPfaceLabel;
435  for
436  (
437  blockPfaceLabel = 0;
438  blockPfaceLabel < blockPfaces.size();
439  blockPfaceLabel++
440  )
441  {
442  if
443  (
444  blockFaces[blockPfaces[blockPfaceLabel]]
445  == blockInternalFaces[blockFaceLabel]
446  )
447  {
448  foundFace = true;
449  break;
450  }
451  }
452 
453  if (!foundFace)
454  {
456  << "Cannot find merge face for block " << blockPlabel
457  << exit(FatalError);
458  }
459 
460  foundFace = false;
461  label blockNfaceLabel;
462  for
463  (
464  blockNfaceLabel = 0;
465  blockNfaceLabel < blockNfaces.size();
466  blockNfaceLabel++
467  )
468  {
469  if
470  (
471  blockFaces[blockNfaces[blockNfaceLabel]]
472  == blockInternalFaces[blockFaceLabel]
473  )
474  {
475  foundFace = true;
476  break;
477  }
478  }
479 
480  if (!foundFace)
481  {
483  << "Cannot find merge face for block " << blockNlabel
484  << exit(FatalError);
485  }
486 
487  const labelListList& blockPfaceFaces =
488  blocks[blockPlabel].boundaryPatches()[blockPfaceLabel];
489 
490  const labelListList& blockNfaceFaces =
491  blocks[blockNlabel].boundaryPatches()[blockNfaceLabel];
492 
493  forAll(blockPfaceFaces, blockPfaceFaceLabel)
494  {
495  const labelList& blockPfaceFacePoints
496  = blockPfaceFaces[blockPfaceFaceLabel];
497 
498  forAll(blockPfaceFacePoints, blockPfaceFacePointLabel)
499  {
500  label PpointLabel =
501  blockPfaceFacePoints[blockPfaceFacePointLabel]
502  + blockOffsets_[blockPlabel];
503 
504  if (mergeList_[PpointLabel] == -1)
505  {
507  << "Unable to merge point "
508  << blockPfaceFacePointLabel
509  << ' ' << blockPpoints[blockPfaceFacePointLabel]
510  << " of face "
511  << blockPfaceLabel
512  << " of block "
513  << blockPlabel
514  << exit(FatalError);
515  }
516  }
517  }
518 
519  forAll(blockNfaceFaces, blockNfaceFaceLabel)
520  {
521  const labelList& blockNfaceFacePoints
522  = blockNfaceFaces[blockNfaceFaceLabel];
523 
524  forAll(blockNfaceFacePoints, blockNfaceFacePointLabel)
525  {
526  label NpointLabel =
527  blockNfaceFacePoints[blockNfaceFacePointLabel]
528  + blockOffsets_[blockNlabel];
529 
530  if (mergeList_[NpointLabel] == -1)
531  {
533  << "unable to merge point "
534  << blockNfaceFacePointLabel
535  << ' ' << blockNpoints[blockNfaceFacePointLabel]
536  << " of face "
537  << blockNfaceLabel
538  << " of block "
539  << blockNlabel
540  << exit(FatalError);
541  }
542  }
543  }
544  }
545 
546 
547  // Sort merge list to return new point label (in new shorter list)
548  // given old point label
549  label newPointLabel = 0;
550 
551  forAll(mergeList_, pointLabel)
552  {
553  if (mergeList_[pointLabel] > pointLabel)
554  {
556  << "Merge list contains point index out of range"
557  << exit(FatalError);
558  }
559 
560  if
561  (
562  mergeList_[pointLabel] == -1
563  || mergeList_[pointLabel] == pointLabel
564  )
565  {
566  mergeList_[pointLabel] = newPointLabel;
567  newPointLabel++;
568  }
569  else
570  {
571  mergeList_[pointLabel] = mergeList_[mergeList_[pointLabel]];
572  }
573  }
574 
575  nPoints_ = newPointLabel;
576 }
577 
578 
579 // ************************************************************************* //
const polyMesh & topology() const
Return the blockMesh topology as a polyMesh.
Definition: blockMesh.C:82
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
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:253
SubList< face > subList
Declare type of subList.
Definition: List.H:155
const cellList & cells() const
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< label > labelList
A List of labels.
Definition: labelList.H:56
dimensioned< scalar > magSqr(const dimensioned< Type > &)
static const char nl
Definition: Ostream.H:262
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
void setSize(const label)
Reset size of List.
Definition: List.C:295
Ostream & flush(Ostream &os)
Flush stream.
Definition: Ostream.H:245
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1023
List< labelListList > labelListListList
A List of labelListList.
Definition: labelList.H:58
messageStream Info
const pointField & points() const
The points for the entire mesh.
Definition: blockMesh.C:118
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1017
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
List< cell > cellList
list of cells
Definition: cellList.H:42