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