1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
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
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/>.
26 \*---------------------------------------------------------------------------*/
28 #include "meshSurfaceEngine.H"
29 #include "demandDrivenData.H"
32 #include "helperFunctionsPar.H"
37 // #define DEBUGSearch
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
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;
57 bpProcsPtr_ = new VRWGraph(bPoints.size());
59 if( !globalBoundaryPointToLocalPtr_ )
60 globalBoundaryPointToLocalPtr_ = new Map<label>();
63 bpNeiProcsPtr_ = new DynList<label>();
65 if( !Pstream::parRun() )
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)
79 const label start = procBoundaries[patchI].patchStart();
80 const label end = start + procBoundaries[patchI].patchSize();
81 for(label faceI=start;faceI<end;++faceI)
83 const face& f = faces[faceI];
87 bpAtProcs.appendIfNotIn
90 procBoundaries[patchI].myProcNo()
92 bpAtProcs.appendIfNotIn
95 procBoundaries[patchI].neiProcNo()
101 //- exchange data with other processor and update bpAtProcs
102 //- continue this process as long as there is some change
108 forAll(procBoundaries, patchI)
110 const label start = procBoundaries[patchI].patchStart();
111 const label end = start + procBoundaries[patchI].patchSize();
114 labelHashSet addedPoint;
115 for(label faceI=start;faceI<end;++faceI)
117 const face& f = faces[faceI];
119 if( (bp[f[pI]] != -1) && !addedPoint.found(f[pI]) )
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
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));
139 procBoundaries[patchI].neiProcNo(),
145 forAll(procBoundaries, patchI)
147 IPstream fromOtherProc
150 procBoundaries[patchI].neiProcNo()
152 labelList receivedData;
153 fromOtherProc >> receivedData;
155 const label start = procBoundaries[patchI].patchStart();
158 while( counter < receivedData.size() )
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)
165 const label neiProc = receivedData[counter++];
166 if( !bpAtProcs.contains(bp[f[pI]], neiProc) )
168 bpAtProcs.append(bp[f[pI]], neiProc);
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 )
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() )
195 localPoints[bpI] = false;
203 //- give local points their labels
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
221 forAll(procBoundaries, patchI)
223 const label start = procBoundaries[patchI].patchStart();
224 const label end = start + procBoundaries[patchI].patchSize();
227 labelHashSet addedPoint;
228 for(label faceI=start;faceI<end;++faceI)
230 const face& f = faces[faceI];
233 const label bpI = bp[f[pI]];
234 if( (bpI != -1) && (globalPointLabel[bpI] != -1) )
236 if( addedPoint.found(bpI) )
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]);
254 procBoundaries[patchI].neiProcNo(),
260 forAll(procBoundaries, patchI)
262 IPstream fromOtherProc
265 procBoundaries[patchI].neiProcNo()
267 labelList receivedData;
268 fromOtherProc >> receivedData;
270 const label start = procBoundaries[patchI].patchStart();
273 while( counter < receivedData.size() )
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 )
281 globalPointLabel[bp[f[pI]]] = globalLabel;
284 else if( globalPointLabel[bp[f[pI]]] != globalLabel )
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);
300 reduce(finished, minOp<bool>());
301 } while( !finished );
303 //- create globalToLocal addressing
304 forAll(bpAtProcs, bpI)
306 if( bpAtProcs.sizeOfRow(bpI) != 0 )
308 globalBoundaryPointToLocalPtr_->insert(globalPointLabel[bpI], bpI);
310 forAllRow(bpAtProcs, bpI, j)
312 const label procI = bpAtProcs(bpI, j);
314 if( procI == Pstream::myProcNo() )
317 bpNeiProcsPtr_->appendIfNotIn(procI);
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;
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() )
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)
360 const label start = procBoundaries[patchI].patchStart();
361 const label end = start + procBoundaries[patchI].patchSize();
362 for(label faceI=start;faceI<end;++faceI)
364 const face& f = faces[faceI];
368 if( bp[f[eI]] != -1 )
370 const edge e = f.faceEdge(eI);
372 const label bpI = bp[e.start()];
374 forAllRow(pEdges, bpI, peI)
375 if( bEdges[pEdges(bpI, peI)] == e )
377 edgeI = pEdges(bpI, peI);
383 facesWithProcBndEdges[patchI].insert
385 std::make_pair(faceI, eI)
388 beAtProcs.appendIfNotIn
391 procBoundaries[patchI].myProcNo()
393 beAtProcs.appendIfNotIn
396 procBoundaries[patchI].neiProcNo()
404 //- exchange data with other processor and update beAtProcs
405 //- continue this process as long as there is some change
411 forAll(facesWithProcBndEdges, patchI)
413 const label start = procBoundaries[patchI].patchStart();
414 const procEdgeMap& procBndEdges = facesWithProcBndEdges[patchI];
417 forAllConstIter(procEdgeMap, procBndEdges, it)
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 )
426 const label bpI = bp[e.start()];
428 forAllRow(pEdges, bpI, peI)
429 if( bEdges[pEdges(bpI, peI)] == e )
431 edgeI = pEdges(bpI, peI);
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
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));
454 procBoundaries[patchI].neiProcNo(),
460 forAll(procBoundaries, patchI)
462 IPstream fromOtherProc
465 procBoundaries[patchI].neiProcNo()
467 labelList receivedData;
468 fromOtherProc >> receivedData;
470 const label start = procBoundaries[patchI].patchStart();
473 while( counter < receivedData.size() )
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);
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)
488 const label neiProc = receivedData[counter++];
489 if( !beAtProcs.contains(edgeI, neiProc) )
491 facesWithProcBndEdges[patchI].insert
493 std::make_pair(faceI, eI)
496 beAtProcs.append(edgeI, neiProc);
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 )
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() )
523 localEdges[bpI] = false;
531 //- give local points their labels
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)
542 globalEdgeLabel[pI] = startEdge++;
544 //- send labels to non-local edges
549 forAll(facesWithProcBndEdges, patchI)
551 const label start = procBoundaries[patchI].patchStart();
552 const procEdgeMap& procBndEdges = facesWithProcBndEdges[patchI];
555 forAllConstIter(procEdgeMap, procBndEdges, it)
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 )
565 const label bpI = bp[e.start()];
567 forAllRow(pEdges, bpI, peI)
568 if( bEdges[pEdges(bpI, peI)] == e )
570 edgeI = pEdges(bpI, peI);
574 if( (edgeI != -1) && (globalEdgeLabel[edgeI] != -1) )
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]);
590 procBoundaries[patchI].neiProcNo(),
596 forAll(procBoundaries, patchI)
598 IPstream fromOtherProc
601 procBoundaries[patchI].neiProcNo()
603 labelList receivedData;
604 fromOtherProc >> receivedData;
606 const label start = procBoundaries[patchI].patchStart();
609 while( counter < receivedData.size() )
611 const face& f = faces[start+receivedData[counter++]];
612 const label eI = receivedData[counter++];
614 const edge e = f.faceEdge(eI);
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 )
624 globalEdgeLabel[edgeI] = globalLabel;
627 else if( globalEdgeLabel[edgeI] != globalLabel )
631 "void meshSurfaceEngine::"
632 "calcGlobalBoundaryEdgeLabels() const"
633 ) << "Edge labels do not match!" << abort(FatalError);
638 reduce(finished, minOp<bool>());
639 } while( !finished );
641 //- create globalToLocal addressing
642 forAll(beAtProcs, beI)
644 if( beAtProcs.sizeOfRow(beI) != 0 )
646 globalBoundaryEdgeToLocalPtr_->insert(globalEdgeLabel[beI], beI);
648 forAllRow(beAtProcs, beI, j)
650 const label procI = beAtProcs(beI, j);
652 if( procI == Pstream::myProcNo() )
655 beNeiProcsPtr_->appendIfNotIn(procI);
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)
678 const label beI = iter();
679 nFacesAtEdge.insert(beI, eFaces.sizeOfRow(beI));
681 forAllRow(beAtProcs, beI, i)
683 const label neiProc = beAtProcs(beI, i);
685 if( neiProc == Pstream::myProcNo() )
688 labelLongList& dts = exchangeData[neiProc];
689 dts.append(iter.key());
690 dts.append(eFaces.sizeOfRow(beI));
694 labelLongList receivedData;
695 help::exchangeMap(exchangeData, receivedData);
696 for(label counter=0;counter<receivedData.size();)
698 const label beI = globalToLocal[receivedData[counter++]];
699 nFacesAtEdge[beI] += receivedData[counter++];
702 forAllConstIter(Map<label>, nFacesAtEdge, iter)
707 "void meshSurfaceEngine::calcAddressingForProcEdges() const"
708 ) << "Surface is not manifold at boundary edge "
709 << iter.key() << exit(FatalError);
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)
720 const label beI = iter();
722 forAllRow(beAtProcs, beI, procI)
724 const label neiProc = beAtProcs(beI, procI);
726 if( neiProc == Pstream::myProcNo() )
729 if( eFaces.sizeOfRow(beI) == 1 )
731 exchangeData[neiProc].append(globalEdgeLabel[beI]);
732 exchangeData[neiProc].append
734 boundaryFacePatches[eFaces(beI, 0)]
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_;
751 std::map<label, labelList>::const_iterator iter=receivedMap.begin();
752 iter!=receivedMap.end();
756 const labelList& receivedData = iter->second;
759 while( counter < receivedData.size() )
761 const label beI = globalToLocal[receivedData[counter++]];
762 const label patch = receivedData[counter++];
763 if( eFaces.sizeOfRow(beI) == 1 )
765 otherProcPatches.insert(beI, patch);
766 otherFaceProc.insert(beI, iter->first);
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);
787 for(label i=0;i<Pstream::myProcNo();++i)
788 startFace += nFacesAtProc[i];
791 globalFaceLabel[fI] = startFace++;
794 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
796 } // End namespace Foam
798 // ************************************************************************* //