1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "globalMeshData.H"
29 #include "PstreamCombineReduceOps.H"
30 #include "processorPolyPatch.H"
31 #include "demandDrivenData.H"
32 #include "globalPoints.H"
34 #include "mapDistribute.H"
35 #include "labelIOList.H"
36 #include "PackedList.H"
37 #include "mergePoints.H"
38 #include "matchPoints.H"
40 #include "globalIndexAndTransform.H"
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 defineTypeNameAndDebug(Foam::globalMeshData, 0);
46 // Geometric matching tolerance. Factor of mesh bounding box.
47 const Foam::scalar Foam::globalMeshData::matchTol_ = 1E-8;
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 // Collect processor patch addressing.
53 void Foam::globalMeshData::initProcAddr()
55 processorPatchIndices_.setSize(mesh_.boundaryMesh().size());
56 processorPatchIndices_ = -1;
58 processorPatchNeighbours_.setSize(mesh_.boundaryMesh().size());
59 processorPatchNeighbours_ = -1;
61 // Construct processor patch indexing. processorPatchNeighbours_ only
62 // set if running in parallel!
63 processorPatches_.setSize(mesh_.boundaryMesh().size());
65 label nNeighbours = 0;
67 forAll(mesh_.boundaryMesh(), patchi)
69 if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
71 processorPatches_[nNeighbours] = patchi;
72 processorPatchIndices_[patchi] = nNeighbours++;
75 processorPatches_.setSize(nNeighbours);
78 if (Pstream::parRun())
80 PstreamBuffers pBufs(Pstream::nonBlocking);
82 // Send indices of my processor patches to my neighbours
83 forAll(processorPatches_, i)
85 label patchi = processorPatches_[i];
89 refCast<const processorPolyPatch>
91 mesh_.boundaryMesh()[patchi]
96 toNeighbour << processorPatchIndices_[patchi];
99 pBufs.finishedSends();
101 forAll(processorPatches_, i)
103 label patchi = processorPatches_[i];
105 UIPstream fromNeighbour
107 refCast<const processorPolyPatch>
109 mesh_.boundaryMesh()[patchi]
114 fromNeighbour >> processorPatchNeighbours_[patchi];
120 void Foam::globalMeshData::calcSharedPoints() const
125 || sharedPointLabelsPtr_.valid()
126 || sharedPointAddrPtr_.valid()
129 FatalErrorIn("globalMeshData::calcSharedPoints()")
130 << "Shared point addressing already done" << abort(FatalError);
133 // Calculate all shared points (exclude points that are only
134 // on two coupled patches). This does all the hard work.
135 globalPoints parallelPoints(mesh_, false, true);
137 // Count the number of master points
139 forAll(parallelPoints.pointPoints(), i)
141 const labelList& pPoints = parallelPoints.pointPoints()[i];
142 const labelList& transPPoints =
143 parallelPoints.transformedPointPoints()[i];
145 if (pPoints.size()+transPPoints.size() > 0)
151 // Allocate global numbers
152 globalIndex masterNumbering(nMaster);
154 nGlobalPoints_ = masterNumbering.size();
157 // Push master number to slaves
158 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
159 // 1. Fill master and slave slots
161 labelList master(parallelPoints.map().constructSize(), -1);
162 forAll(parallelPoints.pointPoints(), i)
164 const labelList& pPoints = parallelPoints.pointPoints()[i];
165 const labelList& transPPoints =
166 parallelPoints.transformedPointPoints()[i];
168 if (pPoints.size()+transPPoints.size() > 0)
170 master[i] = masterNumbering.toGlobal(nMaster);
173 master[pPoints[j]] = master[i];
175 forAll(transPPoints, j)
177 master[transPPoints[j]] = master[i];
184 // 2. Push slave slots back to local storage on originating processor
185 // For all the four types of points:
186 // - local master : already set
187 // - local transformed slave point : the reverse transform at
188 // reverseDistribute will have copied it back to its originating local
190 // - remote untransformed slave point : sent back to originating processor
191 // - remote transformed slave point : the reverse transform will
192 // copy it back into the remote slot which then gets sent back to
193 // originating processor
195 parallelPoints.map().reverseDistribute
197 parallelPoints.map().constructSize(),
202 // Collect all points that are a master or refer to a master.
204 forAll(parallelPoints.pointPoints(), i)
212 sharedPointLabelsPtr_.reset(new labelList(nMaster));
213 labelList& sharedPointLabels = sharedPointLabelsPtr_();
214 sharedPointAddrPtr_.reset(new labelList(nMaster));
215 labelList& sharedPointAddr = sharedPointAddrPtr_();
218 forAll(parallelPoints.pointPoints(), i)
222 // I am master or slave
223 sharedPointLabels[nMaster] = i;
224 sharedPointAddr[nMaster] = master[i];
231 Pout<< "globalMeshData : nGlobalPoints_:" << nGlobalPoints_ << nl
232 << "globalMeshData : sharedPointLabels_:"
233 << sharedPointLabelsPtr_().size() << nl
234 << "globalMeshData : sharedPointAddr_:"
235 << sharedPointAddrPtr_().size() << endl;
240 // Given information about locally used edges allocate global shared edges.
241 void Foam::globalMeshData::countSharedEdges
243 const EdgeMap<labelList>& procSharedEdges,
244 EdgeMap<label>& globalShared,
248 // Count occurrences of procSharedEdges in global shared edges table.
249 forAllConstIter(EdgeMap<labelList>, procSharedEdges, iter)
251 const edge& e = iter.key();
253 EdgeMap<label>::iterator globalFnd = globalShared.find(e);
255 if (globalFnd == globalShared.end())
257 // First time occurrence of this edge. Check how many we are adding.
258 if (iter().size() == 1)
260 // Only one edge. Mark with special value.
261 globalShared.insert(e, -1);
265 // Edge used more than once (even by local shared edges alone)
266 // so allocate proper shared edge label.
267 globalShared.insert(e, sharedEdgeI++);
272 if (globalFnd() == -1)
274 // Second time occurence of this edge. Assign proper
276 globalFnd() = sharedEdgeI++;
283 // Shared edges are shared between multiple processors. By their nature both
284 // of their endpoints are shared points. (but not all edges using two shared
285 // points are shared edges! There might e.g. be an edge between two unrelated
286 // clusters of shared points)
287 void Foam::globalMeshData::calcSharedEdges() const
292 || sharedEdgeLabelsPtr_.valid()
293 || sharedEdgeAddrPtr_.valid()
296 FatalErrorIn("globalMeshData::calcSharedEdges()")
297 << "Shared edge addressing already done" << abort(FatalError);
301 const labelList& sharedPtAddr = sharedPointAddr();
302 const labelList& sharedPtLabels = sharedPointLabels();
304 // Since don't want to construct pointEdges for whole mesh create
305 // Map for all shared points.
306 Map<label> meshToShared(2*sharedPtLabels.size());
307 forAll(sharedPtLabels, i)
309 meshToShared.insert(sharedPtLabels[i], i);
312 // Find edges using shared points. Store correspondence to local edge
313 // numbering. Note that multiple local edges can have the same shared
314 // points! (for cyclics or separated processor patches)
315 EdgeMap<labelList> localShared(2*sharedPtAddr.size());
317 const edgeList& edges = mesh_.edges();
321 const edge& e = edges[edgeI];
323 Map<label>::const_iterator e0Fnd = meshToShared.find(e[0]);
325 if (e0Fnd != meshToShared.end())
327 Map<label>::const_iterator e1Fnd = meshToShared.find(e[1]);
329 if (e1Fnd != meshToShared.end())
331 // Found edge which uses shared points. Probably shared.
333 // Construct the edge in shared points (or rather global indices
334 // of the shared points)
337 sharedPtAddr[e0Fnd()],
338 sharedPtAddr[e1Fnd()]
341 EdgeMap<labelList>::iterator iter =
342 localShared.find(sharedEdge);
344 if (iter == localShared.end())
346 // First occurrence of this point combination. Store.
347 localShared.insert(sharedEdge, labelList(1, edgeI));
351 // Add this edge to list of edge labels.
352 labelList& edgeLabels = iter();
354 label sz = edgeLabels.size();
355 edgeLabels.setSize(sz+1);
356 edgeLabels[sz] = edgeI;
363 // Now we have a table on every processors which gives its edges which use
364 // shared points. Send this all to the master and have it allocate
365 // global edge numbers for it. But only allocate a global edge number for
366 // edge if it is used more than once!
367 // Note that we are now sending the whole localShared to the master whereas
368 // we only need the local count (i.e. the number of times a global edge is
369 // used). But then this only gets done once so not too bothered about the
370 // extra global communication.
372 EdgeMap<label> globalShared(nGlobalPoints());
374 if (Pstream::master())
376 label sharedEdgeI = 0;
378 // Merge my shared edges into the global list
381 Pout<< "globalMeshData::calcSharedEdges : Merging in from proc0 : "
382 << localShared.size() << endl;
384 countSharedEdges(localShared, globalShared, sharedEdgeI);
386 // Receive data from slaves and insert
387 if (Pstream::parRun())
391 int slave=Pstream::firstSlave();
392 slave<=Pstream::lastSlave();
396 // Receive the edges using shared points from the slave.
397 IPstream fromSlave(Pstream::blocking, slave);
398 EdgeMap<labelList> procSharedEdges(fromSlave);
402 Pout<< "globalMeshData::calcSharedEdges : "
403 << "Merging in from proc"
404 << Foam::name(slave) << " : " << procSharedEdges.size()
407 countSharedEdges(procSharedEdges, globalShared, sharedEdgeI);
411 // Now our globalShared should have some edges with -1 as edge label
412 // These were only used once so are not proper shared edges.
415 EdgeMap<label> oldSharedEdges(globalShared);
417 globalShared.clear();
419 forAllConstIter(EdgeMap<label>, oldSharedEdges, iter)
423 globalShared.insert(iter.key(), iter());
428 Pout<< "globalMeshData::calcSharedEdges : Filtered "
429 << oldSharedEdges.size()
430 << " down to " << globalShared.size() << endl;
435 // Send back to slaves.
436 if (Pstream::parRun())
440 int slave=Pstream::firstSlave();
441 slave<=Pstream::lastSlave();
445 // Receive the edges using shared points from the slave.
446 OPstream toSlave(Pstream::blocking, slave);
447 toSlave << globalShared;
453 // Send local edges to master
455 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
457 toMaster << localShared;
459 // Receive merged edges from master.
461 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
463 fromMaster >> globalShared;
467 // Now use the global shared edges list (globalShared) to classify my local
468 // ones (localShared)
470 nGlobalEdges_ = globalShared.size();
472 DynamicList<label> dynSharedEdgeLabels(globalShared.size());
473 DynamicList<label> dynSharedEdgeAddr(globalShared.size());
475 forAllConstIter(EdgeMap<labelList>, localShared, iter)
477 const edge& e = iter.key();
479 EdgeMap<label>::const_iterator edgeFnd = globalShared.find(e);
481 if (edgeFnd != globalShared.end())
483 // My local edge is indeed a shared one. Go through all local edge
484 // labels with this point combination.
485 const labelList& edgeLabels = iter();
487 forAll(edgeLabels, i)
489 // Store label of local mesh edge
490 dynSharedEdgeLabels.append(edgeLabels[i]);
492 // Store label of shared edge
493 dynSharedEdgeAddr.append(edgeFnd());
498 sharedEdgeLabelsPtr_.reset(new labelList());
499 labelList& sharedEdgeLabels = sharedEdgeLabelsPtr_();
500 sharedEdgeLabels.transfer(dynSharedEdgeLabels);
502 sharedEdgeAddrPtr_.reset(new labelList());
503 labelList& sharedEdgeAddr = sharedEdgeAddrPtr_();
504 sharedEdgeAddr.transfer(dynSharedEdgeAddr);
508 Pout<< "globalMeshData : nGlobalEdges_:" << nGlobalEdges_ << nl
509 << "globalMeshData : sharedEdgeLabels:" << sharedEdgeLabels.size()
511 << "globalMeshData : sharedEdgeAddr:" << sharedEdgeAddr.size()
517 void Foam::globalMeshData::calcGlobalPointSlaves() const
521 Pout<< "globalMeshData::calcGlobalPointSlaves() :"
522 << " calculating coupled master to slave point addressing."
526 // Calculate connected points for master points.
527 globalPoints globalData(mesh_, coupledPatch(), true, true);
529 globalPointSlavesPtr_.reset
533 globalData.pointPoints().xfer()
536 globalPointTransformedSlavesPtr_.reset
540 globalData.transformedPointPoints().xfer()
544 globalPointSlavesMapPtr_.reset
548 globalData.map().xfer()
554 void Foam::globalMeshData::calcPointConnectivity
556 List<labelPairList>& allPointConnectivity
559 const globalIndexAndTransform& transforms = globalTransforms();
560 const labelListList& slaves = globalPointSlaves();
561 const labelListList& transformedSlaves = globalPointTransformedSlaves();
564 // Create field with my local data
565 labelPairList myData(globalPointSlavesMap().constructSize());
566 forAll(slaves, pointI)
568 myData[pointI] = globalIndexAndTransform::encode
572 transforms.nullTransformIndex()
576 globalPointSlavesMap().distribute(myData);
579 // String of connected points with their transform
580 allPointConnectivity.setSize(globalPointSlavesMap().constructSize());
581 forAll(slaves, pointI)
583 // Reconstruct string of connected points
584 const labelList& pSlaves = slaves[pointI];
585 const labelList& pTransformSlaves = transformedSlaves[pointI];
586 labelPairList& pConnectivity = allPointConnectivity[pointI];
587 pConnectivity.setSize(1+pSlaves.size()+pTransformSlaves.size());
591 pConnectivity[connI++] = myData[pointI];
592 // Add untransformed points
595 pConnectivity[connI++] = myData[pSlaves[i]];
597 // Add transformed points.
598 forAll(pTransformSlaves, i)
600 // Get transform from index
601 label transformI = globalPointSlavesMap().whichTransform
605 // Add transform to connectivity
606 const labelPair& n = myData[pTransformSlaves[i]];
607 label procI = globalIndexAndTransform::processor(n);
608 label index = globalIndexAndTransform::index(n);
609 pConnectivity[connI++] = globalIndexAndTransform::encode
620 allPointConnectivity[pSlaves[i]] = pConnectivity;
622 forAll(pTransformSlaves, i)
624 allPointConnectivity[pTransformSlaves[i]] = pConnectivity;
627 globalPointSlavesMap().reverseDistribute
629 allPointConnectivity.size(),
635 void Foam::globalMeshData::calcGlobalPointEdges
637 labelListList& globalPointEdges,
638 List<labelPairList>& globalPointPoints
641 const edgeList& edges = coupledPatch().edges();
642 const labelListList& pointEdges = coupledPatch().pointEdges();
643 const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
644 const labelListList& slaves = globalPointSlaves();
645 const labelListList& transformedSlaves = globalPointTransformedSlaves();
647 // Create local version
648 globalPointEdges.setSize(globalPointSlavesMap().constructSize());
649 globalPointPoints.setSize(globalPointSlavesMap().constructSize());
650 forAll(pointEdges, pointI)
652 const labelList& pEdges = pointEdges[pointI];
653 labelList& globalPEdges = globalPointEdges[pointI];
654 globalPEdges.setSize(pEdges.size());
657 globalPEdges[i] = globalEdgeNumbers.toGlobal(pEdges[i]);
660 labelPairList& globalPPoints = globalPointPoints[pointI];
661 globalPPoints.setSize(pEdges.size());
664 label otherPointI = edges[pEdges[i]].otherVertex(pointI);
665 globalPPoints[i] = globalIndexAndTransform::encode
669 globalTransforms().nullTransformIndex()
674 // Pull slave data to master. Dummy transform.
675 globalPointSlavesMap().distribute(globalPointEdges);
676 globalPointSlavesMap().distribute(globalPointPoints);
677 // Add all pointEdges
678 forAll(slaves, pointI)
680 const labelList& pSlaves = slaves[pointI];
681 const labelList& pTransformSlaves = transformedSlaves[pointI];
686 n += globalPointEdges[pSlaves[i]].size();
688 forAll(pTransformSlaves, i)
690 n += globalPointEdges[pTransformSlaves[i]].size();
693 // Add all the point edges of the slaves to those of the (master) point
695 labelList& globalPEdges = globalPointEdges[pointI];
696 label sz = globalPEdges.size();
697 globalPEdges.setSize(sz+n);
700 const labelList& otherData = globalPointEdges[pSlaves[i]];
703 globalPEdges[sz++] = otherData[j];
706 forAll(pTransformSlaves, i)
708 const labelList& otherData =
709 globalPointEdges[pTransformSlaves[i]];
712 globalPEdges[sz++] = otherData[j];
719 globalPointEdges[pSlaves[i]] = globalPEdges;
721 forAll(pTransformSlaves, i)
723 globalPointEdges[pTransformSlaves[i]] = globalPEdges;
728 // Same for corresponding pointPoints
730 labelPairList& globalPPoints = globalPointPoints[pointI];
731 label sz = globalPPoints.size();
732 globalPPoints.setSize(sz + n);
734 // Add untransformed points
737 const labelPairList& otherData = globalPointPoints[pSlaves[i]];
740 globalPPoints[sz++] = otherData[j];
743 // Add transformed points.
744 forAll(pTransformSlaves, i)
746 // Get transform from index
747 label transformI = globalPointSlavesMap().whichTransform
752 const labelPairList& otherData =
753 globalPointPoints[pTransformSlaves[i]];
756 // Add transform to connectivity
757 const labelPair& n = otherData[j];
758 label procI = globalIndexAndTransform::processor(n);
759 label index = globalIndexAndTransform::index(n);
760 globalPPoints[sz++] = globalIndexAndTransform::encode
772 globalPointPoints[pSlaves[i]] = globalPPoints;
774 forAll(pTransformSlaves, i)
776 globalPointPoints[pTransformSlaves[i]] = globalPPoints;
781 globalPointSlavesMap().reverseDistribute
783 globalPointEdges.size(),
787 globalPointSlavesMap().reverseDistribute
789 globalPointPoints.size(),
795 // Find transformation to take remotePoint to localPoint. Use info to find
797 Foam::label Foam::globalMeshData::findTransform
799 const labelPairList& info,
800 const labelPair& remotePoint,
801 const label localPoint
804 const label remoteProcI = globalIndexAndTransform::processor(remotePoint);
805 const label remoteIndex = globalIndexAndTransform::index(remotePoint);
807 label remoteTransformI = -1;
808 label localTransformI = -1;
811 label procI = globalIndexAndTransform::processor(info[i]);
812 label pointI = globalIndexAndTransform::index(info[i]);
813 label transformI = globalIndexAndTransform::transformIndex(info[i]);
815 if (procI == Pstream::myProcNo() && pointI == localPoint)
817 localTransformI = transformI;
818 //Pout<< "For local :" << localPoint
819 // << " found transform:" << localTransformI
822 if (procI == remoteProcI && pointI == remoteIndex)
824 remoteTransformI = transformI;
825 //Pout<< "For remote:" << remotePoint
826 // << " found transform:" << remoteTransformI
827 // << " at index:" << i
832 if (remoteTransformI == -1 || localTransformI == -1)
834 FatalErrorIn("globalMeshData::findTransform(..)")
835 << "Problem. Cannot find " << remotePoint
836 << " or " << localPoint << " in " << info
838 << "remoteTransformI:" << remoteTransformI << endl
839 << "localTransformI:" << localTransformI
840 << abort(FatalError);
843 return globalTransforms().subtractTransformIndex
851 void Foam::globalMeshData::calcGlobalEdgeSlaves() const
855 Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
856 << " calculating coupled master to slave edge addressing." << endl;
859 const edgeList& edges = coupledPatch().edges();
860 const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
863 // The whole problem with deducting edge-connectivity from
864 // point-connectivity is that one of the the endpoints might be
865 // a local master but the other endpoint might not. So we first
866 // need to make sure that all points know about connectivity and
867 // the transformations.
870 // 1. collect point connectivity - basically recreating globalPoints ouput.
871 // All points will now have a string of points. The transforms are
872 // in respect to the master.
873 List<labelPairList> allPointConnectivity;
874 calcPointConnectivity(allPointConnectivity);
877 // 2. Get all pointEdges and pointPoints
878 // Coupled point to global coupled edges and corresponding endpoint.
879 labelListList globalPointEdges;
880 List<labelPairList> globalPointPoints;
881 calcGlobalPointEdges(globalPointEdges, globalPointPoints);
884 // 3. Now all points have
885 // - all the connected points with original transform
886 // - all the connected global edges
888 // Now all we need to do is go through all the edges and check
889 // both endpoints. If there is a edge between the two which is
890 // produced by transforming both points in the same way it is a shared
893 // Collect strings of connected edges.
894 List<labelPairList> allEdgeConnectivity(edges.size());
898 const edge& e = edges[edgeI];
899 const labelList& pEdges0 = globalPointEdges[e[0]];
900 const labelPairList& pPoints0 = globalPointPoints[e[0]];
901 const labelList& pEdges1 = globalPointEdges[e[1]];
902 const labelPairList& pPoints1 = globalPointPoints[e[1]];
904 // Most edges will be size 2
905 DynamicList<labelPair> eEdges(2);
909 globalIndexAndTransform::encode
913 globalTransforms().nullTransformIndex()
923 pEdges0[i] == pEdges1[j]
924 && pEdges0[i] != globalEdgeNumbers.toGlobal(edgeI)
927 // Found a shared edge. Now check if the endpoints
928 // go through the same transformation.
929 // Local: e[0] remote:pPoints1[j]
930 // Local: e[1] remote:pPoints0[i]
933 // Find difference in transforms to go from point on remote
934 // edge (pPoints1[j]) to this point.
936 label transform0 = findTransform
938 allPointConnectivity[e[0]],
942 label transform1 = findTransform
944 allPointConnectivity[e[1]],
949 if (transform0 == transform1)
951 label procI = globalEdgeNumbers.whichProcID(pEdges0[i]);
954 globalIndexAndTransform::encode
957 globalEdgeNumbers.toLocal(procI, pEdges0[i]),
966 allEdgeConnectivity[edgeI].transfer(eEdges);
967 sort(allEdgeConnectivity[edgeI], globalIndexAndTransform::less());
970 // We now have - in allEdgeConnectivity - a list of edges which are shared
971 // between multiple processors. Filter into non-transformed and transformed
974 globalEdgeSlavesPtr_.reset(new labelListList(edges.size()));
975 labelListList& globalEdgeSlaves = globalEdgeSlavesPtr_();
976 List<labelPairList> transformedEdges(edges.size());
977 forAll(allEdgeConnectivity, edgeI)
979 const labelPairList& edgeInfo = allEdgeConnectivity[edgeI];
980 if (edgeInfo.size() >= 2)
982 const labelPair& masterInfo = edgeInfo[0];
984 // Check if master edge (= first element (since sorted)) is me.
988 globalIndexAndTransform::processor(masterInfo)
989 == Pstream::myProcNo()
991 && (globalIndexAndTransform::index(masterInfo) == edgeI)
994 // Sort into transformed and untransformed
995 labelList& eEdges = globalEdgeSlaves[edgeI];
996 eEdges.setSize(edgeInfo.size()-1);
998 labelPairList& trafoEEdges = transformedEdges[edgeI];
999 trafoEEdges.setSize(edgeInfo.size()-1);
1001 label nonTransformI = 0;
1002 label transformI = 0;
1004 for (label i = 1; i < edgeInfo.size(); i++)
1006 const labelPair& info = edgeInfo[i];
1007 label procI = globalIndexAndTransform::processor(info);
1008 label index = globalIndexAndTransform::index(info);
1009 label transform = globalIndexAndTransform::transformIndex
1014 if (transform == globalTransforms().nullTransformIndex())
1016 eEdges[nonTransformI++] = globalEdgeNumbers.toGlobal
1024 trafoEEdges[transformI++] = info;
1028 eEdges.setSize(nonTransformI);
1029 trafoEEdges.setSize(transformI);
1036 globalEdgeTransformedSlavesPtr_.reset(new labelListList());
1038 List<Map<label> > compactMap(Pstream::nProcs());
1039 globalEdgeSlavesMapPtr_.reset
1048 globalEdgeTransformedSlavesPtr_(),
1057 Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
1058 << " coupled edges:" << edges.size()
1059 << " additional coupled edges:"
1060 << globalEdgeSlavesMapPtr_().constructSize() - edges.size()
1066 // Calculate uncoupled boundary faces (without calculating
1067 // primitiveMesh::pointFaces())
1068 void Foam::globalMeshData::calcPointBoundaryFaces
1070 labelListList& pointBoundaryFaces
1073 const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
1074 const Map<label>& meshPointMap = coupledPatch().meshPointMap();
1078 labelList nPointFaces(coupledPatch().nPoints(), 0);
1080 forAll(bMesh, patchI)
1082 const polyPatch& pp = bMesh[patchI];
1088 const face& f = pp[i];
1092 Map<label>::const_iterator iter = meshPointMap.find
1096 if (iter != meshPointMap.end())
1098 nPointFaces[iter()]++;
1108 pointBoundaryFaces.setSize(coupledPatch().nPoints());
1109 forAll(nPointFaces, pointI)
1111 pointBoundaryFaces[pointI].setSize(nPointFaces[pointI]);
1118 forAll(bMesh, patchI)
1120 const polyPatch& pp = bMesh[patchI];
1126 const face& f = pp[i];
1129 Map<label>::const_iterator iter = meshPointMap.find
1133 if (iter != meshPointMap.end())
1136 pp.start() + i - mesh_.nInternalFaces();
1137 pointBoundaryFaces[iter()][nPointFaces[iter()]++] =
1147 void Foam::globalMeshData::calcGlobalPointBoundaryFaces() const
1151 Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1152 << " calculating coupled point to boundary face addressing."
1156 // Construct local point to (uncoupled)boundaryfaces.
1157 labelListList pointBoundaryFaces;
1158 calcPointBoundaryFaces(pointBoundaryFaces);
1161 // Global indices for boundary faces
1162 globalBoundaryFaceNumberingPtr_.reset
1164 new globalIndex(mesh_.nFaces()-mesh_.nInternalFaces())
1166 globalIndex& globalIndices = globalBoundaryFaceNumberingPtr_();
1169 // Convert local boundary faces to global numbering
1170 globalPointBoundaryFacesPtr_.reset
1172 new labelListList(globalPointSlavesMap().constructSize())
1174 labelListList& globalPointBoundaryFaces = globalPointBoundaryFacesPtr_();
1176 forAll(pointBoundaryFaces, pointI)
1178 const labelList& bFaces = pointBoundaryFaces[pointI];
1179 labelList& globalFaces = globalPointBoundaryFaces[pointI];
1180 globalFaces.setSize(bFaces.size());
1183 globalFaces[i] = globalIndices.toGlobal(bFaces[i]);
1188 // Pull slave pointBoundaryFaces to master
1189 globalPointSlavesMap().distribute
1191 globalPointBoundaryFaces,
1192 true // put data on transformed points into correct slots
1196 // Merge slave labels into master globalPointBoundaryFaces.
1197 // Split into untransformed and transformed values.
1198 const labelListList& pointSlaves = globalPointSlaves();
1199 const labelListList& pointTransformSlaves =
1200 globalPointTransformedSlaves();
1203 // Any faces coming in through transformation
1204 List<labelPairList> transformedFaces(pointSlaves.size());
1207 forAll(pointSlaves, pointI)
1209 const labelList& slaves = pointSlaves[pointI];
1210 const labelList& transformedSlaves = pointTransformSlaves[pointI];
1212 if (slaves.size() > 0)
1214 labelList& myBFaces = globalPointBoundaryFaces[pointI];
1215 label sz = myBFaces.size();
1221 n += globalPointBoundaryFaces[slaves[i]].size();
1224 myBFaces.setSize(sz+n);
1228 const labelList& slaveBFaces =
1229 globalPointBoundaryFaces[slaves[i]];
1231 // Add all slaveBFaces. Note that need to check for
1232 // uniqueness only in case of cyclics.
1234 forAll(slaveBFaces, j)
1236 label slave = slaveBFaces[j];
1237 if (findIndex(SubList<label>(myBFaces, sz), slave) == -1)
1239 myBFaces[n++] = slave;
1243 myBFaces.setSize(n);
1247 if (transformedSlaves.size() > 0)
1249 const labelList& untrafoFaces = globalPointBoundaryFaces[pointI];
1251 labelPairList& myBFaces = transformedFaces[pointI];
1252 label sz = myBFaces.size();
1256 forAll(transformedSlaves, i)
1258 n += globalPointBoundaryFaces[transformedSlaves[i]].size();
1261 myBFaces.setSize(sz+n);
1263 forAll(transformedSlaves, i)
1265 label transformI = globalPointSlavesMap().whichTransform
1267 transformedSlaves[i]
1270 const labelList& slaveBFaces =
1271 globalPointBoundaryFaces[transformedSlaves[i]];
1273 forAll(slaveBFaces, j)
1275 label slave = slaveBFaces[j];
1276 // Check that same face not already present untransformed
1277 if (findIndex(untrafoFaces, slave)== -1)
1279 label procI = globalIndices.whichProcID(slave);
1280 label faceI = globalIndices.toLocal(procI, slave);
1282 myBFaces[n++] = globalIndexAndTransform::encode
1291 myBFaces.setSize(n);
1295 if (slaves.size() + transformedSlaves.size() == 0)
1297 globalPointBoundaryFaces[pointI].clear();
1301 // Construct a map to get the face data directly
1302 List<Map<label> > compactMap(Pstream::nProcs());
1304 globalPointTransformedBoundaryFacesPtr_.reset
1306 new labelListList(transformedFaces.size())
1309 globalPointBoundaryFacesMapPtr_.reset
1314 globalPointBoundaryFaces,
1318 globalPointTransformedBoundaryFacesPtr_(),
1323 globalPointBoundaryFaces.setSize(coupledPatch().nPoints());
1324 globalPointTransformedBoundaryFacesPtr_().setSize(coupledPatch().nPoints());
1328 Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1329 << " coupled points:" << coupledPatch().nPoints()
1330 << " local boundary faces:" << globalIndices.localSize()
1331 << " additional coupled faces:"
1332 << globalPointBoundaryFacesMapPtr_().constructSize()
1333 - globalIndices.localSize()
1339 void Foam::globalMeshData::calcGlobalPointBoundaryCells() const
1343 Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1344 << " calculating coupled point to boundary cell addressing."
1348 // Create map of boundary cells and point-cell addressing
1349 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1352 Map<label> meshCellMap(4*coupledPatch().nPoints());
1353 DynamicList<label> cellMap(meshCellMap.size());
1355 // Create addressing for point to boundary cells (local)
1356 labelListList pointBoundaryCells(coupledPatch().nPoints());
1358 forAll(coupledPatch().meshPoints(), pointI)
1360 label meshPointI = coupledPatch().meshPoints()[pointI];
1361 const labelList& pCells = mesh_.pointCells(meshPointI);
1363 labelList& bCells = pointBoundaryCells[pointI];
1364 bCells.setSize(pCells.size());
1368 label cellI = pCells[i];
1369 Map<label>::iterator fnd = meshCellMap.find(cellI);
1371 if (fnd != meshCellMap.end())
1377 meshCellMap.insert(cellI, bCellI);
1378 cellMap.append(cellI);
1386 boundaryCellsPtr_.reset(new labelList());
1387 labelList& boundaryCells = boundaryCellsPtr_();
1388 boundaryCells.transfer(cellMap.shrink());
1391 // Convert point-cells to global (boundary)cell numbers
1392 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1394 globalBoundaryCellNumberingPtr_.reset
1396 new globalIndex(boundaryCells.size())
1398 globalIndex& globalIndices = globalBoundaryCellNumberingPtr_();
1401 globalPointBoundaryCellsPtr_.reset
1403 new labelListList(globalPointSlavesMap().constructSize())
1405 labelListList& globalPointBoundaryCells = globalPointBoundaryCellsPtr_();
1407 forAll(pointBoundaryCells, pointI)
1409 const labelList& pCells = pointBoundaryCells[pointI];
1410 labelList& globalCells = globalPointBoundaryCells[pointI];
1411 globalCells.setSize(pCells.size());
1414 globalCells[i] = globalIndices.toGlobal(pCells[i]);
1419 // Pull slave pointBoundaryCells to master
1420 globalPointSlavesMap().distribute
1422 globalPointBoundaryCells,
1423 true // put data on transformed points into correct slots
1427 // Merge slave labels into master globalPointBoundaryCells
1428 const labelListList& pointSlaves = globalPointSlaves();
1429 const labelListList& pointTransformSlaves =
1430 globalPointTransformedSlaves();
1432 List<labelPairList> transformedCells(pointSlaves.size());
1435 forAll(pointSlaves, pointI)
1437 const labelList& slaves = pointSlaves[pointI];
1438 const labelList& transformedSlaves = pointTransformSlaves[pointI];
1440 if (slaves.size() > 0)
1442 labelList& myBCells = globalPointBoundaryCells[pointI];
1443 label sz = myBCells.size();
1449 n += globalPointBoundaryCells[slaves[i]].size();
1452 myBCells.setSize(sz+n);
1456 const labelList& slaveBCells =
1457 globalPointBoundaryCells[slaves[i]];
1459 // Add all slaveBCells. Note that need to check for
1460 // uniqueness only in case of cyclics.
1462 forAll(slaveBCells, j)
1464 label slave = slaveBCells[j];
1465 if (findIndex(SubList<label>(myBCells, sz), slave) == -1)
1467 myBCells[n++] = slave;
1471 myBCells.setSize(n);
1475 if (transformedSlaves.size() > 0)
1477 const labelList& untrafoCells = globalPointBoundaryCells[pointI];
1479 labelPairList& myBCells = transformedCells[pointI];
1480 label sz = myBCells.size();
1484 forAll(transformedSlaves, i)
1486 n += globalPointBoundaryCells[transformedSlaves[i]].size();
1489 myBCells.setSize(sz+n);
1491 forAll(transformedSlaves, i)
1493 label transformI = globalPointSlavesMap().whichTransform
1495 transformedSlaves[i]
1498 const labelList& slaveBCells =
1499 globalPointBoundaryCells[transformedSlaves[i]];
1501 forAll(slaveBCells, j)
1503 label slave = slaveBCells[j];
1505 // Check that same cell not already present untransformed
1506 if (findIndex(untrafoCells, slave)== -1)
1508 label procI = globalIndices.whichProcID(slave);
1509 label cellI = globalIndices.toLocal(procI, slave);
1510 myBCells[n++] = globalIndexAndTransform::encode
1519 myBCells.setSize(n);
1522 if (slaves.size() + transformedSlaves.size() == 0)
1524 globalPointBoundaryCells[pointI].clear();
1528 // Construct a map to get the cell data directly
1529 List<Map<label> > compactMap(Pstream::nProcs());
1531 globalPointTransformedBoundaryCellsPtr_.reset
1533 new labelListList(transformedCells.size())
1536 globalPointBoundaryCellsMapPtr_.reset
1541 globalPointBoundaryCells,
1545 globalPointTransformedBoundaryCellsPtr_(),
1550 globalPointBoundaryCells.setSize(coupledPatch().nPoints());
1551 globalPointTransformedBoundaryCellsPtr_().setSize(coupledPatch().nPoints());
1555 Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1556 << " coupled points:" << coupledPatch().nPoints()
1557 << " local boundary cells:" << globalIndices.localSize()
1558 << " additional coupled cells:"
1559 << globalPointBoundaryCellsMapPtr_().constructSize()
1560 - globalIndices.localSize()
1566 void Foam::globalMeshData::calcGlobalCoPointSlaves() const
1570 Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1571 << " calculating coupled master to collocated"
1572 << " slave point addressing." << endl;
1575 // Calculate connected points for master points.
1576 globalPoints globalData(mesh_, coupledPatch(), true, false);
1578 globalCoPointSlavesPtr_.reset
1582 globalData.pointPoints().xfer()
1585 globalCoPointSlavesMapPtr_.reset
1589 globalData.map().xfer()
1595 Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1596 << " finished calculating coupled master to collocated"
1597 << " slave point addressing." << endl;
1602 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1604 // Construct from polyMesh
1605 Foam::globalMeshData::globalMeshData(const polyMesh& mesh)
1607 processorTopology(mesh.boundaryMesh()),
1612 processorPatches_(0),
1613 processorPatchIndices_(0),
1614 processorPatchNeighbours_(0),
1616 sharedPointLabelsPtr_(NULL),
1617 sharedPointAddrPtr_(NULL),
1618 sharedPointGlobalLabelsPtr_(NULL),
1620 sharedEdgeLabelsPtr_(NULL),
1621 sharedEdgeAddrPtr_(NULL)
1627 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1629 Foam::globalMeshData::~globalMeshData()
1635 void Foam::globalMeshData::clearOut()
1638 nGlobalPoints_ = -1;
1639 sharedPointLabelsPtr_.clear();
1640 sharedPointAddrPtr_.clear();
1641 sharedPointGlobalLabelsPtr_.clear();
1645 sharedEdgeLabelsPtr_.clear();
1646 sharedEdgeAddrPtr_.clear();
1649 coupledPatchPtr_.clear();
1650 coupledPatchMeshEdgesPtr_.clear();
1651 coupledPatchMeshEdgeMapPtr_.clear();
1652 globalTransformsPtr_.clear();
1655 globalPointNumberingPtr_.clear();
1656 globalPointSlavesPtr_.clear();
1657 globalPointTransformedSlavesPtr_.clear();
1658 globalPointSlavesMapPtr_.clear();
1660 globalEdgeNumberingPtr_.clear();
1661 globalEdgeSlavesPtr_.clear();
1662 globalEdgeTransformedSlavesPtr_.clear();
1663 globalEdgeSlavesMapPtr_.clear();
1666 globalBoundaryFaceNumberingPtr_.clear();
1667 globalPointBoundaryFacesPtr_.clear();
1668 globalPointTransformedBoundaryFacesPtr_.clear();
1669 globalPointBoundaryFacesMapPtr_.clear();
1672 boundaryCellsPtr_.clear();
1673 globalBoundaryCellNumberingPtr_.clear();
1674 globalPointBoundaryCellsPtr_.clear();
1675 globalPointTransformedBoundaryCellsPtr_.clear();
1676 globalPointBoundaryCellsMapPtr_.clear();
1678 // Other: collocated points
1679 globalCoPointSlavesPtr_.clear();
1680 globalCoPointSlavesMapPtr_.clear();
1684 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1686 // Return shared point global labels.
1687 const Foam::labelList& Foam::globalMeshData::sharedPointGlobalLabels() const
1689 if (!sharedPointGlobalLabelsPtr_.valid())
1691 sharedPointGlobalLabelsPtr_.reset
1693 new labelList(sharedPointLabels().size())
1695 labelList& sharedPointGlobalLabels = sharedPointGlobalLabelsPtr_();
1699 "pointProcAddressing",
1700 mesh_.facesInstance()/mesh_.meshSubDir,
1705 if (addrHeader.headerOk())
1707 // There is a pointProcAddressing file so use it to get labels
1708 // on the original mesh
1709 Pout<< "globalMeshData::sharedPointGlobalLabels : "
1710 << "Reading pointProcAddressing" << endl;
1712 labelIOList pointProcAddressing(addrHeader);
1714 const labelList& pointLabels = sharedPointLabels();
1716 forAll(pointLabels, i)
1718 // Get my mesh point
1719 label pointI = pointLabels[i];
1721 // Map to mesh point of original mesh
1722 sharedPointGlobalLabels[i] = pointProcAddressing[pointI];
1727 Pout<< "globalMeshData::sharedPointGlobalLabels :"
1728 << " Setting pointProcAddressing to -1" << endl;
1730 sharedPointGlobalLabels = -1;
1733 return sharedPointGlobalLabelsPtr_();
1737 // Collect coordinates of shared points. (does parallel communication!)
1738 Foam::pointField Foam::globalMeshData::sharedPoints() const
1740 // Get all processors to send their shared points to master.
1741 // (not very efficient)
1743 pointField sharedPoints(nGlobalPoints());
1744 const labelList& pointAddr = sharedPointAddr();
1745 const labelList& pointLabels = sharedPointLabels();
1747 if (Pstream::master())
1750 // insert my own data first
1751 forAll(pointLabels, i)
1753 label sharedPointI = pointAddr[i];
1755 sharedPoints[sharedPointI] = mesh_.points()[pointLabels[i]];
1758 // Receive data from slaves and insert
1761 int slave=Pstream::firstSlave();
1762 slave<=Pstream::lastSlave();
1766 IPstream fromSlave(Pstream::blocking, slave);
1768 labelList nbrSharedPointAddr;
1769 pointField nbrSharedPoints;
1770 fromSlave >> nbrSharedPointAddr >> nbrSharedPoints;
1772 forAll(nbrSharedPointAddr, i)
1774 label sharedPointI = nbrSharedPointAddr[i];
1776 sharedPoints[sharedPointI] = nbrSharedPoints[i];
1783 int slave=Pstream::firstSlave();
1784 slave<=Pstream::lastSlave();
1792 sharedPoints.size()*sizeof(vector::zero)
1794 toSlave << sharedPoints;
1802 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
1806 << UIndirectList<point>(mesh_.points(), pointLabels)();
1809 // Receive sharedPoints
1811 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
1812 fromMaster >> sharedPoints;
1816 return sharedPoints;
1820 // Collect coordinates of shared points. (does parallel communication!)
1821 Foam::pointField Foam::globalMeshData::geometricSharedPoints() const
1823 // Get coords of my shared points
1824 pointField sharedPoints(mesh_.points(), sharedPointLabels());
1826 // Append from all processors
1827 combineReduce(sharedPoints, plusEqOp<pointField>());
1830 scalar tolDim = matchTol_ * mesh_.bounds().mag();
1832 // And see how many are unique
1834 pointField mergedPoints;
1838 sharedPoints, // coordinates to merge
1839 tolDim, // tolerance
1845 return mergedPoints;
1849 Foam::label Foam::globalMeshData::nGlobalPoints() const
1851 if (nGlobalPoints_ == -1)
1855 return nGlobalPoints_;
1859 const Foam::labelList& Foam::globalMeshData::sharedPointLabels() const
1861 if (!sharedPointLabelsPtr_.valid())
1865 return sharedPointLabelsPtr_();
1869 const Foam::labelList& Foam::globalMeshData::sharedPointAddr() const
1871 if (!sharedPointAddrPtr_.valid())
1875 return sharedPointAddrPtr_();
1879 Foam::label Foam::globalMeshData::nGlobalEdges() const
1881 if (nGlobalEdges_ == -1)
1885 return nGlobalEdges_;
1889 const Foam::labelList& Foam::globalMeshData::sharedEdgeLabels() const
1891 if (!sharedEdgeLabelsPtr_.valid())
1895 return sharedEdgeLabelsPtr_();
1899 const Foam::labelList& Foam::globalMeshData::sharedEdgeAddr() const
1901 if (!sharedEdgeAddrPtr_.valid())
1905 return sharedEdgeAddrPtr_();
1909 const Foam::indirectPrimitivePatch& Foam::globalMeshData::coupledPatch() const
1911 if (!coupledPatchPtr_.valid())
1913 const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
1917 forAll(bMesh, patchI)
1919 const polyPatch& pp = bMesh[patchI];
1923 nCoupled += pp.size();
1926 labelList coupledFaces(nCoupled);
1929 forAll(bMesh, patchI)
1931 const polyPatch& pp = bMesh[patchI];
1935 label faceI = pp.start();
1939 coupledFaces[nCoupled++] = faceI++;
1944 coupledPatchPtr_.reset
1946 new indirectPrimitivePatch
1959 Pout<< "globalMeshData::coupledPatch() :"
1960 << " constructed coupled faces patch:"
1961 << " faces:" << coupledPatchPtr_().size()
1962 << " points:" << coupledPatchPtr_().nPoints()
1966 return coupledPatchPtr_();
1970 const Foam::labelList& Foam::globalMeshData::coupledPatchMeshEdges() const
1972 if (!coupledPatchMeshEdgesPtr_.valid())
1974 coupledPatchMeshEdgesPtr_.reset
1978 coupledPatch().meshEdges
1986 return coupledPatchMeshEdgesPtr_();
1990 const Foam::Map<Foam::label>& Foam::globalMeshData::coupledPatchMeshEdgeMap()
1993 if (!coupledPatchMeshEdgeMapPtr_.valid())
1995 const labelList& me = coupledPatchMeshEdges();
1997 coupledPatchMeshEdgeMapPtr_.reset(new Map<label>(2*me.size()));
1998 Map<label>& em = coupledPatchMeshEdgeMapPtr_();
2002 em.insert(me[i], i);
2005 return coupledPatchMeshEdgeMapPtr_();
2009 const Foam::globalIndex& Foam::globalMeshData::globalPointNumbering() const
2011 if (!globalPointNumberingPtr_.valid())
2013 globalPointNumberingPtr_.reset
2015 new globalIndex(coupledPatch().nPoints())
2018 return globalPointNumberingPtr_();
2022 const Foam::globalIndexAndTransform&
2023 Foam::globalMeshData::globalTransforms() const
2025 if (!globalTransformsPtr_.valid())
2027 globalTransformsPtr_.reset(new globalIndexAndTransform(mesh_));
2029 return globalTransformsPtr_();
2033 const Foam::labelListList& Foam::globalMeshData::globalPointSlaves() const
2035 if (!globalPointSlavesPtr_.valid())
2037 calcGlobalPointSlaves();
2039 return globalPointSlavesPtr_();
2043 const Foam::labelListList& Foam::globalMeshData::globalPointTransformedSlaves()
2046 if (!globalPointTransformedSlavesPtr_.valid())
2048 calcGlobalPointSlaves();
2050 return globalPointTransformedSlavesPtr_();
2054 const Foam::mapDistribute& Foam::globalMeshData::globalPointSlavesMap() const
2056 if (!globalPointSlavesMapPtr_.valid())
2058 calcGlobalPointSlaves();
2060 return globalPointSlavesMapPtr_();
2064 const Foam::globalIndex& Foam::globalMeshData::globalEdgeNumbering() const
2066 if (!globalEdgeNumberingPtr_.valid())
2068 globalEdgeNumberingPtr_.reset
2070 new globalIndex(coupledPatch().nEdges())
2073 return globalEdgeNumberingPtr_();
2077 const Foam::labelListList& Foam::globalMeshData::globalEdgeSlaves() const
2079 if (!globalEdgeSlavesPtr_.valid())
2081 calcGlobalEdgeSlaves();
2083 return globalEdgeSlavesPtr_();
2087 const Foam::labelListList& Foam::globalMeshData::globalEdgeTransformedSlaves()
2090 if (!globalEdgeTransformedSlavesPtr_.valid())
2092 calcGlobalEdgeSlaves();
2094 return globalEdgeTransformedSlavesPtr_();
2098 const Foam::mapDistribute& Foam::globalMeshData::globalEdgeSlavesMap() const
2100 if (!globalEdgeSlavesMapPtr_.valid())
2102 calcGlobalEdgeSlaves();
2104 return globalEdgeSlavesMapPtr_();
2108 const Foam::globalIndex& Foam::globalMeshData::globalBoundaryFaceNumbering()
2111 if (!globalBoundaryFaceNumberingPtr_.valid())
2113 calcGlobalPointBoundaryFaces();
2115 return globalBoundaryFaceNumberingPtr_();
2119 const Foam::labelListList& Foam::globalMeshData::globalPointBoundaryFaces()
2122 if (!globalPointBoundaryFacesPtr_.valid())
2124 calcGlobalPointBoundaryFaces();
2126 return globalPointBoundaryFacesPtr_();
2130 const Foam::labelListList&
2131 Foam::globalMeshData::globalPointTransformedBoundaryFaces() const
2133 if (!globalPointTransformedBoundaryFacesPtr_.valid())
2135 calcGlobalPointBoundaryFaces();
2137 return globalPointTransformedBoundaryFacesPtr_();
2141 const Foam::mapDistribute& Foam::globalMeshData::globalPointBoundaryFacesMap()
2144 if (!globalPointBoundaryFacesMapPtr_.valid())
2146 calcGlobalPointBoundaryFaces();
2148 return globalPointBoundaryFacesMapPtr_();
2152 const Foam::labelList& Foam::globalMeshData::boundaryCells() const
2154 if (!boundaryCellsPtr_.valid())
2156 calcGlobalPointBoundaryCells();
2158 return boundaryCellsPtr_();
2162 const Foam::globalIndex& Foam::globalMeshData::globalBoundaryCellNumbering()
2165 if (!globalBoundaryCellNumberingPtr_.valid())
2167 calcGlobalPointBoundaryCells();
2169 return globalBoundaryCellNumberingPtr_();
2173 const Foam::labelListList& Foam::globalMeshData::globalPointBoundaryCells()
2176 if (!globalPointBoundaryCellsPtr_.valid())
2178 calcGlobalPointBoundaryCells();
2180 return globalPointBoundaryCellsPtr_();
2184 const Foam::labelListList&
2185 Foam::globalMeshData::globalPointTransformedBoundaryCells() const
2187 if (!globalPointTransformedBoundaryCellsPtr_.valid())
2189 calcGlobalPointBoundaryCells();
2191 return globalPointTransformedBoundaryCellsPtr_();
2195 const Foam::mapDistribute& Foam::globalMeshData::globalPointBoundaryCellsMap()
2198 if (!globalPointBoundaryCellsMapPtr_.valid())
2200 calcGlobalPointBoundaryCells();
2202 return globalPointBoundaryCellsMapPtr_();
2206 const Foam::labelListList& Foam::globalMeshData::globalCoPointSlaves() const
2208 if (!globalCoPointSlavesPtr_.valid())
2210 calcGlobalCoPointSlaves();
2212 return globalCoPointSlavesPtr_();
2216 const Foam::mapDistribute& Foam::globalMeshData::globalCoPointSlavesMap() const
2218 if (!globalCoPointSlavesMapPtr_.valid())
2220 calcGlobalCoPointSlaves();
2222 return globalCoPointSlavesMapPtr_();
2226 Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
2228 labelList& pointToGlobal,
2229 labelList& uniquePoints
2232 const indirectPrimitivePatch& cpp = coupledPatch();
2233 const globalIndex& globalCoupledPoints = globalPointNumbering();
2234 // Use collocated only
2235 const labelListList& pointSlaves = globalCoPointSlaves();
2236 const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2239 // Points are either
2240 // - master with slaves
2241 // - slave with a master
2242 // - other (since e.g. non-collocated cyclics not connected)
2244 labelList masterGlobalPoint(cpp.nPoints(), -1);
2245 forAll(masterGlobalPoint, pointI)
2247 const labelList& slavePoints = pointSlaves[pointI];
2248 if (slavePoints.size() > 0)
2250 masterGlobalPoint[pointI] = globalCoupledPoints.toGlobal(pointI);
2254 // Sync by taking max
2259 labelListList(cpp.nPoints()), // no transforms
2265 // 1. Count number of masters on my processor.
2267 PackedBoolList isMaster(mesh_.nPoints(), 1);
2268 forAll(pointSlaves, pointI)
2270 if (masterGlobalPoint[pointI] == -1)
2272 // unconnected point (e.g. from separated cyclic)
2277 masterGlobalPoint[pointI]
2278 == globalCoupledPoints.toGlobal(pointI)
2286 // connected slave point
2287 isMaster[cpp.meshPoints()[pointI]] = 0;
2291 label myUniquePoints = mesh_.nPoints() - cpp.nPoints() + nMaster;
2293 //Pout<< "Points :" << nl
2294 // << " mesh : " << mesh_.nPoints() << nl
2295 // << " of which coupled : " << cpp.nPoints() << nl
2296 // << " of which master : " << nMaster << nl
2300 // 2. Create global indexing for unique points.
2301 autoPtr<globalIndex> globalPointsPtr(new globalIndex(myUniquePoints));
2304 // 3. Assign global point numbers. Keep slaves unset.
2305 pointToGlobal.setSize(mesh_.nPoints());
2307 uniquePoints.setSize(myUniquePoints);
2310 forAll(isMaster, meshPointI)
2312 if (isMaster[meshPointI])
2314 pointToGlobal[meshPointI] = globalPointsPtr().toGlobal(nMaster);
2315 uniquePoints[nMaster] = meshPointI;
2321 // 4. Push global index for coupled points to slaves.
2323 labelList masterToGlobal(pointSlavesMap.constructSize(), -1);
2325 forAll(pointSlaves, pointI)
2327 const labelList& slaves = pointSlaves[pointI];
2329 if (slaves.size() > 0)
2331 // Duplicate master globalpoint into slave slots
2332 label meshPointI = cpp.meshPoints()[pointI];
2333 masterToGlobal[pointI] = pointToGlobal[meshPointI];
2336 masterToGlobal[slaves[i]] = masterToGlobal[pointI];
2342 pointSlavesMap.reverseDistribute(cpp.nPoints(), masterToGlobal);
2344 // On slave copy master index into overal map.
2345 forAll(pointSlaves, pointI)
2347 label meshPointI = cpp.meshPoints()[pointI];
2349 if (!isMaster[meshPointI])
2351 pointToGlobal[meshPointI] = masterToGlobal[pointI];
2356 return globalPointsPtr;
2360 Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
2362 const labelList& meshPoints,
2363 const Map<label>& meshPointMap,
2364 labelList& pointToGlobal,
2365 labelList& uniqueMeshPoints
2368 const indirectPrimitivePatch& cpp = coupledPatch();
2369 const labelListList& pointSlaves = globalCoPointSlaves();
2370 const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2373 // The patch points come in two variants:
2374 // - not on a coupled patch so guaranteed unique
2375 // - on a coupled patch
2376 // If the point is on a coupled patch the problem is that the
2377 // master-slave structure (globalPointSlaves etc.) assigns one of the
2378 // coupled points to be the master but this master point is not
2379 // necessarily on the patch itself! (it might just be connected to the
2380 // patch point via coupled patches).
2383 // Determine mapping:
2384 // - from patch point to coupled point (or -1)
2385 // - from coupled point to global patch point
2386 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2388 globalIndex globalPPoints(meshPoints.size());
2390 labelList patchToCoupled(meshPoints.size(), -1);
2392 labelList coupledToGlobalPatch(pointSlavesMap.constructSize(), -1);
2394 // Note: loop over patch since usually smaller
2395 forAll(meshPoints, patchPointI)
2397 label meshPointI = meshPoints[patchPointI];
2399 Map<label>::const_iterator iter = cpp.meshPointMap().find(meshPointI);
2401 if (iter != cpp.meshPointMap().end())
2403 patchToCoupled[patchPointI] = iter();
2404 coupledToGlobalPatch[iter()] = globalPPoints.toGlobal(patchPointI);
2409 //Pout<< "Patch:" << nl
2410 // << " points:" << meshPoints.size() << nl
2411 // << " of which on coupled patch:" << nCoupled << endl;
2414 // Determine master of connected points
2415 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2416 // Problem is that the coupled master might not be on the patch. So
2417 // work out the best patch-point master from all connected points.
2418 // - if the coupled master is on the patch it becomes the patch-point master
2419 // - else the slave with the lowest numbered patch point label
2421 // Get all data on master
2422 pointSlavesMap.distribute(coupledToGlobalPatch);
2423 forAll(pointSlaves, coupledPointI)
2425 const labelList& slaves = pointSlaves[coupledPointI];
2427 if (slaves.size() > 0)
2429 // I am master. What is the best candidate for patch-point master
2430 label masterI = labelMax;
2431 if (coupledToGlobalPatch[coupledPointI] != -1)
2433 // I am master and on the coupled patch. Use me.
2434 masterI = coupledToGlobalPatch[coupledPointI];
2438 // Get min of slaves as master.
2441 label slavePp = coupledToGlobalPatch[slaves[i]];
2442 if (slavePp != -1 && slavePp < masterI)
2449 if (masterI != labelMax)
2452 coupledToGlobalPatch[coupledPointI] = masterI;
2455 coupledToGlobalPatch[slaves[i]] = masterI;
2460 pointSlavesMap.reverseDistribute(cpp.nPoints(), coupledToGlobalPatch);
2463 // Generate compact numbering for master points
2464 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2465 // Now coupledToGlobalPatch is the globalIndex of the master point.
2466 // Now every processor can check whether they hold it and generate a
2467 // compact numbering.
2470 forAll(meshPoints, patchPointI)
2472 if (patchToCoupled[patchPointI] == -1)
2478 label coupledPointI = patchToCoupled[patchPointI];
2481 globalPPoints.toGlobal(patchPointI)
2482 == coupledToGlobalPatch[coupledPointI]
2491 autoPtr<globalIndex> globalPointsPtr(new globalIndex(nMasters));
2493 //Pout<< "Patch:" << nl
2494 // << " points:" << meshPoints.size() << nl
2495 // << " of which on coupled patch:" << nCoupled << nl
2496 // << " of which master:" << nMasters << endl;
2500 // Push back compact numbering for master point onto slaves
2501 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2503 pointToGlobal.setSize(meshPoints.size());
2505 uniqueMeshPoints.setSize(nMasters);
2507 // Sync master in global point numbering so all know the master point.
2508 // Initialise globalMaster to be -1 except at a globalMaster.
2509 labelList globalMaster(cpp.nPoints(), -1);
2512 forAll(meshPoints, patchPointI)
2514 if (patchToCoupled[patchPointI] == -1)
2516 uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
2520 label coupledPointI = patchToCoupled[patchPointI];
2523 globalPPoints.toGlobal(patchPointI)
2524 == coupledToGlobalPatch[coupledPointI]
2527 globalMaster[coupledPointI] =
2528 globalPointsPtr().toGlobal(nMasters);
2529 uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
2535 // Sync by taking max
2540 labelListList(cpp.nPoints()), // no transforms
2546 // Now everyone has the master point in globalPointsPtr numbering. Fill
2547 // in the pointToGlobal map.
2549 forAll(meshPoints, patchPointI)
2551 if (patchToCoupled[patchPointI] == -1)
2553 pointToGlobal[patchPointI] = globalPointsPtr().toGlobal(nMasters++);
2557 label coupledPointI = patchToCoupled[patchPointI];
2558 pointToGlobal[patchPointI] = globalMaster[coupledPointI];
2562 globalPPoints.toGlobal(patchPointI)
2563 == coupledToGlobalPatch[coupledPointI]
2571 return globalPointsPtr;
2575 void Foam::globalMeshData::movePoints(const pointField& newPoints)
2577 // Topology does not change and we don't store any geometry so nothing
2578 // needs to be done.
2579 // Only global transformations might change but this is not really
2584 // Update all data after morph
2585 void Foam::globalMeshData::updateMesh()
2587 // Clear out old data
2590 // Do processor patch addressing
2593 scalar tolDim = matchTol_ * mesh_.bounds().mag();
2597 Pout<< "globalMeshData : merge dist:" << tolDim << endl;
2600 // Total number of faces.
2601 nTotalFaces_ = returnReduce(mesh_.nFaces(), sumOp<label>());
2605 Pout<< "globalMeshData : nTotalFaces_:" << nTotalFaces_ << endl;
2608 nTotalCells_ = returnReduce(mesh_.nCells(), sumOp<label>());
2612 Pout<< "globalMeshData : nTotalCells_:" << nTotalCells_ << endl;
2615 nTotalPoints_ = returnReduce(mesh_.nPoints(), sumOp<label>());
2619 Pout<< "globalMeshData : nTotalPoints_:" << nTotalPoints_ << endl;
2624 // ************************************************************************* //