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"
31 #include "helperFunctions.H"
32 #include "helperFunctionsPar.H"
33 #include "VRWGraphSMPModifier.H"
34 #include "labelledPoint.H"
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 void meshSurfaceEngine::calculateBoundaryFaces() const
53 if( mesh_.boundaries().size() != 0 )
55 const faceListPMG& faces = mesh_.faces();
56 const PtrList<boundaryPatch>& boundaries = mesh_.boundaries();
58 label nBoundaryFaces(0);
59 if( activePatch_ < 0 )
62 forAll(boundaries, patchI)
63 nBoundaryFaces += boundaries[patchI].patchSize();
70 boundaries[0].patchStart()
73 else if( activePatch_ < boundaries.size() )
75 nBoundaryFaces = boundaries[activePatch_].patchSize();
82 boundaries[activePatch_].patchStart()
89 "void meshSurfaceEngine::calculateBoundaryFaces() const"
90 ) << "Cannot select boundary faces. Invalid patch index "
91 << activePatch_ << exit(FatalError);
94 reduce(nBoundaryFaces, sumOp<label>());
95 Info << "Found " << nBoundaryFaces << " boundary faces " << endl;
101 "void meshSurfaceEngine::calculateBoundaryFaces() const"
102 ) << "Boundary faces are not at the end of the face list!"
107 void meshSurfaceEngine::calculateBoundaryOwners() const
109 const labelList& owner = mesh_.owner();
111 const faceList::subList& boundaryFaces = this->boundaryFaces();
113 if( !boundaryFaceOwnersPtr_ )
114 boundaryFaceOwnersPtr_ = new labelList(boundaryFaces.size());
116 labelList& owners = *boundaryFaceOwnersPtr_;
118 const label start = mesh_.boundaries()[0].patchStart();
121 # pragma omp parallel for schedule(static, 1)
123 forAll(boundaryFaces, fI)
124 owners[fI] = owner[start+fI];
127 void meshSurfaceEngine::calculateBoundaryNodes() const
129 //- mark boundary points
132 bppPtr_ = new labelList(mesh_.points().size(), -1);
133 labelList& bp = *bppPtr_;
135 const faceList::subList& boundaryFaces = this->boundaryFaces();
137 boolList isBndPoint(bp.size(), false);
140 const label nThreads = 3 * omp_get_num_procs();
141 # pragma omp parallel for num_threads(nThreads) schedule(static, 1)
143 forAll(boundaryFaces, bfI)
145 const face& bf = boundaryFaces[bfI];
148 isBndPoint[bf[pI]] = true;
151 forAll(isBndPoint, pI)
157 if( Pstream::parRun() )
159 const faceListPMG& faces = mesh_.faces();
160 const PtrList<processorBoundaryPatch>& procBoundaries =
161 mesh_.procBoundaries();
163 //- exchange information with processors
164 //- this is need sometimes to find all nodes at the boundary
170 //- send bnd nodes to other processor
171 forAll(procBoundaries, patchI)
173 const label start = procBoundaries[patchI].patchStart();
174 const label end = start + procBoundaries[patchI].patchSize();
177 labelHashSet addedPoint;
178 for(label faceI=start;faceI<end;++faceI)
180 const face& f = faces[faceI];
182 if( (bp[f[pI]] != -1) && !addedPoint.found(f[pI]) )
184 addedPoint.insert(f[pI]);
186 //- data is sent as follows
187 //- 1. local face label in patch
188 //- 2. local node in face
189 dts.append(faceI-start);
190 dts.append((f.size() - pI) % f.size());
197 procBoundaries[patchI].neiProcNo(),
203 //- receive data and update positions if needed
204 forAll(procBoundaries, patchI)
206 const label start = procBoundaries[patchI].patchStart();
207 labelList receiveData;
208 IPstream fromOtherProc
211 procBoundaries[patchI].neiProcNo()
213 fromOtherProc >> receiveData;
216 while( counter < receiveData.size() )
218 const label fI = receiveData[counter++];
219 const label pI = receiveData[counter++];
221 if( bp[faces[start+fI][pI]] == -1 )
223 bp[faces[start+fI][pI]] = pointI++;
229 reduce(found, maxOp<bool>());
234 if( !boundaryPointsPtr_ )
235 boundaryPointsPtr_ = new labelList();
237 labelList& boundaryPoints = *boundaryPointsPtr_;
238 boundaryPoints.setSize(pointI);
240 //- fill the boundaryPoints list
242 # pragma omp parallel for num_threads(nThreads) schedule(static, 1)
247 boundaryPoints[bp[bpI]] = bpI;
251 void meshSurfaceEngine::calculateBoundaryFacePatches() const
253 const faceList::subList& bFaces = this->boundaryFaces();
254 boundaryFacePatchPtr_ = new labelList(bFaces.size());
255 labelList& facePatch = *boundaryFacePatchPtr_;
258 const PtrList<boundaryPatch>& boundaries = mesh_.boundaries();
259 forAll(boundaries, patchI)
261 const label nFaces = boundaries[patchI].patchSize();
262 for(label patchFaceI=0;patchFaceI<nFaces;++patchFaceI)
264 facePatch[faceI] = patchI;
270 void meshSurfaceEngine::calculatePointFaces() const
272 //- fill pointFacesAddr
273 if( !pointFacesPtr_ )
274 pointFacesPtr_ = new VRWGraph();
275 VRWGraph& pointFacesAddr = *pointFacesPtr_;
277 if( !pointInFacePtr_ )
278 pointInFacePtr_ = new VRWGraph();
279 VRWGraph& pointInFaceAddr = *pointInFacePtr_;
281 const labelList& bPoints = this->boundaryPoints();
282 const faceList::subList& bFaces = this->boundaryFaces();
284 //- create boundary points
285 const labelList& bp = this->bp();
290 label nThreads = 3 * omp_get_num_procs();
291 if( bPoints.size() < 1000 )
294 const label nThreads(1);
297 label minRow(INT_MAX), maxRow(0);
298 List<List<LongList<labelPair> > > dataForOtherThreads(nThreads);
301 # pragma omp parallel num_threads(nThreads)
305 const label threadI = omp_get_thread_num();
307 const label threadI(0);
310 List<LongList<labelPair> >& dot = dataForOtherThreads[threadI];
311 dot.setSize(nThreads);
313 //- find min and max entry in the graph
314 //- they are used for assigning ranges of values local for each process
315 label localMinRow(minRow), localMaxRow(0);
317 # pragma omp for schedule(static)
321 const face& bf = bFaces[bfI];
324 const label bpI = bp[bf[pI]];
325 localMaxRow = Foam::max(localMaxRow, bpI);
326 localMinRow = Foam::min(localMinRow, bpI);
333 # pragma omp critical
336 minRow = Foam::min(minRow, localMinRow);
337 minRow = Foam::max(minRow, 0);
338 maxRow = Foam::max(maxRow, localMaxRow);
347 //- initialise appearances
349 # pragma omp for schedule(static)
351 for(label i=0;i<maxRow;++i)
358 const label range = (maxRow - minRow) / nThreads + 1;
359 const label localMin = minRow + threadI * range;
360 const label localMax = Foam::min(localMin + range, maxRow);
362 //- find the number of appearances of each element in the original graph
364 # pragma omp for schedule(static)
368 const face& bf = bFaces[bfI];
372 const label bpI = bp[bf[pI]];
374 const label threadNo = (bpI - minRow) / range;
376 if( threadNo == threadI )
382 dot[threadNo].append(labelPair(bpI, bfI));
391 //- count the appearances which are not local to the processor
392 for(label i=0;i<nThreads;++i)
394 const LongList<labelPair>& data =
395 dataForOtherThreads[i][threadI];
398 ++npf[data[j].first()];
410 VRWGraphSMPModifier(pointFacesAddr).setSizeAndRowSize(npf);
411 VRWGraphSMPModifier(pointInFaceAddr).setSizeAndRowSize(npf);
418 for(label i=localMin;i<localMax;++i)
421 //- start filling reverse addressing graph
422 //- update data from processors with smaller labels
423 for(label i=0;i<threadI;++i)
425 const LongList<labelPair>& data =
426 dataForOtherThreads[i][threadI];
430 const label bpI = data[j].first();
431 const label bfI = data[j].second();
433 pointFacesAddr(bpI, npf[bpI]) = bfI;
434 pointInFaceAddr(bpI, npf[bpI]) =
435 bFaces[bfI].which(bPoints[bpI]);
441 //- update data local to the processor
443 # pragma omp for schedule(static)
447 const face& bf = bFaces[bfI];
451 const label bpI = bp[bf[pI]];
453 if( (bpI >= localMin) && (bpI < localMax) )
455 pointInFaceAddr(bpI, npf[bpI]) = pI;
456 pointFacesAddr(bpI, npf[bpI]++) = bfI;
461 //- update data from the processors with higher labels
462 for(label i=threadI+1;i<nThreads;++i)
464 const LongList<labelPair>& data =
465 dataForOtherThreads[i][threadI];
469 const label bpI = data[j].first();
470 const label bfI = data[j].second();
472 pointFacesAddr(bpI, npf[bpI]) = bfI;
473 pointInFaceAddr(bpI, npf[bpI]) =
474 bFaces[bfI].which(bPoints[bpI]);
481 pointFacesAddr.setSize(bPoints.size());
482 pointInFaceAddr.setSize(bPoints.size());
485 void meshSurfaceEngine::calculatePointPatches() const
487 if( !pointPatchesPtr_ )
488 pointPatchesPtr_ = new VRWGraph();
489 VRWGraph& pPatches = *pointPatchesPtr_;
491 const labelList& facePatch = boundaryFacePatches();
492 const VRWGraph& pFaces = pointFaces();
495 const label nThreads = 3 * omp_get_num_procs();
498 labelList npPatches(pFaces.size());
501 # pragma omp parallel num_threads(nThreads)
505 # pragma omp for schedule(static)
511 # pragma omp for schedule(static)
516 forAllRow(pFaces, bpI, pfI)
517 pf.appendIfNotIn(facePatch[pFaces(bpI, pfI)]);
519 npPatches[bpI] = pf.size();
527 VRWGraphSMPModifier(pPatches).setSizeAndRowSize(npPatches);
532 # pragma omp for schedule(static)
537 forAllRow(pFaces, bpI, pfI)
538 pf.appendIfNotIn(facePatch[pFaces(bpI, pfI)]);
540 pPatches.setRow(bpI, pf);
544 if( Pstream::parRun() )
546 const labelList& globalPointLabel = globalBoundaryPointLabel();
547 const VRWGraph& bpAtProcs = this->bpAtProcs();
548 const Map<label>& globalToLocal = globalToLocalBndPointAddressing();
550 std::map<label, labelLongList> exchangeData;
552 forAllConstIter(Map<label>, globalToLocal, iter)
554 const label bpI = iter();
556 forAllRow(bpAtProcs, bpI, procI)
558 const label neiProc = bpAtProcs(bpI, procI);
559 if( neiProc == Pstream::myProcNo() )
562 if( exchangeData.find(neiProc) == exchangeData.end() )
566 std::make_pair(neiProc, labelLongList())
570 labelLongList& dataToSend = exchangeData[neiProc];
572 //- prepare data which will be sent
573 //- data is sent as follows
574 //- 1. global point label
575 //- 2. number of local patches for point
576 //- 3. patch labels for a given point
577 dataToSend.append(globalPointLabel[bpI]);
578 dataToSend.append(pPatches.sizeOfRow(bpI));
579 forAllRow(pPatches, bpI, patchI)
580 dataToSend.append(pPatches(bpI, patchI));
584 //- exchange data with other processors
585 labelLongList receivedData;
586 help::exchangeMap(exchangeData, receivedData);
589 while( counter < receivedData.size() )
591 const label bpI = globalToLocal[receivedData[counter++]];
592 const label nPatches = receivedData[counter++];
593 for(label i=0;i<nPatches;++i)
594 pPatches.appendIfNotIn(bpI, receivedData[counter++]);
599 void meshSurfaceEngine::calculatePointPoints() const
601 if( !pointPointsPtr_ )
602 pointPointsPtr_ = new VRWGraph();
604 VRWGraph& pointPoints = *pointPointsPtr_;
606 const labelList& boundaryPoints = this->boundaryPoints();
607 const faceList::subList& bFaces = this->boundaryFaces();
608 const VRWGraph& pFaces = this->pointFaces();
609 const labelList& bp = this->bp();
612 const label nThreads = 3 * omp_get_num_procs();
615 labelList npp(boundaryPoints.size());
618 # pragma omp parallel num_threads(nThreads)
622 # pragma omp for schedule(static)
628 # pragma omp for schedule(static)
632 DynList<label> pPoints;
634 forAllRow(pFaces, bpI, pfI)
636 const face& bf = bFaces[pFaces(bpI, pfI)];
638 const label pos = bf.which(boundaryPoints[bpI]);
640 pPoints.appendIfNotIn(bp[bf.nextLabel(pos)]);
641 pPoints.appendIfNotIn(bp[bf.prevLabel(pos)]);
644 npp[bpI] = pPoints.size();
652 VRWGraphSMPModifier(pointPoints).setSizeAndRowSize(npp);
657 # pragma omp for schedule(static)
661 DynList<label> pPoints;
663 forAllRow(pFaces, bpI, pfI)
665 const face& bf = bFaces[pFaces(bpI, pfI)];
667 const label pos = bf.which(boundaryPoints[bpI]);
669 pPoints.appendIfNotIn(bp[bf.nextLabel(pos)]);
670 pPoints.appendIfNotIn(bp[bf.prevLabel(pos)]);
673 pointPoints.setRow(bpI, pPoints);
677 if( Pstream::parRun() )
679 //- this is needed to make the connection matrix symmetric
680 //- on all processors. In some cases the points on a given processor
681 //- may not be connected because of a single layer of faces on some
682 //- other processor. P0, P0 | P1 | P0 P0
683 const labelList& globalPointLabel = this->globalBoundaryPointLabel();
684 const Map<label>& globalToLocal =
685 this->globalToLocalBndPointAddressing();
686 const VRWGraph& bpAtProcs = this->bpAtProcs();
688 std::map<label, labelLongList> exchangeData;
689 forAllConstIter(Map<label>, globalToLocal, iter)
691 const label bpI = iter();
693 DynList<label> neiToSend;
694 forAllRow(pointPoints, bpI, j)
696 const label bpJ = pointPoints(bpI, j);
697 if( bpAtProcs.sizeOfRow(bpJ) != 0 )
698 neiToSend.append(bpJ);
701 forAllRow(bpAtProcs, bpI, procI)
703 const label neiProc = bpAtProcs(bpI, procI);
704 if( neiProc == Pstream::myProcNo() )
707 if( exchangeData.find(neiProc) == exchangeData.end() )
708 exchangeData.insert(std::make_pair(neiProc,labelLongList()));
710 if( neiToSend.size() != 0 )
712 labelLongList& dts = exchangeData[neiProc];
713 dts.append(globalPointLabel[bpI]);
714 dts.append(neiToSend.size());
716 dts.append(globalPointLabel[neiToSend[i]]);
721 labelLongList receivedData;
722 help::exchangeMap(exchangeData, receivedData);
725 while( counter < receivedData.size() )
727 const label bpI = globalToLocal[receivedData[counter++]];
728 const label size = receivedData[counter++];
729 for(label i=0;i<size;++i)
731 const label gpI = receivedData[counter++];
732 if( globalToLocal.found(gpI) )
733 pointPoints.appendIfNotIn(bpI, globalToLocal[gpI]);
739 void meshSurfaceEngine::calculatePointNormals() const
741 const VRWGraph& pFaces = pointFaces();
742 const vectorField& fNormals = faceNormals();
744 pointNormalsPtr_ = new vectorField(pFaces.size());
747 # pragma omp parallel for if( pFaces.size() > 1000 ) schedule(dynamic, 50)
751 vector normal(vector::zero);
753 forAllRow(pFaces, pI, pfI)
754 normal += fNormals[pFaces(pI, pfI)];
756 const scalar d = mag(normal);
763 normal = vector::zero;
766 (*pointNormalsPtr_)[pI] = normal;
769 updatePointNormalsAtProcBoundaries();
772 void meshSurfaceEngine::calculateFaceNormals() const
774 const faceList::subList& bFaces = this->boundaryFaces();
775 const pointFieldPMG& points = mesh_.points();
777 faceNormalsPtr_ = new vectorField(bFaces.size());
780 # pragma omp parallel for if( bFaces.size() > 1000 )
784 const face& bf = bFaces[bfI];
786 faceNormalsPtr_->operator[](bfI) = bf.normal(points);
790 void meshSurfaceEngine::calculateFaceCentres() const
792 const faceList::subList& bFaces = this->boundaryFaces();
793 const pointFieldPMG& points = mesh_.points();
795 faceCentresPtr_ = new vectorField(bFaces.size());
798 # pragma omp parallel for if( bFaces.size() > 1000 )
801 faceCentresPtr_->operator[](bfI) = bFaces[bfI].centre(points);
804 void meshSurfaceEngine::updatePointNormalsAtProcBoundaries() const
806 if( !Pstream::parRun() )
809 const VRWGraph& pFaces = pointFaces();
810 const vectorField& fNormals = faceNormals();
811 const labelList& globalPointLabel = this->globalBoundaryPointLabel();
812 const Map<label>& globalToLocal =
813 this->globalToLocalBndPointAddressing();
814 const VRWGraph& bpAtProcs = this->bpAtProcs();
816 vectorField& pNormals = *pointNormalsPtr_;
818 //- create data which will be sent to other processors
819 std::map<label, LongList<labelledPoint> > exchangeData;
821 forAllConstIter(Map<label>, globalToLocal, iter)
823 const label bpI = iter();
825 vector& n = pNormals[bpI];
828 forAllRow(pFaces, bpI, pfI)
829 n += fNormals[pFaces(bpI, pfI)];
831 forAllRow(bpAtProcs, bpI, procI)
833 const label neiProc = bpAtProcs(bpI, procI);
834 if( neiProc == Pstream::myProcNo() )
836 if( exchangeData.find(neiProc) == exchangeData.end() )
840 std::make_pair(neiProc, LongList<labelledPoint>())
844 exchangeData[neiProc].append
846 labelledPoint(globalPointLabel[bpI], n)
851 //- exchange data with other procs
852 LongList<labelledPoint> receivedData;
853 help::exchangeMap(exchangeData, receivedData);
855 forAll(receivedData, i)
857 const label bpI = globalToLocal[receivedData[i].pointLabel()];
858 pNormals[bpI] += receivedData[i].coordinates();
861 //- normalize vectors
863 # pragma omp parallel for if( bpAtProcs.size() > 1000 ) \
866 forAll(bpAtProcs, bpI)
868 if( bpAtProcs.sizeOfRow(bpI) == 0 )
871 vector normal = pNormals[bpI];
872 const scalar d = mag(normal);
879 normal = vector::zero;
882 pNormals[bpI] = normal;
886 void meshSurfaceEngine::calculateEdgesAndAddressing() const
888 const VRWGraph& pFaces = pointFaces();
889 const faceList::subList& bFaces = boundaryFaces();
890 const labelList& bp = this->bp();
892 edgesPtr_ = new edgeList();
893 edgeList& edges = *edgesPtr_;
895 bpEdgesPtr_ = new VRWGraph();
896 VRWGraph& bpEdges = *bpEdgesPtr_;
899 label nThreads = 3 * omp_get_num_procs();
900 if( pFaces.size() < 1000 )
903 const label nThreads(1);
906 labelList nEdgesForThread(nThreads);
911 # pragma omp parallel num_threads(nThreads)
914 LongList<edge> edgesHelper;
917 # pragma omp for schedule(static)
921 const face& bf = bFaces[bfI];
925 const edge fe = bf.faceEdge(pI);
926 const label bpI = bp[fe.start()];
927 const label e = fe.end();
929 DynList<label> edgeFaces;
933 //- find all faces attached to this edge
934 //- store the edge in case the face faceI is the face
935 //- with the smallest label
936 forAllRow(pFaces, bpI, pfI)
938 const label ofI = pFaces(bpI, pfI);
939 const face& of = bFaces[ofI];
941 if( of.which(e) < 0 )
949 edgeFaces.append(ofI);
953 edgesHelper.append(fe);
957 //- this enables other threads to see the number of edges
958 //- generated by each thread
960 const label threadI = omp_get_thread_num();
962 const label threadI(0);
964 nEdgesForThread[threadI] = edgesHelper.size();
967 # pragma omp critical
969 edgeI += edgesHelper.size();
976 edgesPtr_->setSize(edgeI);
982 //- find the starting position of the edges generated by this thread
983 //- in the global list of edges
985 for(label i=0;i<threadI;++i)
986 localStart += nEdgesForThread[i];
988 //- store edges into the global list
989 forAll(edgesHelper, i)
990 edgesPtr_->operator[](localStart+i) = edgesHelper[i];
994 VRWGraphSMPModifier(bpEdges).reverseAddressing(bp, edges);
995 bpEdges.setSize(pFaces.size());
997 if( !Pstream::parRun() )
1005 //- mark boundary edges for processors which do not contain
1006 //- boundary faces. This procedure is needed to identify boundary
1007 //- edges which are not part of any boundary face on their processor
1008 const faceListPMG& faces = mesh_.faces();
1009 const PtrList<processorBoundaryPatch>& procBoundaries =
1010 mesh_.procBoundaries();
1012 //- send boundary edges to neighbour processors
1013 forAll(procBoundaries, patchI)
1015 const label start = procBoundaries[patchI].patchStart();
1016 const label end = start + procBoundaries[patchI].patchSize();
1019 for(label faceI=start;faceI<end;++faceI)
1021 const face& f = faces[faceI];
1024 const edge e = f.faceEdge(eI);
1025 const label s = bp[e.start()];
1029 forAllRow(bpEdges, s, peI)
1030 if( edges[bpEdges(s, peI)] == e )
1032 dts.append(faceI-start);
1033 dts.append((f.size()-1-eI)%f.size());
1039 OPstream toOtherProc
1042 procBoundaries[patchI].neiProcNo(),
1048 //- receive data from other processors. Mark edges which are not yet
1049 //- marked as boundary edges
1050 forAll(procBoundaries, patchI)
1052 labelList receivedEdges;
1053 IPstream fromOtherProc
1056 procBoundaries[patchI].neiProcNo()
1058 fromOtherProc >> receivedEdges;
1060 const label start = procBoundaries[patchI].patchStart();
1061 label nReceivedEdges(0);
1062 while( nReceivedEdges < receivedEdges.size() )
1064 const face& f = faces[start+receivedEdges[nReceivedEdges++]];
1065 const label eI = receivedEdges[nReceivedEdges++];
1067 const edge e = f.faceEdge(eI);
1068 const label s = bp[e.start()];
1071 forAllRow(bpEdges, s, peI)
1072 if( edges[bpEdges(s, peI)] == e )
1080 //- create a new edge
1082 edges.newElmt(edgeI) = e;
1084 bpEdges.append(bp[e.start()], edgeI);
1085 bpEdges.append(bp[e.end()], edgeI);
1091 reduce(addEdges, maxOp<bool>());
1092 } while( addEdges );
1094 edges.setSize(edgeI);
1097 void meshSurfaceEngine::calculateFaceEdgesAddressing() const
1099 const faceList::subList& bFaces = this->boundaryFaces();
1100 const labelList& bp = this->bp();
1101 const edgeList& edges = this->edges();
1102 const VRWGraph& pointFaces = this->pointFaces();
1104 faceEdgesPtr_ = new VRWGraph(bFaces.size());
1105 VRWGraph& faceEdges = *faceEdgesPtr_;
1107 labelList nfe(bFaces.size());
1110 const label nThreads = 3 * omp_get_num_procs();
1112 # pragma omp parallel num_threads(nThreads)
1116 # pragma omp for schedule(static)
1119 nfe[bfI] = bFaces[bfI].size();
1122 # pragma omp barrier
1126 VRWGraphSMPModifier(faceEdges).setSizeAndRowSize(nfe);
1129 # pragma omp barrier
1131 # pragma omp for schedule(static)
1133 forAll(edges, edgeI)
1135 const edge ee = edges[edgeI];
1136 const label bpI = bp[ee.start()];
1138 forAllRow(pointFaces, bpI, pfI)
1140 const label bfI = pointFaces(bpI, pfI);
1142 const face& bf = bFaces[bfI];
1145 if( bf.faceEdge(eI) == ee )
1147 faceEdges[bfI][eI] = edgeI;
1156 void meshSurfaceEngine::calculateEdgeFacesAddressing() const
1158 const faceList::subList& bFaces = this->boundaryFaces();
1159 const VRWGraph& pointFaces = this->pointFaces();
1160 const edgeList& edges = this->edges();
1161 const labelList& bp = this->bp();
1163 edgeFacesPtr_ = new VRWGraph();
1164 VRWGraph& edgeFaces = *edgeFacesPtr_;
1166 labelList nef(edges.size());
1169 const label nThreads = 3 * omp_get_num_procs();
1171 # pragma omp parallel num_threads(nThreads)
1175 # pragma omp for schedule(static)
1181 # pragma omp for schedule(static)
1183 forAll(edges, edgeI)
1185 const edge& ee = edges[edgeI];
1186 const label bpI = bp[ee.start()];
1188 forAllRow(pointFaces, bpI, pfI)
1190 const label bfI = pointFaces(bpI, pfI);
1192 const face& bf = bFaces[bfI];
1196 if( bf.faceEdge(eI) == ee )
1206 # pragma omp barrier
1210 VRWGraphSMPModifier(edgeFaces).setSizeAndRowSize(nef);
1213 # pragma omp barrier
1215 # pragma omp for schedule(static)
1217 forAll(edges, edgeI)
1219 const edge& ee = edges[edgeI];
1220 const label bpI = bp[ee.start()];
1222 DynList<label> eFaces;
1223 forAllRow(pointFaces, bpI, pfI)
1225 const label bfI = pointFaces(bpI, pfI);
1227 const face& bf = bFaces[bfI];
1231 if( bf.faceEdge(eI) == ee )
1239 edgeFaces.setRow(edgeI, eFaces);
1244 void meshSurfaceEngine::calculateEdgePatchesAddressing() const
1246 edgePatchesPtr_ = new VRWGraph();
1247 VRWGraph& edgePatches = *edgePatchesPtr_;
1249 const VRWGraph& edgeFaces = this->edgeFaces();
1250 const labelList& facePatch = this->boundaryFacePatches();
1252 edgePatches.setSize(edgeFaces.size());
1254 forAll(edgeFaces, eI)
1256 DynList<label> ePatches;
1258 forAllRow(edgeFaces, eI, i)
1260 const label patchI = facePatch[edgeFaces(eI, i)];
1262 ePatches.appendIfNotIn(patchI);
1265 edgePatches.setRow(eI, ePatches);
1268 if( Pstream::parRun() )
1270 const Map<label>& globalToLocal = globalToLocalBndEdgeAddressing();
1271 const Map<label>& otherPatch = this->otherEdgeFacePatch();
1273 forAllConstIter(Map<label>, globalToLocal, it)
1275 const label beI = it();
1277 edgePatches.appendIfNotIn(beI, otherPatch[beI]);
1282 void meshSurfaceEngine::calculateFaceFacesAddressing() const
1284 const VRWGraph& edgeFaces = this->edgeFaces();
1286 const faceList::subList& bFaces = boundaryFaces();
1287 faceFacesPtr_ = new VRWGraph(bFaces.size());
1288 VRWGraph& faceFaces = *faceFacesPtr_;
1291 faceFaces.setRowSize(bfI, bFaces[bfI].size());
1293 labelList nAppearances(bFaces.size(), 0);
1295 forAll(edgeFaces, efI)
1297 if( edgeFaces.sizeOfRow(efI) == 2 )
1299 const label f0 = edgeFaces(efI, 0);
1300 const label f1 = edgeFaces(efI, 1);
1302 faceFaces(f0, nAppearances[f0]++) = f1;
1303 faceFaces(f1, nAppearances[f1]++) = f0;
1305 else if( Pstream::parRun() && (edgeFaces.sizeOfRow(efI) == 1) )
1307 const label f0 = edgeFaces(efI, 0);
1308 faceFaces(f0, nAppearances[f0]++) = -1;
1310 else if( Pstream::parRun() && (edgeFaces.sizeOfRow(efI) != 0 ) )
1314 "void meshSurfaceEngine::calculateFaceFacesAddressing() const"
1315 ) << "The surface of the mesh is invalid!"
1316 << " The number of faces containing edge " << efI
1317 << " is " << edgeFaces.sizeOfRow(efI)
1318 << " Cannot continue" << exit(FatalError);
1323 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1325 } // End namespace Foam
1327 // ************************************************************************* //