00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "distributedTriSurfaceMesh.H"
00028 #include "mapDistribute.H"
00029 #include "Random.H"
00030 #include "addToRunTimeSelectionTable.H"
00031 #include "triangleFuncs.H"
00032 #include "matchPoints.H"
00033 #include "globalIndex.H"
00034 #include "Time.H"
00035
00036 #include "IFstream.H"
00037 #include "decompositionMethod.H"
00038 #include "vectorList.H"
00039
00040
00041
00042 namespace Foam
00043 {
00044
00045 defineTypeNameAndDebug(distributedTriSurfaceMesh, 0);
00046 addToRunTimeSelectionTable(searchableSurface, distributedTriSurfaceMesh, dict);
00047
00048 }
00049
00050
00051 template<>
00052 const char*
00053 Foam::NamedEnum<Foam::distributedTriSurfaceMesh::distributionType, 3>::names[] =
00054 {
00055 "follow",
00056 "independent",
00057 "frozen"
00058 };
00059
00060 const Foam::NamedEnum<Foam::distributedTriSurfaceMesh::distributionType, 3>
00061 Foam::distributedTriSurfaceMesh::distributionTypeNames_;
00062
00063
00064
00065
00066
00067 bool Foam::distributedTriSurfaceMesh::read()
00068 {
00069
00070 procBb_.setSize(Pstream::nProcs());
00071
00072 procBb_[Pstream::myProcNo()] = List<treeBoundBox>(dict_.lookup("bounds"));
00073 Pstream::gatherList(procBb_);
00074 Pstream::scatterList(procBb_);
00075
00076
00077 distType_ = distributionTypeNames_.read(dict_.lookup("distributionType"));
00078
00079
00080 mergeDist_ = readScalar(dict_.lookup("mergeDistance"));
00081
00082 return true;
00083 }
00084
00085
00086
00087 bool Foam::distributedTriSurfaceMesh::isLocal
00088 (
00089 const List<treeBoundBox>& myBbs,
00090 const point& start,
00091 const point& end
00092 )
00093 {
00094 forAll(myBbs, bbI)
00095 {
00096 if (myBbs[bbI].contains(start) && myBbs[bbI].contains(end))
00097 {
00098 return true;
00099 }
00100 }
00101 return false;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 void Foam::distributedTriSurfaceMesh::distributeSegment
00168 (
00169 const label segmentI,
00170 const point& start,
00171 const point& end,
00172
00173 DynamicList<segment>& allSegments,
00174 DynamicList<label>& allSegmentMap,
00175 List<DynamicList<label> >& sendMap
00176 ) const
00177 {
00178
00179 point clipPt;
00180
00181
00182
00183 if (isLocal(procBb_[Pstream::myProcNo()], start, end))
00184 {
00185 return;
00186 }
00187
00188
00189
00190
00191
00192 forAll(procBb_, procI)
00193 {
00194 if (procI != Pstream::myProcNo())
00195 {
00196 const List<treeBoundBox>& bbs = procBb_[procI];
00197
00198 if (isLocal(bbs, start, end))
00199 {
00200 sendMap[procI].append(allSegments.size());
00201 allSegmentMap.append(segmentI);
00202 allSegments.append(segment(start, end));
00203 return;
00204 }
00205 }
00206 }
00207
00208
00209
00210
00211 forAll(procBb_, procI)
00212 {
00213 const List<treeBoundBox>& bbs = procBb_[procI];
00214
00215 forAll(bbs, bbI)
00216 {
00217 const treeBoundBox& bb = bbs[bbI];
00218
00219
00220
00221
00222 if (bb.intersects(start, end, clipPt))
00223 {
00224 sendMap[procI].append(allSegments.size());
00225 allSegmentMap.append(segmentI);
00226 allSegments.append(segment(start, end));
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 }
00244 }
00245 }
00246
00247
00248 Foam::autoPtr<Foam::mapDistribute>
00249 Foam::distributedTriSurfaceMesh::distributeSegments
00250 (
00251 const pointField& start,
00252 const pointField& end,
00253
00254 List<segment>& allSegments,
00255 labelList& allSegmentMap
00256 ) const
00257 {
00258
00259
00260
00261 labelListList sendMap(Pstream::nProcs());
00262
00263 {
00264
00265
00266
00267
00268
00269 DynamicList<segment> dynAllSegments(start.size());
00270
00271 DynamicList<label> dynAllSegmentMap(start.size());
00272
00273 List<DynamicList<label> > dynSendMap(Pstream::nProcs());
00274
00275 forAll(start, segmentI)
00276 {
00277 distributeSegment
00278 (
00279 segmentI,
00280 start[segmentI],
00281 end[segmentI],
00282
00283 dynAllSegments,
00284 dynAllSegmentMap,
00285 dynSendMap
00286 );
00287 }
00288
00289
00290 sendMap.setSize(Pstream::nProcs());
00291 forAll(sendMap, procI)
00292 {
00293 dynSendMap[procI].shrink();
00294 sendMap[procI].transfer(dynSendMap[procI]);
00295 }
00296
00297 allSegments.transfer(dynAllSegments.shrink());
00298 allSegmentMap.transfer(dynAllSegmentMap.shrink());
00299 }
00300
00301
00302
00303 labelListList sendSizes(Pstream::nProcs());
00304 sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
00305 forAll(sendMap, procI)
00306 {
00307 sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
00308 }
00309 Pstream::gatherList(sendSizes);
00310 Pstream::scatterList(sendSizes);
00311
00312
00313
00314 labelListList constructMap(Pstream::nProcs());
00315
00316
00317 constructMap[Pstream::myProcNo()] = identity
00318 (
00319 sendMap[Pstream::myProcNo()].size()
00320 );
00321
00322 label segmentI = constructMap[Pstream::myProcNo()].size();
00323 forAll(constructMap, procI)
00324 {
00325 if (procI != Pstream::myProcNo())
00326 {
00327
00328 label nRecv = sendSizes[procI][Pstream::myProcNo()];
00329 constructMap[procI].setSize(nRecv);
00330
00331 for (label i = 0; i < nRecv; i++)
00332 {
00333 constructMap[procI][i] = segmentI++;
00334 }
00335 }
00336 }
00337
00338 return autoPtr<mapDistribute>
00339 (
00340 new mapDistribute
00341 (
00342 segmentI,
00343 sendMap,
00344 constructMap,
00345 true
00346 )
00347 );
00348 }
00349
00350
00351 void Foam::distributedTriSurfaceMesh::findLine
00352 (
00353 const bool nearestIntersection,
00354 const pointField& start,
00355 const pointField& end,
00356 List<pointIndexHit>& info
00357 ) const
00358 {
00359 const indexedOctree<treeDataTriSurface>& octree = tree();
00360
00361
00362 const globalIndex& triIndexer = globalTris();
00363
00364
00365 info.setSize(start.size());
00366 forAll(info, i)
00367 {
00368 info[i].setMiss();
00369 }
00370
00371
00372
00373
00374
00375 label nLocal = 0;
00376
00377 forAll(start, i)
00378 {
00379 if (isLocal(procBb_[Pstream::myProcNo()], start[i], end[i]))
00380 {
00381 if (nearestIntersection)
00382 {
00383 info[i] = octree.findLine(start[i], end[i]);
00384 }
00385 else
00386 {
00387 info[i] = octree.findLineAny(start[i], end[i]);
00388 }
00389
00390 if (info[i].hit())
00391 {
00392 info[i].setIndex(triIndexer.toGlobal(info[i].index()));
00393 }
00394 nLocal++;
00395 }
00396 }
00397
00398
00399 if
00400 (
00401 Pstream::parRun()
00402 && (
00403 returnReduce(nLocal, sumOp<label>())
00404 < returnReduce(start.size(), sumOp<label>())
00405 )
00406 )
00407 {
00408
00409
00410
00411
00412
00413
00414
00415
00416 List<segment> allSegments(start.size());
00417
00418 labelList allSegmentMap(start.size());
00419
00420 const autoPtr<mapDistribute> mapPtr
00421 (
00422 distributeSegments
00423 (
00424 start,
00425 end,
00426 allSegments,
00427 allSegmentMap
00428 )
00429 );
00430 const mapDistribute& map = mapPtr();
00431
00432 label nOldAllSegments = allSegments.size();
00433
00434
00435
00436
00437
00438 map.distribute
00439 (
00440 Pstream::nonBlocking,
00441 List<labelPair>(0),
00442 map.constructSize(),
00443 map.subMap(),
00444 map.constructMap(),
00445 allSegments
00446 );
00447
00448
00449
00450
00451
00452
00453 List<pointIndexHit> intersections(allSegments.size());
00454
00455 forAll(allSegments, i)
00456 {
00457 if (nearestIntersection)
00458 {
00459 intersections[i] = octree.findLine
00460 (
00461 allSegments[i].first(),
00462 allSegments[i].second()
00463 );
00464 }
00465 else
00466 {
00467 intersections[i] = octree.findLineAny
00468 (
00469 allSegments[i].first(),
00470 allSegments[i].second()
00471 );
00472 }
00473
00474
00475 if (intersections[i].hit())
00476 {
00477 intersections[i].setIndex
00478 (
00479 triIndexer.toGlobal(intersections[i].index())
00480 );
00481 }
00482 }
00483
00484
00485
00486
00487
00488 map.distribute
00489 (
00490
00491
00492
00493
00494
00495
00496 Pstream::nonBlocking,
00497 List<labelPair>(0),
00498 nOldAllSegments,
00499 map.constructMap(),
00500 map.subMap(),
00501 intersections
00502 );
00503
00504
00505
00506
00507
00508 forAll(intersections, i)
00509 {
00510 const pointIndexHit& allInfo = intersections[i];
00511 label segmentI = allSegmentMap[i];
00512 pointIndexHit& hitInfo = info[segmentI];
00513
00514 if (allInfo.hit())
00515 {
00516 if (!hitInfo.hit())
00517 {
00518
00519 hitInfo = allInfo;
00520 }
00521 else if (nearestIntersection)
00522 {
00523
00524 if
00525 (
00526 magSqr(allInfo.hitPoint()-start[segmentI])
00527 < magSqr(hitInfo.hitPoint()-start[segmentI])
00528 )
00529 {
00530 hitInfo = allInfo;
00531 }
00532 }
00533 }
00534 }
00535 }
00536 }
00537
00538
00539
00540
00541
00542 Foam::autoPtr<Foam::mapDistribute>
00543 Foam::distributedTriSurfaceMesh::calcLocalQueries
00544 (
00545 const List<pointIndexHit>& info,
00546 labelList& triangleIndex
00547 ) const
00548 {
00549 triangleIndex.setSize(info.size());
00550
00551 const globalIndex& triIndexer = globalTris();
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 labelList nSend(Pstream::nProcs(), 0);
00562
00563 forAll(info, i)
00564 {
00565 if (info[i].hit())
00566 {
00567 label procI = triIndexer.whichProcID(info[i].index());
00568 nSend[procI]++;
00569 }
00570 }
00571
00572
00573 labelListList sendMap(Pstream::nProcs());
00574 forAll(nSend, procI)
00575 {
00576 sendMap[procI].setSize(nSend[procI]);
00577 nSend[procI] = 0;
00578 }
00579
00580
00581 forAll(info, i)
00582 {
00583 if (info[i].hit())
00584 {
00585 label procI = triIndexer.whichProcID(info[i].index());
00586 triangleIndex[i] = triIndexer.toLocal(procI, info[i].index());
00587 sendMap[procI][nSend[procI]++] = i;
00588 }
00589 else
00590 {
00591 triangleIndex[i] = -1;
00592 }
00593 }
00594
00595
00596
00597
00598
00599 labelListList sendSizes(Pstream::nProcs());
00600 sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
00601 forAll(sendMap, procI)
00602 {
00603 sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
00604 }
00605 Pstream::gatherList(sendSizes);
00606 Pstream::scatterList(sendSizes);
00607
00608
00609
00610
00611
00612 labelListList constructMap(Pstream::nProcs());
00613
00614
00615 constructMap[Pstream::myProcNo()] = identity
00616 (
00617 sendMap[Pstream::myProcNo()].size()
00618 );
00619
00620 label segmentI = constructMap[Pstream::myProcNo()].size();
00621 forAll(constructMap, procI)
00622 {
00623 if (procI != Pstream::myProcNo())
00624 {
00625
00626 label nRecv = sendSizes[procI][Pstream::myProcNo()];
00627 constructMap[procI].setSize(nRecv);
00628
00629 for (label i = 0; i < nRecv; i++)
00630 {
00631 constructMap[procI][i] = segmentI++;
00632 }
00633 }
00634 }
00635
00636
00637
00638
00639
00640 autoPtr<mapDistribute> mapPtr
00641 (
00642 new mapDistribute
00643 (
00644 segmentI,
00645 sendMap,
00646 constructMap,
00647 true
00648 )
00649 );
00650 const mapDistribute& map = mapPtr();
00651
00652
00653
00654
00655
00656 map.distribute
00657 (
00658
00659
00660 Pstream::nonBlocking,
00661 List<labelPair>(0),
00662 map.constructSize(),
00663 map.subMap(),
00664 map.constructMap(),
00665 triangleIndex
00666 );
00667
00668
00669 return mapPtr;
00670 }
00671
00672
00673 Foam::label Foam::distributedTriSurfaceMesh::calcOverlappingProcs
00674 (
00675 const point& centre,
00676 const scalar radiusSqr,
00677 boolList& overlaps
00678 ) const
00679 {
00680 overlaps = false;
00681 label nOverlaps = 0;
00682
00683 forAll(procBb_, procI)
00684 {
00685 const List<treeBoundBox>& bbs = procBb_[procI];
00686
00687 forAll(bbs, bbI)
00688 {
00689 if (bbs[bbI].overlaps(centre, radiusSqr))
00690 {
00691 overlaps[procI] = true;
00692 nOverlaps++;
00693 break;
00694 }
00695 }
00696 }
00697 return nOverlaps;
00698 }
00699
00700
00701
00702
00703
00704 Foam::autoPtr<Foam::mapDistribute>
00705 Foam::distributedTriSurfaceMesh::calcLocalQueries
00706 (
00707 const pointField& centres,
00708 const scalarField& radiusSqr,
00709
00710 pointField& allCentres,
00711 scalarField& allRadiusSqr,
00712 labelList& allSegmentMap
00713 ) const
00714 {
00715
00716
00717
00718 labelListList sendMap(Pstream::nProcs());
00719
00720 {
00721
00722 DynamicList<point> dynAllCentres(centres.size());
00723 DynamicList<scalar> dynAllRadiusSqr(centres.size());
00724
00725 DynamicList<label> dynAllSegmentMap(centres.size());
00726
00727 List<DynamicList<label> > dynSendMap(Pstream::nProcs());
00728
00729
00730 boolList procBbOverlaps(Pstream::nProcs());
00731
00732 forAll(centres, centreI)
00733 {
00734
00735 calcOverlappingProcs
00736 (
00737 centres[centreI],
00738 radiusSqr[centreI],
00739 procBbOverlaps
00740 );
00741
00742 forAll(procBbOverlaps, procI)
00743 {
00744 if (procI != Pstream::myProcNo() && procBbOverlaps[procI])
00745 {
00746 dynSendMap[procI].append(dynAllCentres.size());
00747 dynAllSegmentMap.append(centreI);
00748 dynAllCentres.append(centres[centreI]);
00749 dynAllRadiusSqr.append(radiusSqr[centreI]);
00750 }
00751 }
00752 }
00753
00754
00755 sendMap.setSize(Pstream::nProcs());
00756 forAll(sendMap, procI)
00757 {
00758 dynSendMap[procI].shrink();
00759 sendMap[procI].transfer(dynSendMap[procI]);
00760 }
00761
00762 allCentres.transfer(dynAllCentres.shrink());
00763 allRadiusSqr.transfer(dynAllRadiusSqr.shrink());
00764 allSegmentMap.transfer(dynAllSegmentMap.shrink());
00765 }
00766
00767
00768
00769 labelListList sendSizes(Pstream::nProcs());
00770 sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
00771 forAll(sendMap, procI)
00772 {
00773 sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
00774 }
00775 Pstream::gatherList(sendSizes);
00776 Pstream::scatterList(sendSizes);
00777
00778
00779
00780 labelListList constructMap(Pstream::nProcs());
00781
00782
00783 constructMap[Pstream::myProcNo()] = identity
00784 (
00785 sendMap[Pstream::myProcNo()].size()
00786 );
00787
00788 label segmentI = constructMap[Pstream::myProcNo()].size();
00789 forAll(constructMap, procI)
00790 {
00791 if (procI != Pstream::myProcNo())
00792 {
00793
00794 label nRecv = sendSizes[procI][Pstream::myProcNo()];
00795 constructMap[procI].setSize(nRecv);
00796
00797 for (label i = 0; i < nRecv; i++)
00798 {
00799 constructMap[procI][i] = segmentI++;
00800 }
00801 }
00802 }
00803
00804 autoPtr<mapDistribute> mapPtr
00805 (
00806 new mapDistribute
00807 (
00808 segmentI,
00809 sendMap,
00810 constructMap,
00811 true
00812 )
00813 );
00814 return mapPtr;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824 Foam::List<Foam::List<Foam::treeBoundBox> >
00825 Foam::distributedTriSurfaceMesh::independentlyDistributedBbs
00826 (
00827 const triSurface& s
00828 )
00829 {
00830 if (!decomposer_.valid())
00831 {
00832
00833
00834 IOdictionary decomposeDict
00835 (
00836 IOobject
00837 (
00838 "decomposeParDict",
00839 searchableSurface::time().system(),
00840 searchableSurface::time(),
00841 IOobject::MUST_READ,
00842 IOobject::NO_WRITE,
00843 false
00844 )
00845 );
00846 decomposer_ = decompositionMethod::New(decomposeDict);
00847
00848 if (!decomposer_().parallelAware())
00849 {
00850 FatalErrorIn
00851 (
00852 "distributedTriSurfaceMesh::independentlyDistributedBbs"
00853 "(const triSurface&)"
00854 ) << "The decomposition method " << decomposer_().typeName
00855 << " does not decompose in parallel."
00856 << " Please choose one that does." << exit(FatalError);
00857 }
00858 }
00859
00860
00861 pointField triCentres(s.size());
00862 forAll (s, triI)
00863 {
00864 triCentres[triI] = s[triI].centre(s.points());
00865 }
00866
00867
00868 labelList distribution(decomposer_->decompose(triCentres));
00869
00870
00871
00872
00873 List<List<treeBoundBox> > bbs(Pstream::nProcs());
00874 forAll(bbs, procI)
00875 {
00876 bbs[procI].setSize(1);
00877
00878 bbs[procI][0].min() = point( VGREAT, VGREAT, VGREAT);
00879 bbs[procI][0].max() = point(-VGREAT, -VGREAT, -VGREAT);
00880 }
00881
00882 forAll (s, triI)
00883 {
00884 point& bbMin = bbs[distribution[triI]][0].min();
00885 point& bbMax = bbs[distribution[triI]][0].max();
00886
00887 const labelledTri& f = s[triI];
00888 const point& p0 = s.points()[f[0]];
00889 const point& p1 = s.points()[f[1]];
00890 const point& p2 = s.points()[f[2]];
00891
00892 bbMin = min(bbMin, p0);
00893 bbMin = min(bbMin, p1);
00894 bbMin = min(bbMin, p2);
00895
00896 bbMax = max(bbMax, p0);
00897 bbMax = max(bbMax, p1);
00898 bbMax = max(bbMax, p2);
00899 }
00900
00901
00902 forAll(bbs, procI)
00903 {
00904 forAll(bbs[procI], i)
00905 {
00906 reduce(bbs[procI][i].min(), minOp<point>());
00907 reduce(bbs[procI][i].max(), maxOp<point>());
00908 }
00909 }
00910 return bbs;
00911 }
00912
00913
00914 void Foam::distributedTriSurfaceMesh::calcBounds
00915 (
00916 boundBox& bb,
00917 label& nPoints
00918 ) const
00919 {
00920
00921
00922
00923 PackedList<1> pointIsUsed(points().size());
00924 pointIsUsed = 0U;
00925
00926 nPoints = 0;
00927 bb.min() = point(VGREAT, VGREAT, VGREAT);
00928 bb.max() = point(-VGREAT, -VGREAT, -VGREAT);
00929
00930 const triSurface& s = static_cast<const triSurface&>(*this);
00931
00932 forAll(s, triI)
00933 {
00934 const labelledTri& f = s[triI];
00935
00936 forAll(f, fp)
00937 {
00938 label pointI = f[fp];
00939 if (pointIsUsed.set(pointI, 1))
00940 {
00941 bb.min() = ::Foam::min(bb.min(), points()[pointI]);
00942 bb.max() = ::Foam::max(bb.max(), points()[pointI]);
00943 nPoints++;
00944 }
00945 }
00946 }
00947 }
00948
00949
00950
00951 bool Foam::distributedTriSurfaceMesh::overlaps
00952 (
00953 const List<treeBoundBox>& bbs,
00954 const point& p0,
00955 const point& p1,
00956 const point& p2
00957 )
00958 {
00959 forAll(bbs, bbI)
00960 {
00961 const treeBoundBox& bb = bbs[bbI];
00962
00963 boundBox triBb(p0, p0);
00964 triBb.min() = min(triBb.min(), p1);
00965 triBb.min() = min(triBb.min(), p2);
00966
00967 triBb.max() = max(triBb.max(), p1);
00968 triBb.max() = max(triBb.max(), p2);
00969
00970
00971
00972
00973
00974 if (bb.overlaps(triBb))
00975 {
00976
00977 if (bb.contains(p0) || bb.contains(p1) || bb.contains(p2))
00978 {
00979
00980 return true;
00981 }
00982
00983
00984
00985
00986 bool intersect = triangleFuncs::intersectBb(p0, p1, p2, bb);
00987
00988 if (intersect)
00989 {
00990 return true;
00991 }
00992 }
00993 }
00994 return false;
00995 }
00996
00997
00998 void Foam::distributedTriSurfaceMesh::subsetMeshMap
00999 (
01000 const triSurface& s,
01001 const boolList& include,
01002 const label nIncluded,
01003 labelList& newToOldPoints,
01004 labelList& oldToNewPoints,
01005 labelList& newToOldFaces
01006 )
01007 {
01008 newToOldFaces.setSize(nIncluded);
01009 newToOldPoints.setSize(s.points().size());
01010 oldToNewPoints.setSize(s.points().size());
01011 oldToNewPoints = -1;
01012 {
01013 label faceI = 0;
01014 label pointI = 0;
01015
01016 forAll(include, oldFacei)
01017 {
01018 if (include[oldFacei])
01019 {
01020
01021 newToOldFaces[faceI++] = oldFacei;
01022
01023
01024 const labelledTri& tri = s[oldFacei];
01025
01026 forAll(tri, fp)
01027 {
01028 label oldPointI = tri[fp];
01029
01030 if (oldToNewPoints[oldPointI] == -1)
01031 {
01032 oldToNewPoints[oldPointI] = pointI;
01033 newToOldPoints[pointI++] = oldPointI;
01034 }
01035 }
01036 }
01037 }
01038 newToOldPoints.setSize(pointI);
01039 }
01040 }
01041
01042
01043 Foam::triSurface Foam::distributedTriSurfaceMesh::subsetMesh
01044 (
01045 const triSurface& s,
01046 const labelList& newToOldPoints,
01047 const labelList& oldToNewPoints,
01048 const labelList& newToOldFaces
01049 )
01050 {
01051
01052 pointField newPoints(newToOldPoints.size());
01053 forAll(newToOldPoints, i)
01054 {
01055 newPoints[i] = s.points()[newToOldPoints[i]];
01056 }
01057
01058 List<labelledTri> newTriangles(newToOldFaces.size());
01059
01060 forAll(newToOldFaces, i)
01061 {
01062
01063 const labelledTri& tri = s[newToOldFaces[i]];
01064
01065 newTriangles[i][0] = oldToNewPoints[tri[0]];
01066 newTriangles[i][1] = oldToNewPoints[tri[1]];
01067 newTriangles[i][2] = oldToNewPoints[tri[2]];
01068 newTriangles[i].region() = tri.region();
01069 }
01070
01071
01072 return triSurface(newTriangles, s.patches(), newPoints, true);
01073 }
01074
01075
01076 Foam::triSurface Foam::distributedTriSurfaceMesh::subsetMesh
01077 (
01078 const triSurface& s,
01079 const boolList& include,
01080 labelList& newToOldPoints,
01081 labelList& newToOldFaces
01082 )
01083 {
01084 label n = 0;
01085
01086 forAll(include, i)
01087 {
01088 if (include[i])
01089 {
01090 n++;
01091 }
01092 }
01093
01094 labelList oldToNewPoints;
01095 subsetMeshMap
01096 (
01097 s,
01098 include,
01099 n,
01100 newToOldPoints,
01101 oldToNewPoints,
01102 newToOldFaces
01103 );
01104
01105 return subsetMesh
01106 (
01107 s,
01108 newToOldPoints,
01109 oldToNewPoints,
01110 newToOldFaces
01111 );
01112 }
01113
01114
01115 Foam::triSurface Foam::distributedTriSurfaceMesh::subsetMesh
01116 (
01117 const triSurface& s,
01118 const labelList& newToOldFaces,
01119 labelList& newToOldPoints
01120 )
01121 {
01122 const boolList include
01123 (
01124 createWithValues<boolList>
01125 (
01126 s.size(),
01127 false,
01128 newToOldFaces,
01129 true
01130 )
01131 );
01132
01133 newToOldPoints.setSize(s.points().size());
01134 labelList oldToNewPoints(s.points().size(), -1);
01135 {
01136 label pointI = 0;
01137
01138 forAll(include, oldFacei)
01139 {
01140 if (include[oldFacei])
01141 {
01142
01143 const labelledTri& tri = s[oldFacei];
01144
01145 forAll(tri, fp)
01146 {
01147 label oldPointI = tri[fp];
01148
01149 if (oldToNewPoints[oldPointI] == -1)
01150 {
01151 oldToNewPoints[oldPointI] = pointI;
01152 newToOldPoints[pointI++] = oldPointI;
01153 }
01154 }
01155 }
01156 }
01157 newToOldPoints.setSize(pointI);
01158 }
01159
01160 return subsetMesh
01161 (
01162 s,
01163 newToOldPoints,
01164 oldToNewPoints,
01165 newToOldFaces
01166 );
01167 }
01168
01169
01170 Foam::label Foam::distributedTriSurfaceMesh::findTriangle
01171 (
01172 const List<labelledTri>& allFaces,
01173 const labelListList& allPointFaces,
01174 const labelledTri& otherF
01175 )
01176 {
01177
01178 const labelList& pFaces = allPointFaces[otherF[0]];
01179
01180 forAll(pFaces, i)
01181 {
01182 const labelledTri& f = allFaces[pFaces[i]];
01183
01184 if (f.region() == otherF.region())
01185 {
01186
01187 label fp0 = findIndex(f, otherF[0]);
01188
01189 label fp1 = f.fcIndex(fp0);
01190 label fp2 = f.fcIndex(fp1);
01191
01192 if (f[fp1] == otherF[1] && f[fp2] == otherF[2])
01193 {
01194 return pFaces[i];
01195 }
01196 }
01197 }
01198 return -1;
01199 }
01200
01201
01202
01203 void Foam::distributedTriSurfaceMesh::merge
01204 (
01205 const scalar mergeDist,
01206 const List<labelledTri>& subTris,
01207 const pointField& subPoints,
01208
01209 List<labelledTri>& allTris,
01210 pointField& allPoints,
01211
01212 labelList& faceConstructMap,
01213 labelList& pointConstructMap
01214 )
01215 {
01216 labelList subToAll;
01217 matchPoints
01218 (
01219 subPoints,
01220 allPoints,
01221 scalarField(subPoints.size(), mergeDist),
01222 false,
01223 pointConstructMap
01224 );
01225
01226 label nOldAllPoints = allPoints.size();
01227
01228
01229
01230
01231
01232 label allPointI = nOldAllPoints;
01233 forAll(pointConstructMap, pointI)
01234 {
01235 if (pointConstructMap[pointI] == -1)
01236 {
01237 pointConstructMap[pointI] = allPointI++;
01238 }
01239 }
01240
01241 if (allPointI > nOldAllPoints)
01242 {
01243 allPoints.setSize(allPointI);
01244
01245 forAll(pointConstructMap, pointI)
01246 {
01247 if (pointConstructMap[pointI] >= nOldAllPoints)
01248 {
01249 allPoints[pointConstructMap[pointI]] = subPoints[pointI];
01250 }
01251 }
01252 }
01253
01254
01255
01256 labelListList allPointFaces;
01257 invertManyToMany(nOldAllPoints, allTris, allPointFaces);
01258
01259
01260
01261
01262
01263 label allTriI = allTris.size();
01264 allTris.setSize(allTriI + subTris.size());
01265
01266 faceConstructMap.setSize(subTris.size());
01267
01268 forAll(subTris, triI)
01269 {
01270 const labelledTri& subTri = subTris[triI];
01271
01272
01273 labelledTri mappedTri
01274 (
01275 pointConstructMap[subTri[0]],
01276 pointConstructMap[subTri[1]],
01277 pointConstructMap[subTri[2]],
01278 subTri.region()
01279 );
01280
01281
01282
01283 bool fullMatch = true;
01284
01285 forAll(mappedTri, fp)
01286 {
01287 if (mappedTri[fp] >= nOldAllPoints)
01288 {
01289 fullMatch = false;
01290 break;
01291 }
01292 }
01293
01294 if (fullMatch)
01295 {
01296
01297
01298 label i = findTriangle
01299 (
01300 allTris,
01301 allPointFaces,
01302 mappedTri
01303 );
01304
01305 if (i == -1)
01306 {
01307
01308 faceConstructMap[triI] = allTriI;
01309 allTris[allTriI] = mappedTri;
01310 allTriI++;
01311 }
01312 else
01313 {
01314 faceConstructMap[triI] = i;
01315 }
01316 }
01317 else
01318 {
01319
01320 faceConstructMap[triI] = allTriI;
01321 allTris[allTriI] = mappedTri;
01322 allTriI++;
01323 }
01324 }
01325 allTris.setSize(allTriI);
01326 }
01327
01328
01329
01330
01331 Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
01332 (
01333 const IOobject& io,
01334 const triSurface& s,
01335 const dictionary& dict
01336 )
01337 :
01338 triSurfaceMesh(io, s),
01339 dict_(io, dict)
01340 {
01341 read();
01342
01343 if (debug)
01344 {
01345 Info<< "Constructed from triSurface:" << endl;
01346 writeStats(Info);
01347
01348 labelList nTris(Pstream::nProcs());
01349 nTris[Pstream::myProcNo()] = triSurface::size();
01350 Pstream::gatherList(nTris);
01351 Pstream::scatterList(nTris);
01352
01353 Info<< endl<< "\tproc\ttris\tbb" << endl;
01354 forAll(nTris, procI)
01355 {
01356 Info<< '\t' << procI << '\t' << nTris[procI]
01357 << '\t' << procBb_[procI] << endl;
01358 }
01359 Info<< endl;
01360 }
01361 }
01362
01363
01364 Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh(const IOobject& io)
01365 :
01366
01367 triSurfaceMesh
01368 (
01369 IOobject
01370 (
01371 io.name(),
01372 io.time().findInstance(io.local(), word::null),
01373 io.local(),
01374 io.db(),
01375 io.readOpt(),
01376 io.writeOpt(),
01377 io.registerObject()
01378 )
01379 ),
01380 dict_
01381 (
01382 IOobject
01383 (
01384 searchableSurface::name() + "Dict",
01385 searchableSurface::instance(),
01386 searchableSurface::local(),
01387 searchableSurface::db(),
01388 searchableSurface::readOpt(),
01389 searchableSurface::writeOpt(),
01390 searchableSurface::registerObject()
01391 )
01392 )
01393 {
01394 read();
01395
01396 if (debug)
01397 {
01398 Info<< "Read distributedTriSurface from " << io.objectPath()
01399 << ':' << endl;
01400 writeStats(Info);
01401
01402 labelList nTris(Pstream::nProcs());
01403 nTris[Pstream::myProcNo()] = triSurface::size();
01404 Pstream::gatherList(nTris);
01405 Pstream::scatterList(nTris);
01406
01407 Info<< endl<< "\tproc\ttris\tbb" << endl;
01408 forAll(nTris, procI)
01409 {
01410 Info<< '\t' << procI << '\t' << nTris[procI]
01411 << '\t' << procBb_[procI] << endl;
01412 }
01413 Info<< endl;
01414 }
01415 }
01416
01417
01418 Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
01419 (
01420 const IOobject& io,
01421 const dictionary& dict
01422 )
01423 :
01424
01425 triSurfaceMesh
01426 (
01427 IOobject
01428 (
01429 io.name(),
01430 io.time().findInstance(io.local(), word::null),
01431 io.local(),
01432 io.db(),
01433 io.readOpt(),
01434 io.writeOpt(),
01435 io.registerObject()
01436 ),
01437 dict
01438 ),
01439 dict_
01440 (
01441 IOobject
01442 (
01443 searchableSurface::name() + "Dict",
01444 searchableSurface::instance(),
01445 searchableSurface::local(),
01446 searchableSurface::db(),
01447 searchableSurface::readOpt(),
01448 searchableSurface::writeOpt(),
01449 searchableSurface::registerObject()
01450 )
01451 )
01452 {
01453 read();
01454
01455 if (debug)
01456 {
01457 Info<< "Read distributedTriSurface from " << io.objectPath()
01458 << " and dictionary:" << endl;
01459 writeStats(Info);
01460
01461 labelList nTris(Pstream::nProcs());
01462 nTris[Pstream::myProcNo()] = triSurface::size();
01463 Pstream::gatherList(nTris);
01464 Pstream::scatterList(nTris);
01465
01466 Info<< endl<< "\tproc\ttris\tbb" << endl;
01467 forAll(nTris, procI)
01468 {
01469 Info<< '\t' << procI << '\t' << nTris[procI]
01470 << '\t' << procBb_[procI] << endl;
01471 }
01472 Info<< endl;
01473 }
01474 }
01475
01476
01477
01478
01479 Foam::distributedTriSurfaceMesh::~distributedTriSurfaceMesh()
01480 {
01481 clearOut();
01482 }
01483
01484
01485 void Foam::distributedTriSurfaceMesh::clearOut()
01486 {
01487 globalTris_.clear();
01488 triSurfaceMesh::clearOut();
01489 }
01490
01491
01492
01493
01494 const Foam::globalIndex& Foam::distributedTriSurfaceMesh::globalTris() const
01495 {
01496 if (!globalTris_.valid())
01497 {
01498 globalTris_.reset(new globalIndex(triSurface::size()));
01499 }
01500 return globalTris_;
01501 }
01502
01503
01504 void Foam::distributedTriSurfaceMesh::findNearest
01505 (
01506 const pointField& samples,
01507 const scalarField& nearestDistSqr,
01508 List<pointIndexHit>& info
01509 ) const
01510 {
01511 const indexedOctree<treeDataTriSurface>& octree = tree();
01512
01513
01514 const globalIndex& triIndexer = globalTris();
01515
01516
01517
01518
01519
01520 info.setSize(samples.size());
01521 forAll(info, i)
01522 {
01523 info[i].setMiss();
01524 }
01525
01526
01527
01528
01529
01530
01531 label nLocal = 0;
01532
01533 {
01534
01535 boolList procBbOverlaps(Pstream::nProcs());
01536
01537 forAll(samples, i)
01538 {
01539
01540 label nProcs = calcOverlappingProcs
01541 (
01542 samples[i],
01543 nearestDistSqr[i],
01544 procBbOverlaps
01545 );
01546
01547
01548 if (procBbOverlaps[Pstream::myProcNo()])
01549 {
01550 info[i] = octree.findNearest(samples[i], nearestDistSqr[i]);
01551 if (info[i].hit())
01552 {
01553 info[i].setIndex(triIndexer.toGlobal(info[i].index()));
01554 }
01555 if (nProcs == 1)
01556 {
01557
01558 nLocal++;
01559 }
01560 }
01561 }
01562 }
01563
01564
01565 if
01566 (
01567 Pstream::parRun()
01568 && (
01569 returnReduce(nLocal, sumOp<label>())
01570 < returnReduce(samples.size(), sumOp<label>())
01571 )
01572 )
01573 {
01574
01575
01576
01577
01578
01579
01580 pointField allCentres;
01581 scalarField allRadiusSqr;
01582 labelList allSegmentMap;
01583 autoPtr<mapDistribute> mapPtr
01584 (
01585 calcLocalQueries
01586 (
01587 samples,
01588 nearestDistSqr,
01589
01590 allCentres,
01591 allRadiusSqr,
01592 allSegmentMap
01593 )
01594 );
01595 const mapDistribute& map = mapPtr();
01596
01597
01598
01599
01600
01601 map.distribute
01602 (
01603
01604
01605 Pstream::nonBlocking,
01606 List<labelPair>(0),
01607 map.constructSize(),
01608 map.subMap(),
01609 map.constructMap(),
01610 allCentres
01611 );
01612 map.distribute
01613 (
01614
01615
01616 Pstream::nonBlocking,
01617 List<labelPair>(0),
01618 map.constructSize(),
01619 map.subMap(),
01620 map.constructMap(),
01621 allRadiusSqr
01622 );
01623
01624
01625
01626
01627
01628 List<pointIndexHit> allInfo(allCentres.size());
01629 forAll(allInfo, i)
01630 {
01631 allInfo[i] = octree.findNearest
01632 (
01633 allCentres[i],
01634 allRadiusSqr[i]
01635 );
01636 if (allInfo[i].hit())
01637 {
01638 allInfo[i].setIndex(triIndexer.toGlobal(allInfo[i].index()));
01639 }
01640 }
01641
01642
01643
01644
01645
01646 map.distribute
01647 (
01648
01649
01650
01651
01652
01653
01654 Pstream::nonBlocking,
01655 List<labelPair>(0),
01656 allSegmentMap.size(),
01657 map.constructMap(),
01658 map.subMap(),
01659 allInfo
01660 );
01661
01662
01663
01664
01665
01666 forAll(allInfo, i)
01667 {
01668 if (allInfo[i].hit())
01669 {
01670 label pointI = allSegmentMap[i];
01671
01672 if (!info[pointI].hit())
01673 {
01674
01675 info[pointI] = allInfo[i];
01676 }
01677 else
01678 {
01679
01680 if
01681 (
01682 magSqr(allInfo[i].hitPoint()-samples[pointI])
01683 < magSqr(info[pointI].hitPoint()-samples[pointI])
01684 )
01685 {
01686 info[pointI] = allInfo[i];
01687 }
01688 }
01689 }
01690 }
01691 }
01692 }
01693
01694
01695 void Foam::distributedTriSurfaceMesh::findLine
01696 (
01697 const pointField& start,
01698 const pointField& end,
01699 List<pointIndexHit>& info
01700 ) const
01701 {
01702 findLine
01703 (
01704 true,
01705 start,
01706 end,
01707 info
01708 );
01709 }
01710
01711
01712 void Foam::distributedTriSurfaceMesh::findLineAny
01713 (
01714 const pointField& start,
01715 const pointField& end,
01716 List<pointIndexHit>& info
01717 ) const
01718 {
01719 findLine
01720 (
01721 true,
01722 start,
01723 end,
01724 info
01725 );
01726 }
01727
01728
01729 void Foam::distributedTriSurfaceMesh::findLineAll
01730 (
01731 const pointField& start,
01732 const pointField& end,
01733 List<List<pointIndexHit> >& info
01734 ) const
01735 {
01736
01737
01738
01739
01740
01741
01742 List<pointIndexHit> hitInfo(start.size());
01743
01744 findLine
01745 (
01746 true,
01747 start,
01748 end,
01749 hitInfo
01750 );
01751
01752
01753
01754
01755
01756
01757
01758 const vectorField dirVec(end-start);
01759 const scalarField magSqrDirVec(magSqr(dirVec));
01760 const vectorField smallVec
01761 (
01762 Foam::sqrt(SMALL)*dirVec
01763 + vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
01764 );
01765
01766
01767 labelList pointMap(start.size());
01768 pointField e0(start.size());
01769 pointField e1(start.size());
01770 label compactI = 0;
01771
01772 info.setSize(hitInfo.size());
01773 forAll(hitInfo, pointI)
01774 {
01775 if (hitInfo[pointI].hit())
01776 {
01777 info[pointI].setSize(1);
01778 info[pointI][0] = hitInfo[pointI];
01779
01780 point pt = hitInfo[pointI].hitPoint() + smallVec[pointI];
01781
01782 if (((pt-start[pointI])&dirVec[pointI]) <= magSqrDirVec[pointI])
01783 {
01784 e0[compactI] = pt;
01785 e1[compactI] = end[pointI];
01786 pointMap[compactI] = pointI;
01787 compactI++;
01788 }
01789 }
01790 else
01791 {
01792 info[pointI].clear();
01793 }
01794 }
01795
01796 e0.setSize(compactI);
01797 e1.setSize(compactI);
01798 pointMap.setSize(compactI);
01799
01800 while (returnReduce(e0.size(), sumOp<label>()) > 0)
01801 {
01802 findLine
01803 (
01804 true,
01805 e0,
01806 e1,
01807 hitInfo
01808 );
01809
01810
01811
01812 label compactI = 0;
01813 forAll(hitInfo, i)
01814 {
01815 if (hitInfo[i].hit())
01816 {
01817 label pointI = pointMap[i];
01818
01819 label sz = info[pointI].size();
01820 info[pointI].setSize(sz+1);
01821 info[pointI][sz] = hitInfo[i];
01822
01823 point pt = hitInfo[i].hitPoint() + smallVec[pointI];
01824
01825 if (((pt-start[pointI])&dirVec[pointI]) <= magSqrDirVec[pointI])
01826 {
01827 e0[compactI] = pt;
01828 e1[compactI] = end[pointI];
01829 pointMap[compactI] = pointI;
01830 compactI++;
01831 }
01832 }
01833 }
01834
01835
01836 e0.setSize(compactI);
01837 e1.setSize(compactI);
01838 pointMap.setSize(compactI);
01839 }
01840 }
01841
01842
01843 void Foam::distributedTriSurfaceMesh::getRegion
01844 (
01845 const List<pointIndexHit>& info,
01846 labelList& region
01847 ) const
01848 {
01849 if (!Pstream::parRun())
01850 {
01851 region.setSize(info.size());
01852 forAll(info, i)
01853 {
01854 if (info[i].hit())
01855 {
01856 region[i] = triSurface::operator[](info[i].index()).region();
01857 }
01858 else
01859 {
01860 region[i] = -1;
01861 }
01862 }
01863 return;
01864 }
01865
01866
01867
01868
01869
01870 labelList triangleIndex(info.size());
01871 autoPtr<mapDistribute> mapPtr
01872 (
01873 calcLocalQueries
01874 (
01875 info,
01876 triangleIndex
01877 )
01878 );
01879 const mapDistribute& map = mapPtr();
01880
01881
01882
01883
01884
01885 const triSurface& s = static_cast<const triSurface&>(*this);
01886
01887 region.setSize(triangleIndex.size());
01888
01889 forAll(triangleIndex, i)
01890 {
01891 label triI = triangleIndex[i];
01892 region[i] = s[triI].region();
01893 }
01894
01895
01896
01897
01898
01899 map.distribute
01900 (
01901
01902
01903
01904
01905
01906
01907 Pstream::nonBlocking,
01908 List<labelPair>(0),
01909 info.size(),
01910 map.constructMap(),
01911 map.subMap(),
01912 region
01913 );
01914 }
01915
01916
01917 void Foam::distributedTriSurfaceMesh::getNormal
01918 (
01919 const List<pointIndexHit>& info,
01920 vectorField& normal
01921 ) const
01922 {
01923 if (!Pstream::parRun())
01924 {
01925 normal.setSize(info.size());
01926
01927 forAll(info, i)
01928 {
01929 if (info[i].hit())
01930 {
01931 normal[i] = faceNormals()[info[i].index()];
01932 }
01933 else
01934 {
01935
01936 normal[i] = vector::zero;
01937 }
01938 }
01939 return;
01940 }
01941
01942
01943
01944
01945
01946 labelList triangleIndex(info.size());
01947 autoPtr<mapDistribute> mapPtr
01948 (
01949 calcLocalQueries
01950 (
01951 info,
01952 triangleIndex
01953 )
01954 );
01955 const mapDistribute& map = mapPtr();
01956
01957
01958
01959
01960
01961 const triSurface& s = static_cast<const triSurface&>(*this);
01962
01963 normal.setSize(triangleIndex.size());
01964
01965 forAll(triangleIndex, i)
01966 {
01967 label triI = triangleIndex[i];
01968 normal[i] = s[triI].normal(s.points());
01969 normal[i] /= mag(normal[i]) + VSMALL;
01970 }
01971
01972
01973
01974
01975
01976 map.distribute
01977 (
01978
01979
01980
01981
01982
01983
01984 Pstream::nonBlocking,
01985 List<labelPair>(0),
01986 info.size(),
01987 map.constructMap(),
01988 map.subMap(),
01989 normal
01990 );
01991 }
01992
01993
01994 void Foam::distributedTriSurfaceMesh::getField
01995 (
01996 const word& fieldName,
01997 const List<pointIndexHit>& info,
01998 labelList& values
01999 ) const
02000 {
02001 const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
02002 (
02003 fieldName
02004 );
02005
02006
02007 if (!Pstream::parRun())
02008 {
02009 values.setSize(info.size());
02010 forAll(info, i)
02011 {
02012 if (info[i].hit())
02013 {
02014 values[i] = fld[info[i].index()];
02015 }
02016 }
02017 return;
02018 }
02019
02020
02021
02022
02023
02024 labelList triangleIndex(info.size());
02025 autoPtr<mapDistribute> mapPtr
02026 (
02027 calcLocalQueries
02028 (
02029 info,
02030 triangleIndex
02031 )
02032 );
02033 const mapDistribute& map = mapPtr();
02034
02035
02036
02037
02038
02039 values.setSize(triangleIndex.size());
02040
02041 forAll(triangleIndex, i)
02042 {
02043 label triI = triangleIndex[i];
02044 values[i] = fld[triI];
02045 }
02046
02047
02048
02049
02050
02051 map.distribute
02052 (
02053 Pstream::nonBlocking,
02054 List<labelPair>(0),
02055 info.size(),
02056 map.constructMap(),
02057 map.subMap(),
02058 values
02059 );
02060 }
02061
02062
02063 void Foam::distributedTriSurfaceMesh::getVolumeType
02064 (
02065 const pointField& points,
02066 List<volumeType>& volType
02067 ) const
02068 {
02069 FatalErrorIn
02070 (
02071 "distributedTriSurfaceMesh::getVolumeType"
02072 "(const pointField&, List<volumeType>&) const"
02073 ) << "Volume type not supported for distributed surfaces."
02074 << exit(FatalError);
02075 }
02076
02077
02078
02079 Foam::triSurface Foam::distributedTriSurfaceMesh::overlappingSurface
02080 (
02081 const triSurface& s,
02082 const List<treeBoundBox>& bbs,
02083
02084 labelList& subPointMap,
02085 labelList& subFaceMap
02086 )
02087 {
02088
02089 boolList includedFace(s.size(), false);
02090
02091
02092 List<treeBoundBox> bbsX(bbs.size());
02093 const scalar eps = 1.0e-4;
02094 forAll(bbs, i)
02095 {
02096 const point mid = 0.5*(bbs[i].min() + bbs[i].max());
02097 const vector halfSpan = (1.0+eps)*(bbs[i].max() - mid);
02098
02099 bbsX[i].min() = mid - halfSpan;
02100 bbsX[i].max() = mid + halfSpan;
02101 }
02102
02103 forAll(s, triI)
02104 {
02105 const labelledTri& f = s[triI];
02106 const point& p0 = s.points()[f[0]];
02107 const point& p1 = s.points()[f[1]];
02108 const point& p2 = s.points()[f[2]];
02109
02110 if (overlaps(bbsX, p0, p1, p2))
02111 {
02112 includedFace[triI] = true;
02113 }
02114 }
02115
02116 return subsetMesh(s, includedFace, subPointMap, subFaceMap);
02117 }
02118
02119
02120 void Foam::distributedTriSurfaceMesh::distribute
02121 (
02122 const List<treeBoundBox>& bbs,
02123 const bool keepNonLocal,
02124 autoPtr<mapDistribute>& faceMap,
02125 autoPtr<mapDistribute>& pointMap
02126 )
02127 {
02128
02129
02130
02131 {
02132 List<List<treeBoundBox> > newProcBb(Pstream::nProcs());
02133
02134 switch(distType_)
02135 {
02136 case FOLLOW:
02137 newProcBb[Pstream::myProcNo()].setSize(bbs.size());
02138 forAll(bbs, i)
02139 {
02140 newProcBb[Pstream::myProcNo()][i] = bbs[i];
02141 }
02142 Pstream::gatherList(newProcBb);
02143 Pstream::scatterList(newProcBb);
02144 break;
02145
02146 case INDEPENDENT:
02147 newProcBb = independentlyDistributedBbs(*this);
02148 break;
02149
02150 case FROZEN:
02151 return;
02152 break;
02153
02154 default:
02155 FatalErrorIn("distributedTriSurfaceMesh::distribute(..)")
02156 << "Unsupported distribution type." << exit(FatalError);
02157 break;
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167 if (newProcBb == procBb_)
02168 {
02169 return;
02170 }
02171 else
02172 {
02173 procBb_.transfer(newProcBb);
02174 dict_.set("bounds", procBb_[Pstream::myProcNo()]);
02175 }
02176 }
02177
02178
02179
02180 if (debug)
02181 {
02182 labelList nTris(Pstream::nProcs());
02183 nTris[Pstream::myProcNo()] = triSurface::size();
02184 Pstream::gatherList(nTris);
02185 Pstream::scatterList(nTris);
02186
02187 Info<< "distributedTriSurfaceMesh::distribute : before distribution:"
02188 << endl
02189 << "\tproc\ttris" << endl;
02190
02191 forAll(nTris, procI)
02192 {
02193 Info<< '\t' << procI << '\t' << nTris[procI] << endl;
02194 }
02195 Info<< endl;
02196 }
02197
02198
02199
02200
02201
02202 labelListList faceSendMap(Pstream::nProcs());
02203 labelListList pointSendMap(Pstream::nProcs());
02204
02205 forAll(procBb_, procI)
02206 {
02207 overlappingSurface
02208 (
02209 *this,
02210 procBb_[procI],
02211 pointSendMap[procI],
02212 faceSendMap[procI]
02213 );
02214
02215 if (debug)
02216 {
02217
02218
02219
02220 }
02221 }
02222
02223 if (keepNonLocal)
02224 {
02225
02226
02227
02228 const triSurface& s = static_cast<const triSurface&>(*this);
02229
02230 boolList includedFace(s.size(), true);
02231
02232 forAll(faceSendMap, procI)
02233 {
02234 if (procI != Pstream::myProcNo())
02235 {
02236 forAll(faceSendMap[procI], i)
02237 {
02238 includedFace[faceSendMap[procI][i]] = false;
02239 }
02240 }
02241 }
02242
02243
02244
02245
02246 forAll(faceSendMap[Pstream::myProcNo()], i)
02247 {
02248 includedFace[faceSendMap[Pstream::myProcNo()][i]] = true;
02249 }
02250
02251 subsetMesh
02252 (
02253 s,
02254 includedFace,
02255 pointSendMap[Pstream::myProcNo()],
02256 faceSendMap[Pstream::myProcNo()]
02257 );
02258 }
02259
02260
02261
02262
02263
02264 labelListList faceSendSizes(Pstream::nProcs());
02265 faceSendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
02266 forAll(faceSendMap, procI)
02267 {
02268 faceSendSizes[Pstream::myProcNo()][procI] = faceSendMap[procI].size();
02269 }
02270 Pstream::gatherList(faceSendSizes);
02271 Pstream::scatterList(faceSendSizes);
02272
02273
02274
02275
02276
02277
02278
02279 List<labelledTri> allTris;
02280 pointField allPoints;
02281
02282 labelListList faceConstructMap(Pstream::nProcs());
02283 labelListList pointConstructMap(Pstream::nProcs());
02284
02285
02286
02287
02288
02289 {
02290 labelList pointMap;
02291 triSurface subSurface
02292 (
02293 subsetMesh
02294 (
02295 *this,
02296 faceSendMap[Pstream::myProcNo()],
02297 pointMap
02298 )
02299 );
02300
02301 allTris = subSurface;
02302 allPoints = subSurface.points();
02303
02304 faceConstructMap[Pstream::myProcNo()] = identity
02305 (
02306 faceSendMap[Pstream::myProcNo()].size()
02307 );
02308 pointConstructMap[Pstream::myProcNo()] = identity
02309 (
02310 pointSendMap[Pstream::myProcNo()].size()
02311 );
02312 }
02313
02314
02315
02316
02317
02318
02319 forAll(faceSendSizes, procI)
02320 {
02321 if (procI != Pstream::myProcNo())
02322 {
02323 if (faceSendSizes[Pstream::myProcNo()][procI] > 0)
02324 {
02325 OPstream str(Pstream::blocking, procI);
02326
02327 labelList pointMap;
02328 triSurface subSurface
02329 (
02330 subsetMesh
02331 (
02332 *this,
02333 faceSendMap[procI],
02334 pointMap
02335 )
02336 );
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346 str << subSurface;
02347 }
02348 }
02349 }
02350
02351
02352
02353
02354
02355 forAll(faceSendSizes, procI)
02356 {
02357 if (procI != Pstream::myProcNo())
02358 {
02359 if (faceSendSizes[procI][Pstream::myProcNo()] > 0)
02360 {
02361 IPstream str(Pstream::blocking, procI);
02362
02363
02364 triSurface subSurface(str);
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 merge
02376 (
02377 mergeDist_,
02378 subSurface,
02379 subSurface.points(),
02380
02381 allTris,
02382 allPoints,
02383 faceConstructMap[procI],
02384 pointConstructMap[procI]
02385 );
02386
02387
02388
02389
02390
02391
02392 }
02393 }
02394 }
02395
02396
02397 faceMap.reset
02398 (
02399 new mapDistribute
02400 (
02401 allTris.size(),
02402 faceSendMap,
02403 faceConstructMap,
02404 true
02405 )
02406 );
02407 pointMap.reset
02408 (
02409 new mapDistribute
02410 (
02411 allPoints.size(),
02412 pointSendMap,
02413 pointConstructMap,
02414 true
02415 )
02416 );
02417
02418
02419 triSurface::operator=(triSurface(allTris, patches(), allPoints, true));
02420
02421 clearOut();
02422
02423
02424
02425
02426 distributeFields<label>(faceMap());
02427 distributeFields<scalar>(faceMap());
02428 distributeFields<vector>(faceMap());
02429 distributeFields<sphericalTensor>(faceMap());
02430 distributeFields<symmTensor>(faceMap());
02431 distributeFields<tensor>(faceMap());
02432
02433 if (debug)
02434 {
02435 labelList nTris(Pstream::nProcs());
02436 nTris[Pstream::myProcNo()] = triSurface::size();
02437 Pstream::gatherList(nTris);
02438 Pstream::scatterList(nTris);
02439
02440 Info<< "distributedTriSurfaceMesh::distribute : after distribution:"
02441 << endl
02442 << "\tproc\ttris" << endl;
02443
02444 forAll(nTris, procI)
02445 {
02446 Info<< '\t' << procI << '\t' << nTris[procI] << endl;
02447 }
02448 Info<< endl;
02449 }
02450 }
02451
02452
02453
02454 bool Foam::distributedTriSurfaceMesh::writeObject
02455 (
02456 IOstream::streamFormat fmt,
02457 IOstream::versionNumber ver,
02458 IOstream::compressionType cmp
02459 ) const
02460 {
02461
02462 const_cast<fileName&>(dict_.instance()) = searchableSurface::instance();
02463
02464
02465 return
02466 triSurfaceMesh::writeObject(fmt, ver, cmp)
02467 && dict_.writeObject(IOstream::ASCII, ver, cmp);
02468 }
02469
02470
02471 void Foam::distributedTriSurfaceMesh::writeStats(Ostream& os) const
02472 {
02473 boundBox bb;
02474 label nPoints;
02475 calcBounds(bb, nPoints);
02476 reduce(bb.min(), minOp<point>());
02477 reduce(bb.max(), maxOp<point>());
02478
02479 os << "Triangles : " << returnReduce(triSurface::size(), sumOp<label>())
02480 << endl
02481 << "Vertices : " << returnReduce(nPoints, sumOp<label>()) << endl
02482 << "Bounding Box : " << bb << endl;
02483 }
02484
02485
02486