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