Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / mesh / cfMesh / utilities / surfaceTools / meshSurfaceEngine / meshSurfaceEngineParallelAddressing.C
blobb0c778fe70119b300f10b5e37151765469d1b23d
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | cfMesh: A library for mesh generation
4    \\    /   O peration     |
5     \\  /    A nd           | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6      \\/     M anipulation  | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9     This file is part of cfMesh.
11     cfMesh is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 3 of the License, or (at your
14     option) any later version.
16     cfMesh 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.
21     You should have received a copy of the GNU General Public License
22     along with cfMesh.  If not, see <http://www.gnu.org/licenses/>.
24 Description
26 \*---------------------------------------------------------------------------*/
28 #include "meshSurfaceEngine.H"
29 #include "demandDrivenData.H"
30 #include "Map.H"
31 #include "HashSet.H"
32 #include "helperFunctionsPar.H"
34 #include <map>
35 #include <set>
37 // #define DEBUGSearch
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 namespace Foam
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 void meshSurfaceEngine::calcGlobalBoundaryPointLabels() const
48     if( !globalBoundaryPointLabelPtr_ )
49         globalBoundaryPointLabelPtr_ = new labelList();
51     const labelList& bPoints = this->boundaryPoints();
52     labelList& globalPointLabel = *globalBoundaryPointLabelPtr_;
53     globalPointLabel.setSize(bPoints.size());
54     globalPointLabel = -1;
56     if( !bpProcsPtr_ )
57         bpProcsPtr_ = new VRWGraph(bPoints.size());
59     if( !globalBoundaryPointToLocalPtr_ )
60         globalBoundaryPointToLocalPtr_ = new Map<label>();
62     if( !bpNeiProcsPtr_ )
63         bpNeiProcsPtr_ = new DynList<label>();
65     if( !Pstream::parRun() )
66         return;
68     VRWGraph& bpAtProcs = *bpProcsPtr_;
70     //- find local points for the given processor
71     const faceListPMG& faces = mesh_.faces();
72     const labelList& bp = this->bp();
73     const PtrList<processorBoundaryPatch>& procBoundaries =
74         mesh_.procBoundaries();
76     //- find which processor contain a given bnd point
77     forAll(procBoundaries, patchI)
78     {
79         const label start = procBoundaries[patchI].patchStart();
80         const label end = start + procBoundaries[patchI].patchSize();
81         for(label faceI=start;faceI<end;++faceI)
82         {
83             const face& f = faces[faceI];
84             forAll(f, pI)
85                 if( bp[f[pI]] != -1 )
86                 {
87                     bpAtProcs.appendIfNotIn
88                     (
89                         bp[f[pI]],
90                         procBoundaries[patchI].myProcNo()
91                     );
92                     bpAtProcs.appendIfNotIn
93                     (
94                         bp[f[pI]],
95                         procBoundaries[patchI].neiProcNo()
96                     );
97                 }
98         }
99     }
101     //- exchange data with other processor and update bpAtProcs
102     //- continue this process as long as there is some change
103     bool finished;
104     do
105     {
106         finished = true;
108         forAll(procBoundaries, patchI)
109         {
110             const label start = procBoundaries[patchI].patchStart();
111             const label end = start + procBoundaries[patchI].patchSize();
113             labelLongList dts;
114             labelHashSet addedPoint;
115             for(label faceI=start;faceI<end;++faceI)
116             {
117                 const face& f = faces[faceI];
118                 forAll(f, pI)
119                     if( (bp[f[pI]] != -1) && !addedPoint.found(f[pI]) )
120                     {
121                         addedPoint.insert(f[pI]);
122                         const label bpI = bp[f[pI]];
123                         //- data is sent as follows
124                         //- 1. face position in patch
125                         //- 2. local point position in face
126                         //- 3. number of processors for point
127                         //- 4. proc labels
128                         dts.append(faceI-start);
129                         dts.append((f.size()-pI)%f.size());
130                         dts.append(bpAtProcs.sizeOfRow(bpI));
131                         forAllRow(bpAtProcs, bpI, i)
132                             dts.append(bpAtProcs(bpI, i));
133                     }
134             }
136             OPstream toOtherProc
137             (
138                 Pstream::blocking,
139                 procBoundaries[patchI].neiProcNo(),
140                 dts.byteSize()
141             );
142             toOtherProc << dts;
143         }
145         forAll(procBoundaries, patchI)
146         {
147             IPstream fromOtherProc
148             (
149                 Pstream::blocking,
150                 procBoundaries[patchI].neiProcNo()
151             );
152             labelList receivedData;
153             fromOtherProc >> receivedData;
155             const label start = procBoundaries[patchI].patchStart();
157             label counter(0);
158             while( counter < receivedData.size() )
159             {
160                 const face& f = faces[start+receivedData[counter++]];
161                 const label pI = receivedData[counter++];
162                 const label nProcs = receivedData[counter++];
163                 for(label i=0;i<nProcs;++i)
164                 {
165                     const label neiProc = receivedData[counter++];
166                     if( !bpAtProcs.contains(bp[f[pI]], neiProc) )
167                     {
168                         bpAtProcs.append(bp[f[pI]], neiProc);
169                         finished = false;
170                     }
171                 }
172             }
173         }
175         reduce(finished, minOp<bool>());
176     } while( !finished );
178     //- start calculating global point labels
179     label nLocalPoints(0);
180     boolList localPoints(bPoints.size(), true);
181     forAll(bpAtProcs, bpI)
182         if( bpAtProcs.sizeOfRow(bpI) != 0 )
183         {
184             label pMin = bpAtProcs(bpI, 0);
185             forAllRow(bpAtProcs, bpI, procI)
186                 if( bpAtProcs(bpI, procI) < pMin )
187                     pMin = bpAtProcs(bpI, procI);
189             if( pMin == Pstream::myProcNo() )
190             {
191                 ++nLocalPoints;
192             }
193             else
194             {
195                 localPoints[bpI] = false;
196             }
197         }
198         else
199         {
200             ++nLocalPoints;
201         }
203     //- give local points their labels
204     label startPoint(0);
205     labelList nPointsAtProc(Pstream::nProcs());
206     nPointsAtProc[Pstream::myProcNo()] = nLocalPoints;
207     Pstream::gatherList(nPointsAtProc);
208     Pstream::scatterList(nPointsAtProc);
209     for(label i=0;i<Pstream::myProcNo();++i)
210         startPoint += nPointsAtProc[i];
212     forAll(localPoints, pI)
213         if( localPoints[pI] )
214             globalPointLabel[pI] = startPoint++;
216     //- send labels to non-local points
217     do
218     {
219         finished = true;
221         forAll(procBoundaries, patchI)
222         {
223             const label start = procBoundaries[patchI].patchStart();
224             const label end = start + procBoundaries[patchI].patchSize();
226             labelLongList dts;
227             labelHashSet addedPoint;
228             for(label faceI=start;faceI<end;++faceI)
229             {
230                 const face& f = faces[faceI];
231                 forAll(f, pI)
232                 {
233                     const label bpI = bp[f[pI]];
234                     if( (bpI != -1) && (globalPointLabel[bpI] != -1) )
235                     {
236                         if( addedPoint.found(bpI) )
237                             continue;
239                         addedPoint.insert(bpI);
240                         //- data is sent as follows
241                         //- 1. face position in patch
242                         //- 2. local point position in face
243                         //- 3. global point label
244                         dts.append(faceI-start);
245                         dts.append((f.size()-pI)%f.size());
246                         dts.append(globalPointLabel[bpI]);
247                     }
248                 }
249             }
251             OPstream toOtherProc
252             (
253                 Pstream::blocking,
254                 procBoundaries[patchI].neiProcNo(),
255                 dts.byteSize()
256             );
257             toOtherProc << dts;
258         }
260         forAll(procBoundaries, patchI)
261         {
262             IPstream fromOtherProc
263             (
264                 Pstream::blocking,
265                 procBoundaries[patchI].neiProcNo()
266             );
267             labelList receivedData;
268             fromOtherProc >> receivedData;
270             const label start = procBoundaries[patchI].patchStart();
272             label counter(0);
273             while( counter < receivedData.size() )
274             {
275                 const face& f = faces[start+receivedData[counter++]];
276                 const label pI = receivedData[counter++];
277                 const label globalLabel = receivedData[counter++];
279                 if( globalPointLabel[bp[f[pI]]] == -1 )
280                 {
281                     globalPointLabel[bp[f[pI]]] = globalLabel;
282                     finished = false;
283                 }
284                 else if( globalPointLabel[bp[f[pI]]] != globalLabel )
285                 {
286                     FatalErrorIn
287                     (
288                         "void meshSurfaceEngine::"
289                         "calcGlobalBoundaryPointLabels() const"
290                     ) << "Point labels in proc boundary "
291                         << procBoundaries[patchI].patchName()
292                         << " face " << f << " pI = " << pI
293                         << nl << " label " << globalPointLabel[bp[f[pI]]]
294                         << nl << " other global label " << globalLabel
295                         << " do not match!" << abort(FatalError);
296                 }
297             }
298         }
300         reduce(finished, minOp<bool>());
301     } while( !finished );
303     //- create globalToLocal addressing
304     forAll(bpAtProcs, bpI)
305     {
306         if( bpAtProcs.sizeOfRow(bpI) != 0 )
307         {
308             globalBoundaryPointToLocalPtr_->insert(globalPointLabel[bpI], bpI);
310             forAllRow(bpAtProcs, bpI, j)
311             {
312                 const label procI = bpAtProcs(bpI, j);
314                 if( procI == Pstream::myProcNo() )
315                     continue;
317                 bpNeiProcsPtr_->appendIfNotIn(procI);
318             }
319         }
320     }
323 void meshSurfaceEngine::calcGlobalBoundaryEdgeLabels() const
325     if( !globalBoundaryEdgeLabelPtr_ )
326         globalBoundaryEdgeLabelPtr_ = new labelList();
328     const edgeList& bEdges = this->edges();
330     labelList& globalEdgeLabel = *globalBoundaryEdgeLabelPtr_;
331     globalEdgeLabel.setSize(bEdges.size());
332     globalEdgeLabel = -1;
334     if( !beProcsPtr_ )
335         beProcsPtr_ = new VRWGraph(bEdges.size());
337     if( !globalBoundaryEdgeToLocalPtr_ )
338         globalBoundaryEdgeToLocalPtr_ = new Map<label>();
340     if( !beNeiProcsPtr_ )
341         beNeiProcsPtr_ = new DynList<label>();
343     if( !Pstream::parRun() )
344         return;
346     VRWGraph& beAtProcs = *beProcsPtr_;
348     const faceListPMG& faces = mesh_.faces();
349     const labelList& bp = this->bp();
350     const VRWGraph& pEdges = this->boundaryPointEdges();
351     const PtrList<processorBoundaryPatch>& procBoundaries =
352         mesh_.procBoundaries();
354     //- find which processors contain a given bnd edge
355     typedef std::set<std::pair<label, label> > procEdgeMap;
356     List<procEdgeMap> facesWithProcBndEdges(procBoundaries.size());
358     forAll(procBoundaries, patchI)
359     {
360         const label start = procBoundaries[patchI].patchStart();
361         const label end = start + procBoundaries[patchI].patchSize();
362         for(label faceI=start;faceI<end;++faceI)
363         {
364             const face& f = faces[faceI];
366             forAll(f, eI)
367             {
368                 if( bp[f[eI]] != -1 )
369                 {
370                     const edge e = f.faceEdge(eI);
372                     const label bpI = bp[e.start()];
373                     label edgeI(-1);
374                     forAllRow(pEdges, bpI, peI)
375                         if( bEdges[pEdges(bpI, peI)] == e )
376                         {
377                             edgeI = pEdges(bpI, peI);
378                             break;
379                         }
381                     if( edgeI != -1 )
382                     {
383                         facesWithProcBndEdges[patchI].insert
384                         (
385                             std::make_pair(faceI, eI)
386                         );
388                         beAtProcs.appendIfNotIn
389                         (
390                             edgeI,
391                             procBoundaries[patchI].myProcNo()
392                         );
393                         beAtProcs.appendIfNotIn
394                         (
395                             edgeI,
396                             procBoundaries[patchI].neiProcNo()
397                         );
398                     }
399                 }
400             }
401         }
402     }
404     //- exchange data with other processor and update beAtProcs
405     //- continue this process as long as there is some change
406     bool finished;
407     do
408     {
409         finished = true;
411         forAll(facesWithProcBndEdges, patchI)
412         {
413             const label start = procBoundaries[patchI].patchStart();
414             const procEdgeMap& procBndEdges = facesWithProcBndEdges[patchI];
416             labelLongList dts;
417             forAllConstIter(procEdgeMap, procBndEdges, it)
418             {
419                 const std::pair<label, label>& fPair = *it;
421                 const face& f = faces[fPair.first];
422                 const edge e = f.faceEdge(fPair.second);
424                 if( bp[e.start()] != -1 )
425                 {
426                     const label bpI = bp[e.start()];
427                     label edgeI(-1);
428                     forAllRow(pEdges, bpI, peI)
429                         if( bEdges[pEdges(bpI, peI)] == e )
430                         {
431                             edgeI = pEdges(bpI, peI);
432                             break;
433                         }
435                     if( edgeI != -1 )
436                     {
437                         //- data is sent as follows
438                         //- 1. face position in patch
439                         //- 2. local edge position in face
440                         //- 3. number of processors for edge
441                         //- 4. proc labels
442                         dts.append(fPair.first-start);
443                         dts.append((f.size()-fPair.second-1)%f.size());
444                         dts.append(beAtProcs.sizeOfRow(edgeI));
445                         forAllRow(beAtProcs, edgeI, i)
446                             dts.append(beAtProcs(edgeI, i));
447                     }
448                 }
449             }
451             OPstream toOtherProc
452             (
453                 Pstream::blocking,
454                 procBoundaries[patchI].neiProcNo(),
455                 dts.byteSize()
456             );
457             toOtherProc << dts;
458         }
460         forAll(procBoundaries, patchI)
461         {
462             IPstream fromOtherProc
463             (
464                 Pstream::blocking,
465                 procBoundaries[patchI].neiProcNo()
466             );
467             labelList receivedData;
468             fromOtherProc >> receivedData;
470             const label start = procBoundaries[patchI].patchStart();
472             label counter(0);
473             while( counter < receivedData.size() )
474             {
475                 const label faceI = start+receivedData[counter++];
476                 const face& f = faces[faceI];
477                 const label eI = receivedData[counter++];
479                 const edge e = f.faceEdge(eI);
480                 label edgeI(-1);
481                 forAllRow(pEdges, bp[e.start()], peI)
482                     if( bEdges[pEdges(bp[e.start()], peI)] == e )
483                         edgeI = pEdges(bp[e.start()], peI);
485                 const label nProcs = receivedData[counter++];
486                 for(label i=0;i<nProcs;++i)
487                 {
488                     const label neiProc = receivedData[counter++];
489                     if( !beAtProcs.contains(edgeI, neiProc) )
490                     {
491                         facesWithProcBndEdges[patchI].insert
492                         (
493                             std::make_pair(faceI, eI)
494                         );
496                         beAtProcs.append(edgeI, neiProc);
497                         finished = false;
498                     }
499                 }
500             }
501         }
503         reduce(finished, minOp<bool>());
504     } while( !finished );
506     //- start calculating global edge labels
507     label nLocalEdges(0);
508     boolList localEdges(bEdges.size(), true);
509     forAll(beAtProcs, bpI)
510         if( beAtProcs.sizeOfRow(bpI) != 0 )
511         {
512             label pMin = beAtProcs(bpI, 0);
513             forAllRow(beAtProcs, bpI, procI)
514                 if( beAtProcs(bpI, procI) < pMin )
515                     pMin = beAtProcs(bpI, procI);
517             if( pMin == Pstream::myProcNo() )
518             {
519                 ++nLocalEdges;
520             }
521             else
522             {
523                 localEdges[bpI] = false;
524             }
525         }
526         else
527         {
528             ++nLocalEdges;
529         }
531     //- give local points their labels
532     label startEdge(0);
533     labelList nEdgesAtProc(Pstream::nProcs());
534     nEdgesAtProc[Pstream::myProcNo()] = nLocalEdges;
535     Pstream::gatherList(nEdgesAtProc);
536     Pstream::scatterList(nEdgesAtProc);
537     for(label i=0;i<Pstream::myProcNo();++i)
538         startEdge += nEdgesAtProc[i];
540     forAll(localEdges, pI)
541         if( localEdges[pI] )
542             globalEdgeLabel[pI] = startEdge++;
544     //- send labels to non-local edges
545     do
546     {
547         finished = true;
549         forAll(facesWithProcBndEdges, patchI)
550         {
551             const label start = procBoundaries[patchI].patchStart();
552             const procEdgeMap& procBndEdges = facesWithProcBndEdges[patchI];
554             labelLongList dts;
555             forAllConstIter(procEdgeMap, procBndEdges, it)
556             {
557                 const label faceI = it->first;
558                 const face& f = faces[faceI];
560                 const label eI = it->second;
561                 const edge e = f.faceEdge(eI);
563                 if( bp[e.start()] != -1 )
564                 {
565                     const label bpI = bp[e.start()];
566                     label edgeI(-1);
567                     forAllRow(pEdges, bpI, peI)
568                         if( bEdges[pEdges(bpI, peI)] == e )
569                         {
570                             edgeI = pEdges(bpI, peI);
571                             break;
572                         }
574                     if( (edgeI != -1) && (globalEdgeLabel[edgeI] != -1) )
575                     {
576                         //- data is sent as follows
577                         //- 1. face position in patch
578                         //- 2. local edge position in face
579                         //- 3. global edge label
580                         dts.append(faceI-start);
581                         dts.append((f.size()-eI-1)%f.size());
582                         dts.append(globalEdgeLabel[edgeI]);
583                     }
584                 }
585             }
587             OPstream toOtherProc
588             (
589                 Pstream::blocking,
590                 procBoundaries[patchI].neiProcNo(),
591                 dts.byteSize()
592             );
593             toOtherProc << dts;
594         }
596         forAll(procBoundaries, patchI)
597         {
598             IPstream fromOtherProc
599             (
600                 Pstream::blocking,
601                 procBoundaries[patchI].neiProcNo()
602             );
603             labelList receivedData;
604             fromOtherProc >> receivedData;
606             const label start = procBoundaries[patchI].patchStart();
608             label counter(0);
609             while( counter < receivedData.size() )
610             {
611                 const face& f = faces[start+receivedData[counter++]];
612                 const label eI = receivedData[counter++];
614                 const edge e = f.faceEdge(eI);
615                 label edgeI(-1);
616                 forAllRow(pEdges, bp[e.start()], peI)
617                     if( bEdges[pEdges(bp[e.start()], peI)] == e )
618                         edgeI = pEdges(bp[e.start()], peI);
620                 const label globalLabel = receivedData[counter++];
622                 if( globalEdgeLabel[edgeI] == -1 )
623                 {
624                     globalEdgeLabel[edgeI] = globalLabel;
625                     finished = false;
626                 }
627                 else if( globalEdgeLabel[edgeI] != globalLabel )
628                 {
629                     FatalErrorIn
630                     (
631                         "void meshSurfaceEngine::"
632                         "calcGlobalBoundaryEdgeLabels() const"
633                     ) << "Edge labels do not match!" << abort(FatalError);
634                 }
635             }
636         }
638         reduce(finished, minOp<bool>());
639     } while( !finished );
641     //- create globalToLocal addressing
642     forAll(beAtProcs, beI)
643     {
644         if( beAtProcs.sizeOfRow(beI) != 0 )
645         {
646             globalBoundaryEdgeToLocalPtr_->insert(globalEdgeLabel[beI], beI);
648             forAllRow(beAtProcs, beI, j)
649             {
650                 const label procI = beAtProcs(beI, j);
652                 if( procI == Pstream::myProcNo() )
653                     continue;
655                 beNeiProcsPtr_->appendIfNotIn(procI);
656             }
657         }
658     }
661 void meshSurfaceEngine::calcAddressingForProcEdges() const
663     const labelList& globalEdgeLabel = this->globalBoundaryEdgeLabel();
664     const labelList& boundaryFacePatches = this->boundaryFacePatches();
665     const VRWGraph& eFaces = this->edgeFaces();
666     const VRWGraph& beAtProcs = this->beAtProcs();
667     const Map<label>& globalToLocal = this->globalToLocalBndEdgeAddressing();
668     const DynList<label>& beNeiProcs = this->beNeiProcs();
670     std::map<label, labelLongList> exchangeData;
671     forAll(beNeiProcs, i)
672         exchangeData.insert(std::make_pair(beNeiProcs[i], labelLongList()));
674     //- check if it the surface is manifold over inter-processor edges
675     Map<label> nFacesAtEdge;
676     forAllConstIter(Map<label>, globalToLocal, iter)
677     {
678         const label beI = iter();
679         nFacesAtEdge.insert(beI, eFaces.sizeOfRow(beI));
681         forAllRow(beAtProcs, beI, i)
682         {
683             const label neiProc = beAtProcs(beI, i);
685             if( neiProc == Pstream::myProcNo() )
686                 continue;
688             labelLongList& dts = exchangeData[neiProc];
689             dts.append(iter.key());
690             dts.append(eFaces.sizeOfRow(beI));
691         }
692     }
694     labelLongList receivedData;
695     help::exchangeMap(exchangeData, receivedData);
696     for(label counter=0;counter<receivedData.size();)
697     {
698         const label beI = globalToLocal[receivedData[counter++]];
699         nFacesAtEdge[beI] += receivedData[counter++];
700     }
702     forAllConstIter(Map<label>, nFacesAtEdge, iter)
703     {
704         if( iter() != 2 )
705             FatalErrorIn
706             (
707                 "void meshSurfaceEngine::calcAddressingForProcEdges() const"
708             ) << "Surface is not manifold at boundary edge "
709               << iter.key() << exit(FatalError);
710     }
712     //- find the processor which contains other face containing an edge
713     //- at inter-processor boundary
714     exchangeData.clear();
715     forAll(beNeiProcs, i)
716         exchangeData.insert(std::make_pair(beNeiProcs[i], labelLongList()));
718     forAllConstIter(Map<label>, globalToLocal, iter)
719     {
720         const label beI = iter();
722         forAllRow(beAtProcs, beI, procI)
723         {
724             const label neiProc = beAtProcs(beI, procI);
726             if( neiProc == Pstream::myProcNo() )
727                 continue;
729             if( eFaces.sizeOfRow(beI) == 1 )
730             {
731                 exchangeData[neiProc].append(globalEdgeLabel[beI]);
732                 exchangeData[neiProc].append
733                 (
734                     boundaryFacePatches[eFaces(beI, 0)]
735                 );
736             }
737         }
738     }
740     //- exchange edge-face patches with other processors
741     std::map<label, labelList> receivedMap;
742     help::exchangeMap(exchangeData, receivedMap);
744     //- store other face patches in a map
745     otherEdgeFaceAtProcPtr_ = new Map<label>();
746     otherEdgeFacePatchPtr_ = new Map<label>();
747     Map<label>& otherProcPatches = *otherEdgeFacePatchPtr_;
748     Map<label>& otherFaceProc = *otherEdgeFaceAtProcPtr_;
749     for
750     (
751         std::map<label, labelList>::const_iterator iter=receivedMap.begin();
752         iter!=receivedMap.end();
753         ++iter
754     )
755     {
756         const labelList& receivedData = iter->second;
758         label counter(0);
759         while( counter < receivedData.size() )
760         {
761             const label beI = globalToLocal[receivedData[counter++]];
762             const label patch = receivedData[counter++];
763             if( eFaces.sizeOfRow(beI) == 1 )
764             {
765                 otherProcPatches.insert(beI, patch);
766                 otherFaceProc.insert(beI, iter->first);
767             }
768         }
769     }
772 void meshSurfaceEngine::calcGlobalBoundaryFaceLabels() const
774     const faceList::subList& bFaces = boundaryFaces();
776     if( !globalBoundaryFaceLabelPtr_ )
777         globalBoundaryFaceLabelPtr_ = new labelList(bFaces.size());
779     labelList& globalFaceLabel = *globalBoundaryFaceLabelPtr_;
781     labelList nFacesAtProc(Pstream::nProcs());
782     nFacesAtProc[Pstream::myProcNo()] = bFaces.size();
783     Pstream::gatherList(nFacesAtProc);
784     Pstream::scatterList(nFacesAtProc);
786     label startFace(0);
787     for(label i=0;i<Pstream::myProcNo();++i)
788         startFace += nFacesAtProc[i];
790     forAll(bFaces, fI)
791         globalFaceLabel[fI] = startFace++;
794 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
796 } // End namespace Foam
798 // ************************************************************************* //