1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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;
52 class minEqOp<labelPair>
55 void operator()(labelPair& x, const labelPair& y) const
57 x[0] = min(x[0], y[0]);
58 x[1] = min(x[1], y[1]);
64 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
66 // Collect processor patch addressing.
67 void Foam::globalMeshData::initProcAddr()
69 processorPatchIndices_.setSize(mesh_.boundaryMesh().size());
70 processorPatchIndices_ = -1;
72 processorPatchNeighbours_.setSize(mesh_.boundaryMesh().size());
73 processorPatchNeighbours_ = -1;
75 // Construct processor patch indexing. processorPatchNeighbours_ only
76 // set if running in parallel!
77 processorPatches_.setSize(mesh_.boundaryMesh().size());
79 label nNeighbours = 0;
81 forAll(mesh_.boundaryMesh(), patchi)
83 if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
85 processorPatches_[nNeighbours] = patchi;
86 processorPatchIndices_[patchi] = nNeighbours++;
89 processorPatches_.setSize(nNeighbours);
92 if (Pstream::parRun())
94 PstreamBuffers pBufs(Pstream::nonBlocking);
96 // Send indices of my processor patches to my neighbours
97 forAll(processorPatches_, i)
99 label patchi = processorPatches_[i];
101 UOPstream toNeighbour
103 refCast<const processorPolyPatch>
105 mesh_.boundaryMesh()[patchi]
110 toNeighbour << processorPatchIndices_[patchi];
113 pBufs.finishedSends();
115 forAll(processorPatches_, i)
117 label patchi = processorPatches_[i];
119 UIPstream fromNeighbour
121 refCast<const processorPolyPatch>
123 mesh_.boundaryMesh()[patchi]
128 fromNeighbour >> processorPatchNeighbours_[patchi];
134 void Foam::globalMeshData::calcSharedPoints() const
139 || sharedPointLabelsPtr_.valid()
140 || sharedPointAddrPtr_.valid()
143 FatalErrorIn("globalMeshData::calcSharedPoints()")
144 << "Shared point addressing already done" << abort(FatalError);
147 // Calculate all shared points (exclude points that are only
148 // on two coupled patches). This does all the hard work.
149 globalPoints parallelPoints(mesh_, false, true);
151 // Count the number of master points
153 forAll(parallelPoints.pointPoints(), i)
155 const labelList& pPoints = parallelPoints.pointPoints()[i];
156 const labelList& transPPoints =
157 parallelPoints.transformedPointPoints()[i];
159 if (pPoints.size()+transPPoints.size() > 0)
165 // Allocate global numbers
166 globalIndex masterNumbering(nMaster);
168 nGlobalPoints_ = masterNumbering.size();
171 // Push master number to slaves
172 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173 // 1. Fill master and slave slots
175 labelList master(parallelPoints.map().constructSize(), -1);
176 forAll(parallelPoints.pointPoints(), i)
178 const labelList& pPoints = parallelPoints.pointPoints()[i];
179 const labelList& transPPoints =
180 parallelPoints.transformedPointPoints()[i];
182 if (pPoints.size()+transPPoints.size() > 0)
184 master[i] = masterNumbering.toGlobal(nMaster);
187 master[pPoints[j]] = master[i];
189 forAll(transPPoints, j)
191 master[transPPoints[j]] = master[i];
198 // 2. Push slave slots back to local storage on originating processor
199 // For all the four types of points:
200 // - local master : already set
201 // - local transformed slave point : the reverse transform at
202 // reverseDistribute will have copied it back to its originating local
204 // - remote untransformed slave point : sent back to originating processor
205 // - remote transformed slave point : the reverse transform will
206 // copy it back into the remote slot which then gets sent back to
207 // originating processor
209 parallelPoints.map().reverseDistribute
211 parallelPoints.map().constructSize(),
216 // Collect all points that are a master or refer to a master.
218 forAll(parallelPoints.pointPoints(), i)
226 sharedPointLabelsPtr_.reset(new labelList(nMaster));
227 labelList& sharedPointLabels = sharedPointLabelsPtr_();
228 sharedPointAddrPtr_.reset(new labelList(nMaster));
229 labelList& sharedPointAddr = sharedPointAddrPtr_();
232 forAll(parallelPoints.pointPoints(), i)
236 // I am master or slave
237 sharedPointLabels[nMaster] = i;
238 sharedPointAddr[nMaster] = master[i];
245 Pout<< "globalMeshData : nGlobalPoints_:" << nGlobalPoints_ << nl
246 << "globalMeshData : sharedPointLabels_:"
247 << sharedPointLabelsPtr_().size() << nl
248 << "globalMeshData : sharedPointAddr_:"
249 << sharedPointAddrPtr_().size() << endl;
254 // Given information about locally used edges allocate global shared edges.
255 void Foam::globalMeshData::countSharedEdges
257 const EdgeMap<labelList>& procSharedEdges,
258 EdgeMap<label>& globalShared,
262 // Count occurrences of procSharedEdges in global shared edges table.
263 forAllConstIter(EdgeMap<labelList>, procSharedEdges, iter)
265 const edge& e = iter.key();
267 EdgeMap<label>::iterator globalFnd = globalShared.find(e);
269 if (globalFnd == globalShared.end())
271 // First time occurrence of this edge. Check how many we are adding.
272 if (iter().size() == 1)
274 // Only one edge. Mark with special value.
275 globalShared.insert(e, -1);
279 // Edge used more than once (even by local shared edges alone)
280 // so allocate proper shared edge label.
281 globalShared.insert(e, sharedEdgeI++);
286 if (globalFnd() == -1)
288 // Second time occurence of this edge. Assign proper
290 globalFnd() = sharedEdgeI++;
297 // Shared edges are shared between multiple processors. By their nature both
298 // of their endpoints are shared points. (but not all edges using two shared
299 // points are shared edges! There might e.g. be an edge between two unrelated
300 // clusters of shared points)
301 void Foam::globalMeshData::calcSharedEdges() const
306 || sharedEdgeLabelsPtr_.valid()
307 || sharedEdgeAddrPtr_.valid()
310 FatalErrorIn("globalMeshData::calcSharedEdges()")
311 << "Shared edge addressing already done" << abort(FatalError);
315 const labelList& sharedPtAddr = sharedPointAddr();
316 const labelList& sharedPtLabels = sharedPointLabels();
318 // Since don't want to construct pointEdges for whole mesh create
319 // Map for all shared points.
320 Map<label> meshToShared(2*sharedPtLabels.size());
321 forAll(sharedPtLabels, i)
323 meshToShared.insert(sharedPtLabels[i], i);
326 // Find edges using shared points. Store correspondence to local edge
327 // numbering. Note that multiple local edges can have the same shared
328 // points! (for cyclics or separated processor patches)
329 EdgeMap<labelList> localShared(2*sharedPtAddr.size());
331 const edgeList& edges = mesh_.edges();
335 const edge& e = edges[edgeI];
337 Map<label>::const_iterator e0Fnd = meshToShared.find(e[0]);
339 if (e0Fnd != meshToShared.end())
341 Map<label>::const_iterator e1Fnd = meshToShared.find(e[1]);
343 if (e1Fnd != meshToShared.end())
345 // Found edge which uses shared points. Probably shared.
347 // Construct the edge in shared points (or rather global indices
348 // of the shared points)
351 sharedPtAddr[e0Fnd()],
352 sharedPtAddr[e1Fnd()]
355 EdgeMap<labelList>::iterator iter =
356 localShared.find(sharedEdge);
358 if (iter == localShared.end())
360 // First occurrence of this point combination. Store.
361 localShared.insert(sharedEdge, labelList(1, edgeI));
365 // Add this edge to list of edge labels.
366 labelList& edgeLabels = iter();
368 label sz = edgeLabels.size();
369 edgeLabels.setSize(sz+1);
370 edgeLabels[sz] = edgeI;
377 // Now we have a table on every processors which gives its edges which use
378 // shared points. Send this all to the master and have it allocate
379 // global edge numbers for it. But only allocate a global edge number for
380 // edge if it is used more than once!
381 // Note that we are now sending the whole localShared to the master whereas
382 // we only need the local count (i.e. the number of times a global edge is
383 // used). But then this only gets done once so not too bothered about the
384 // extra global communication.
386 EdgeMap<label> globalShared(nGlobalPoints());
388 if (Pstream::master())
390 label sharedEdgeI = 0;
392 // Merge my shared edges into the global list
395 Pout<< "globalMeshData::calcSharedEdges : Merging in from proc0 : "
396 << localShared.size() << endl;
398 countSharedEdges(localShared, globalShared, sharedEdgeI);
400 // Receive data from slaves and insert
401 if (Pstream::parRun())
405 int slave=Pstream::firstSlave();
406 slave<=Pstream::lastSlave();
410 // Receive the edges using shared points from the slave.
411 IPstream fromSlave(Pstream::blocking, slave);
412 EdgeMap<labelList> procSharedEdges(fromSlave);
416 Pout<< "globalMeshData::calcSharedEdges : "
417 << "Merging in from proc"
418 << Foam::name(slave) << " : " << procSharedEdges.size()
421 countSharedEdges(procSharedEdges, globalShared, sharedEdgeI);
425 // Now our globalShared should have some edges with -1 as edge label
426 // These were only used once so are not proper shared edges.
429 EdgeMap<label> oldSharedEdges(globalShared);
431 globalShared.clear();
433 forAllConstIter(EdgeMap<label>, oldSharedEdges, iter)
437 globalShared.insert(iter.key(), iter());
442 Pout<< "globalMeshData::calcSharedEdges : Filtered "
443 << oldSharedEdges.size()
444 << " down to " << globalShared.size() << endl;
449 // Send back to slaves.
450 if (Pstream::parRun())
454 int slave=Pstream::firstSlave();
455 slave<=Pstream::lastSlave();
459 // Receive the edges using shared points from the slave.
460 OPstream toSlave(Pstream::blocking, slave);
461 toSlave << globalShared;
467 // Send local edges to master
469 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
471 toMaster << localShared;
473 // Receive merged edges from master.
475 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
477 fromMaster >> globalShared;
481 // Now use the global shared edges list (globalShared) to classify my local
482 // ones (localShared)
484 nGlobalEdges_ = globalShared.size();
486 DynamicList<label> dynSharedEdgeLabels(globalShared.size());
487 DynamicList<label> dynSharedEdgeAddr(globalShared.size());
489 forAllConstIter(EdgeMap<labelList>, localShared, iter)
491 const edge& e = iter.key();
493 EdgeMap<label>::const_iterator edgeFnd = globalShared.find(e);
495 if (edgeFnd != globalShared.end())
497 // My local edge is indeed a shared one. Go through all local edge
498 // labels with this point combination.
499 const labelList& edgeLabels = iter();
501 forAll(edgeLabels, i)
503 // Store label of local mesh edge
504 dynSharedEdgeLabels.append(edgeLabels[i]);
506 // Store label of shared edge
507 dynSharedEdgeAddr.append(edgeFnd());
512 sharedEdgeLabelsPtr_.reset(new labelList());
513 labelList& sharedEdgeLabels = sharedEdgeLabelsPtr_();
514 sharedEdgeLabels.transfer(dynSharedEdgeLabels);
516 sharedEdgeAddrPtr_.reset(new labelList());
517 labelList& sharedEdgeAddr = sharedEdgeAddrPtr_();
518 sharedEdgeAddr.transfer(dynSharedEdgeAddr);
522 Pout<< "globalMeshData : nGlobalEdges_:" << nGlobalEdges_ << nl
523 << "globalMeshData : sharedEdgeLabels:" << sharedEdgeLabels.size()
525 << "globalMeshData : sharedEdgeAddr:" << sharedEdgeAddr.size()
531 void Foam::globalMeshData::calcGlobalPointSlaves() const
535 Pout<< "globalMeshData::calcGlobalPointSlaves() :"
536 << " calculating coupled master to slave point addressing."
540 // Calculate connected points for master points.
541 globalPoints globalData(mesh_, coupledPatch(), true, true);
543 globalPointSlavesPtr_.reset
547 globalData.pointPoints().xfer()
550 globalPointTransformedSlavesPtr_.reset
554 globalData.transformedPointPoints().xfer()
558 globalPointSlavesMapPtr_.reset
562 globalData.map().xfer()
568 void Foam::globalMeshData::calcPointConnectivity
570 List<labelPairList>& allPointConnectivity
573 const globalIndexAndTransform& transforms = globalTransforms();
574 const labelListList& slaves = globalPointSlaves();
575 const labelListList& transformedSlaves = globalPointTransformedSlaves();
578 // Create field with my local data
579 labelPairList myData(globalPointSlavesMap().constructSize());
580 forAll(slaves, pointI)
582 myData[pointI] = globalIndexAndTransform::encode
586 transforms.nullTransformIndex()
590 globalPointSlavesMap().distribute(myData);
593 // String of connected points with their transform
594 allPointConnectivity.setSize(globalPointSlavesMap().constructSize());
595 forAll(slaves, pointI)
597 // Reconstruct string of connected points
598 const labelList& pSlaves = slaves[pointI];
599 const labelList& pTransformSlaves = transformedSlaves[pointI];
600 labelPairList& pConnectivity = allPointConnectivity[pointI];
601 pConnectivity.setSize(1+pSlaves.size()+pTransformSlaves.size());
605 pConnectivity[connI++] = myData[pointI];
606 // Add untransformed points
609 pConnectivity[connI++] = myData[pSlaves[i]];
611 // Add transformed points.
612 forAll(pTransformSlaves, i)
614 // Get transform from index
615 label transformI = globalPointSlavesMap().whichTransform
619 // Add transform to connectivity
620 const labelPair& n = myData[pTransformSlaves[i]];
621 label procI = globalIndexAndTransform::processor(n);
622 label index = globalIndexAndTransform::index(n);
623 pConnectivity[connI++] = globalIndexAndTransform::encode
634 allPointConnectivity[pSlaves[i]] = pConnectivity;
636 forAll(pTransformSlaves, i)
638 allPointConnectivity[pTransformSlaves[i]] = pConnectivity;
641 globalPointSlavesMap().reverseDistribute
643 allPointConnectivity.size(),
649 void Foam::globalMeshData::calcGlobalPointEdges
651 labelListList& globalPointEdges,
652 List<labelPairList>& globalPointPoints
655 const edgeList& edges = coupledPatch().edges();
656 const labelListList& pointEdges = coupledPatch().pointEdges();
657 const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
658 const labelListList& slaves = globalPointSlaves();
659 const labelListList& transformedSlaves = globalPointTransformedSlaves();
661 // Create local version
662 globalPointEdges.setSize(globalPointSlavesMap().constructSize());
663 globalPointPoints.setSize(globalPointSlavesMap().constructSize());
664 forAll(pointEdges, pointI)
666 const labelList& pEdges = pointEdges[pointI];
667 labelList& globalPEdges = globalPointEdges[pointI];
668 globalPEdges.setSize(pEdges.size());
671 globalPEdges[i] = globalEdgeNumbers.toGlobal(pEdges[i]);
674 labelPairList& globalPPoints = globalPointPoints[pointI];
675 globalPPoints.setSize(pEdges.size());
678 label otherPointI = edges[pEdges[i]].otherVertex(pointI);
679 globalPPoints[i] = globalIndexAndTransform::encode
683 globalTransforms().nullTransformIndex()
688 // Pull slave data to master. Dummy transform.
689 globalPointSlavesMap().distribute(globalPointEdges);
690 globalPointSlavesMap().distribute(globalPointPoints);
691 // Add all pointEdges
692 forAll(slaves, pointI)
694 const labelList& pSlaves = slaves[pointI];
695 const labelList& pTransformSlaves = transformedSlaves[pointI];
700 n += globalPointEdges[pSlaves[i]].size();
702 forAll(pTransformSlaves, i)
704 n += globalPointEdges[pTransformSlaves[i]].size();
707 // Add all the point edges of the slaves to those of the (master) point
709 labelList& globalPEdges = globalPointEdges[pointI];
710 label sz = globalPEdges.size();
711 globalPEdges.setSize(sz+n);
714 const labelList& otherData = globalPointEdges[pSlaves[i]];
717 globalPEdges[sz++] = otherData[j];
720 forAll(pTransformSlaves, i)
722 const labelList& otherData =
723 globalPointEdges[pTransformSlaves[i]];
726 globalPEdges[sz++] = otherData[j];
733 globalPointEdges[pSlaves[i]] = globalPEdges;
735 forAll(pTransformSlaves, i)
737 globalPointEdges[pTransformSlaves[i]] = globalPEdges;
742 // Same for corresponding pointPoints
744 labelPairList& globalPPoints = globalPointPoints[pointI];
745 label sz = globalPPoints.size();
746 globalPPoints.setSize(sz + n);
748 // Add untransformed points
751 const labelPairList& otherData = globalPointPoints[pSlaves[i]];
754 globalPPoints[sz++] = otherData[j];
757 // Add transformed points.
758 forAll(pTransformSlaves, i)
760 // Get transform from index
761 label transformI = globalPointSlavesMap().whichTransform
766 const labelPairList& otherData =
767 globalPointPoints[pTransformSlaves[i]];
770 // Add transform to connectivity
771 const labelPair& n = otherData[j];
772 label procI = globalIndexAndTransform::processor(n);
773 label index = globalIndexAndTransform::index(n);
774 globalPPoints[sz++] = globalIndexAndTransform::encode
786 globalPointPoints[pSlaves[i]] = globalPPoints;
788 forAll(pTransformSlaves, i)
790 globalPointPoints[pTransformSlaves[i]] = globalPPoints;
795 globalPointSlavesMap().reverseDistribute
797 globalPointEdges.size(),
801 globalPointSlavesMap().reverseDistribute
803 globalPointPoints.size(),
809 // Find transformation to take remotePoint to localPoint. Use info to find
811 Foam::label Foam::globalMeshData::findTransform
813 const labelPairList& info,
814 const labelPair& remotePoint,
815 const label localPoint
818 const label remoteProcI = globalIndexAndTransform::processor(remotePoint);
819 const label remoteIndex = globalIndexAndTransform::index(remotePoint);
821 label remoteTransformI = -1;
822 label localTransformI = -1;
825 label procI = globalIndexAndTransform::processor(info[i]);
826 label pointI = globalIndexAndTransform::index(info[i]);
827 label transformI = globalIndexAndTransform::transformIndex(info[i]);
829 if (procI == Pstream::myProcNo() && pointI == localPoint)
831 localTransformI = transformI;
832 //Pout<< "For local :" << localPoint
833 // << " found transform:" << localTransformI
836 if (procI == remoteProcI && pointI == remoteIndex)
838 remoteTransformI = transformI;
839 //Pout<< "For remote:" << remotePoint
840 // << " found transform:" << remoteTransformI
841 // << " at index:" << i
846 if (remoteTransformI == -1 || localTransformI == -1)
848 FatalErrorIn("globalMeshData::findTransform(..)")
849 << "Problem. Cannot find " << remotePoint
850 << " or " << localPoint << " in " << info
852 << "remoteTransformI:" << remoteTransformI << endl
853 << "localTransformI:" << localTransformI
854 << abort(FatalError);
857 return globalTransforms().subtractTransformIndex
865 void Foam::globalMeshData::calcGlobalEdgeSlaves() const
869 Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
870 << " calculating coupled master to slave edge addressing." << endl;
873 const edgeList& edges = coupledPatch().edges();
874 const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
877 // The whole problem with deducting edge-connectivity from
878 // point-connectivity is that one of the the endpoints might be
879 // a local master but the other endpoint might not. So we first
880 // need to make sure that all points know about connectivity and
881 // the transformations.
884 // 1. collect point connectivity - basically recreating globalPoints ouput.
885 // All points will now have a string of points. The transforms are
886 // in respect to the master.
887 List<labelPairList> allPointConnectivity;
888 calcPointConnectivity(allPointConnectivity);
891 // 2. Get all pointEdges and pointPoints
892 // Coupled point to global coupled edges and corresponding endpoint.
893 labelListList globalPointEdges;
894 List<labelPairList> globalPointPoints;
895 calcGlobalPointEdges(globalPointEdges, globalPointPoints);
898 // 3. Now all points have
899 // - all the connected points with original transform
900 // - all the connected global edges
902 // Now all we need to do is go through all the edges and check
903 // both endpoints. If there is a edge between the two which is
904 // produced by transforming both points in the same way it is a shared
907 // Collect strings of connected edges.
908 List<labelPairList> allEdgeConnectivity(edges.size());
912 const edge& e = edges[edgeI];
913 const labelList& pEdges0 = globalPointEdges[e[0]];
914 const labelPairList& pPoints0 = globalPointPoints[e[0]];
915 const labelList& pEdges1 = globalPointEdges[e[1]];
916 const labelPairList& pPoints1 = globalPointPoints[e[1]];
918 // Most edges will be size 2
919 DynamicList<labelPair> eEdges(2);
923 globalIndexAndTransform::encode
927 globalTransforms().nullTransformIndex()
937 pEdges0[i] == pEdges1[j]
938 && pEdges0[i] != globalEdgeNumbers.toGlobal(edgeI)
941 // Found a shared edge. Now check if the endpoints
942 // go through the same transformation.
943 // Local: e[0] remote:pPoints1[j]
944 // Local: e[1] remote:pPoints0[i]
947 // Find difference in transforms to go from point on remote
948 // edge (pPoints1[j]) to this point.
950 label transform0 = findTransform
952 allPointConnectivity[e[0]],
956 label transform1 = findTransform
958 allPointConnectivity[e[1]],
963 if (transform0 == transform1)
965 label procI = globalEdgeNumbers.whichProcID(pEdges0[i]);
968 globalIndexAndTransform::encode
971 globalEdgeNumbers.toLocal(procI, pEdges0[i]),
980 allEdgeConnectivity[edgeI].transfer(eEdges);
981 sort(allEdgeConnectivity[edgeI], globalIndexAndTransform::less());
984 // We now have - in allEdgeConnectivity - a list of edges which are shared
985 // between multiple processors. Filter into non-transformed and transformed
988 globalEdgeSlavesPtr_.reset(new labelListList(edges.size()));
989 labelListList& globalEdgeSlaves = globalEdgeSlavesPtr_();
990 List<labelPairList> transformedEdges(edges.size());
991 forAll(allEdgeConnectivity, edgeI)
993 const labelPairList& edgeInfo = allEdgeConnectivity[edgeI];
994 if (edgeInfo.size() >= 2)
996 const labelPair& masterInfo = edgeInfo[0];
998 // Check if master edge (= first element (since sorted)) is me.
1002 globalIndexAndTransform::processor(masterInfo)
1003 == Pstream::myProcNo()
1005 && (globalIndexAndTransform::index(masterInfo) == edgeI)
1008 // Sort into transformed and untransformed
1009 labelList& eEdges = globalEdgeSlaves[edgeI];
1010 eEdges.setSize(edgeInfo.size()-1);
1012 labelPairList& trafoEEdges = transformedEdges[edgeI];
1013 trafoEEdges.setSize(edgeInfo.size()-1);
1015 label nonTransformI = 0;
1016 label transformI = 0;
1018 for (label i = 1; i < edgeInfo.size(); i++)
1020 const labelPair& info = edgeInfo[i];
1021 label procI = globalIndexAndTransform::processor(info);
1022 label index = globalIndexAndTransform::index(info);
1023 label transform = globalIndexAndTransform::transformIndex
1028 if (transform == globalTransforms().nullTransformIndex())
1030 eEdges[nonTransformI++] = globalEdgeNumbers.toGlobal
1038 trafoEEdges[transformI++] = info;
1042 eEdges.setSize(nonTransformI);
1043 trafoEEdges.setSize(transformI);
1050 globalEdgeTransformedSlavesPtr_.reset(new labelListList());
1052 List<Map<label> > compactMap(Pstream::nProcs());
1053 globalEdgeSlavesMapPtr_.reset
1062 globalEdgeTransformedSlavesPtr_(),
1071 Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
1072 << " coupled edges:" << edges.size()
1073 << " additional coupled edges:"
1074 << globalEdgeSlavesMapPtr_().constructSize() - edges.size()
1080 void Foam::globalMeshData::calcGlobalEdgeOrientation() const
1084 Pout<< "globalMeshData::calcGlobalEdgeOrientation() :"
1085 << " calculating edge orientation w.r.t. master edge." << endl;
1088 const globalIndex& globalPoints = globalPointNumbering();
1090 // 1. Determine master point
1091 labelList masterPoint;
1093 const mapDistribute& map = globalPointSlavesMap();
1095 masterPoint.setSize(map.constructSize());
1096 masterPoint = labelMax;
1098 for (label pointI = 0; pointI < coupledPatch().nPoints(); pointI++)
1100 masterPoint[pointI] = globalPoints.toGlobal(pointI);
1105 globalPointSlaves(),
1106 globalPointTransformedSlaves(),
1112 // Now all points should know who is master by comparing their global
1113 // pointID with the masterPointID. We now can use this information
1114 // to find the orientation of the master edge.
1117 const mapDistribute& map = globalEdgeSlavesMap();
1118 const labelListList& slaves = globalEdgeSlaves();
1119 const labelListList& transformedSlaves = globalEdgeTransformedSlaves();
1121 // Distribute orientation of master edge (in masterPoint numbering)
1122 labelPairList masterEdgeVerts(map.constructSize());
1123 masterEdgeVerts = labelPair(labelMax, labelMax);
1125 for (label edgeI = 0; edgeI < coupledPatch().nEdges(); edgeI++)
1130 slaves[edgeI].size()
1131 + transformedSlaves[edgeI].size()
1136 // I am master. Fill in my masterPoint equivalent.
1138 const edge& e = coupledPatch().edges()[edgeI];
1139 masterEdgeVerts[edgeI] = labelPair
1152 minEqOp<labelPair>()
1155 // Now check my edges on how they relate to the master's edgeVerts
1156 globalEdgeOrientationPtr_.reset
1158 new PackedBoolList(coupledPatch().nEdges())
1160 PackedBoolList& globalEdgeOrientation = globalEdgeOrientationPtr_();
1162 forAll(coupledPatch().edges(), edgeI)
1164 const edge& e = coupledPatch().edges()[edgeI];
1165 const labelPair masterE
1171 label stat = labelPair::compare
1174 masterEdgeVerts[edgeI]
1180 "globalMeshData::calcGlobalEdgeOrientation() const"
1181 ) << "problem : my edge:" << e
1182 << " in master points:" << masterE
1183 << " v.s. masterEdgeVerts:" << masterEdgeVerts[edgeI]
1184 << exit(FatalError);
1188 globalEdgeOrientation[edgeI] = (stat == 1);
1195 Pout<< "globalMeshData::calcGlobalEdgeOrientation() :"
1196 << " finished calculating edge orientation."
1202 // Calculate uncoupled boundary faces (without calculating
1203 // primitiveMesh::pointFaces())
1204 void Foam::globalMeshData::calcPointBoundaryFaces
1206 labelListList& pointBoundaryFaces
1209 const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
1210 const Map<label>& meshPointMap = coupledPatch().meshPointMap();
1214 labelList nPointFaces(coupledPatch().nPoints(), 0);
1216 forAll(bMesh, patchI)
1218 const polyPatch& pp = bMesh[patchI];
1224 const face& f = pp[i];
1228 Map<label>::const_iterator iter = meshPointMap.find
1232 if (iter != meshPointMap.end())
1234 nPointFaces[iter()]++;
1244 pointBoundaryFaces.setSize(coupledPatch().nPoints());
1245 forAll(nPointFaces, pointI)
1247 pointBoundaryFaces[pointI].setSize(nPointFaces[pointI]);
1254 forAll(bMesh, patchI)
1256 const polyPatch& pp = bMesh[patchI];
1262 const face& f = pp[i];
1265 Map<label>::const_iterator iter = meshPointMap.find
1269 if (iter != meshPointMap.end())
1272 pp.start() + i - mesh_.nInternalFaces();
1273 pointBoundaryFaces[iter()][nPointFaces[iter()]++] =
1283 void Foam::globalMeshData::calcGlobalPointBoundaryFaces() const
1287 Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1288 << " calculating coupled point to boundary face addressing."
1292 // Construct local point to (uncoupled)boundaryfaces.
1293 labelListList pointBoundaryFaces;
1294 calcPointBoundaryFaces(pointBoundaryFaces);
1297 // Global indices for boundary faces
1298 globalBoundaryFaceNumberingPtr_.reset
1300 new globalIndex(mesh_.nFaces()-mesh_.nInternalFaces())
1302 globalIndex& globalIndices = globalBoundaryFaceNumberingPtr_();
1305 // Convert local boundary faces to global numbering
1306 globalPointBoundaryFacesPtr_.reset
1308 new labelListList(globalPointSlavesMap().constructSize())
1310 labelListList& globalPointBoundaryFaces = globalPointBoundaryFacesPtr_();
1312 forAll(pointBoundaryFaces, pointI)
1314 const labelList& bFaces = pointBoundaryFaces[pointI];
1315 labelList& globalFaces = globalPointBoundaryFaces[pointI];
1316 globalFaces.setSize(bFaces.size());
1319 globalFaces[i] = globalIndices.toGlobal(bFaces[i]);
1324 // Pull slave pointBoundaryFaces to master
1325 globalPointSlavesMap().distribute
1327 globalPointBoundaryFaces,
1328 true // put data on transformed points into correct slots
1332 // Merge slave labels into master globalPointBoundaryFaces.
1333 // Split into untransformed and transformed values.
1334 const labelListList& pointSlaves = globalPointSlaves();
1335 const labelListList& pointTransformSlaves =
1336 globalPointTransformedSlaves();
1339 // Any faces coming in through transformation
1340 List<labelPairList> transformedFaces(pointSlaves.size());
1343 forAll(pointSlaves, pointI)
1345 const labelList& slaves = pointSlaves[pointI];
1346 const labelList& transformedSlaves = pointTransformSlaves[pointI];
1348 if (slaves.size() > 0)
1350 labelList& myBFaces = globalPointBoundaryFaces[pointI];
1351 label sz = myBFaces.size();
1357 n += globalPointBoundaryFaces[slaves[i]].size();
1360 myBFaces.setSize(sz+n);
1364 const labelList& slaveBFaces =
1365 globalPointBoundaryFaces[slaves[i]];
1367 // Add all slaveBFaces. Note that need to check for
1368 // uniqueness only in case of cyclics.
1370 forAll(slaveBFaces, j)
1372 label slave = slaveBFaces[j];
1373 if (findIndex(SubList<label>(myBFaces, sz), slave) == -1)
1375 myBFaces[n++] = slave;
1379 myBFaces.setSize(n);
1383 if (transformedSlaves.size() > 0)
1385 const labelList& untrafoFaces = globalPointBoundaryFaces[pointI];
1387 labelPairList& myBFaces = transformedFaces[pointI];
1388 label sz = myBFaces.size();
1392 forAll(transformedSlaves, i)
1394 n += globalPointBoundaryFaces[transformedSlaves[i]].size();
1397 myBFaces.setSize(sz+n);
1399 forAll(transformedSlaves, i)
1401 label transformI = globalPointSlavesMap().whichTransform
1403 transformedSlaves[i]
1406 const labelList& slaveBFaces =
1407 globalPointBoundaryFaces[transformedSlaves[i]];
1409 forAll(slaveBFaces, j)
1411 label slave = slaveBFaces[j];
1412 // Check that same face not already present untransformed
1413 if (findIndex(untrafoFaces, slave)== -1)
1415 label procI = globalIndices.whichProcID(slave);
1416 label faceI = globalIndices.toLocal(procI, slave);
1418 myBFaces[n++] = globalIndexAndTransform::encode
1427 myBFaces.setSize(n);
1431 if (slaves.size() + transformedSlaves.size() == 0)
1433 globalPointBoundaryFaces[pointI].clear();
1437 // Construct a map to get the face data directly
1438 List<Map<label> > compactMap(Pstream::nProcs());
1440 globalPointTransformedBoundaryFacesPtr_.reset
1442 new labelListList(transformedFaces.size())
1445 globalPointBoundaryFacesMapPtr_.reset
1450 globalPointBoundaryFaces,
1454 globalPointTransformedBoundaryFacesPtr_(),
1459 globalPointBoundaryFaces.setSize(coupledPatch().nPoints());
1460 globalPointTransformedBoundaryFacesPtr_().setSize(coupledPatch().nPoints());
1464 Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1465 << " coupled points:" << coupledPatch().nPoints()
1466 << " local boundary faces:" << globalIndices.localSize()
1467 << " additional coupled faces:"
1468 << globalPointBoundaryFacesMapPtr_().constructSize()
1469 - globalIndices.localSize()
1475 void Foam::globalMeshData::calcGlobalPointBoundaryCells() const
1479 Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1480 << " calculating coupled point to boundary cell addressing."
1484 // Create map of boundary cells and point-cell addressing
1485 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1488 Map<label> meshCellMap(4*coupledPatch().nPoints());
1489 DynamicList<label> cellMap(meshCellMap.size());
1491 // Create addressing for point to boundary cells (local)
1492 labelListList pointBoundaryCells(coupledPatch().nPoints());
1494 forAll(coupledPatch().meshPoints(), pointI)
1496 label meshPointI = coupledPatch().meshPoints()[pointI];
1497 const labelList& pCells = mesh_.pointCells(meshPointI);
1499 labelList& bCells = pointBoundaryCells[pointI];
1500 bCells.setSize(pCells.size());
1504 label cellI = pCells[i];
1505 Map<label>::iterator fnd = meshCellMap.find(cellI);
1507 if (fnd != meshCellMap.end())
1513 meshCellMap.insert(cellI, bCellI);
1514 cellMap.append(cellI);
1522 boundaryCellsPtr_.reset(new labelList());
1523 labelList& boundaryCells = boundaryCellsPtr_();
1524 boundaryCells.transfer(cellMap.shrink());
1527 // Convert point-cells to global (boundary)cell numbers
1528 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1530 globalBoundaryCellNumberingPtr_.reset
1532 new globalIndex(boundaryCells.size())
1534 globalIndex& globalIndices = globalBoundaryCellNumberingPtr_();
1537 globalPointBoundaryCellsPtr_.reset
1539 new labelListList(globalPointSlavesMap().constructSize())
1541 labelListList& globalPointBoundaryCells = globalPointBoundaryCellsPtr_();
1543 forAll(pointBoundaryCells, pointI)
1545 const labelList& pCells = pointBoundaryCells[pointI];
1546 labelList& globalCells = globalPointBoundaryCells[pointI];
1547 globalCells.setSize(pCells.size());
1550 globalCells[i] = globalIndices.toGlobal(pCells[i]);
1555 // Pull slave pointBoundaryCells to master
1556 globalPointSlavesMap().distribute
1558 globalPointBoundaryCells,
1559 true // put data on transformed points into correct slots
1563 // Merge slave labels into master globalPointBoundaryCells
1564 const labelListList& pointSlaves = globalPointSlaves();
1565 const labelListList& pointTransformSlaves =
1566 globalPointTransformedSlaves();
1568 List<labelPairList> transformedCells(pointSlaves.size());
1571 forAll(pointSlaves, pointI)
1573 const labelList& slaves = pointSlaves[pointI];
1574 const labelList& transformedSlaves = pointTransformSlaves[pointI];
1576 if (slaves.size() > 0)
1578 labelList& myBCells = globalPointBoundaryCells[pointI];
1579 label sz = myBCells.size();
1585 n += globalPointBoundaryCells[slaves[i]].size();
1588 myBCells.setSize(sz+n);
1592 const labelList& slaveBCells =
1593 globalPointBoundaryCells[slaves[i]];
1595 // Add all slaveBCells. Note that need to check for
1596 // uniqueness only in case of cyclics.
1598 forAll(slaveBCells, j)
1600 label slave = slaveBCells[j];
1601 if (findIndex(SubList<label>(myBCells, sz), slave) == -1)
1603 myBCells[n++] = slave;
1607 myBCells.setSize(n);
1611 if (transformedSlaves.size() > 0)
1613 const labelList& untrafoCells = globalPointBoundaryCells[pointI];
1615 labelPairList& myBCells = transformedCells[pointI];
1616 label sz = myBCells.size();
1620 forAll(transformedSlaves, i)
1622 n += globalPointBoundaryCells[transformedSlaves[i]].size();
1625 myBCells.setSize(sz+n);
1627 forAll(transformedSlaves, i)
1629 label transformI = globalPointSlavesMap().whichTransform
1631 transformedSlaves[i]
1634 const labelList& slaveBCells =
1635 globalPointBoundaryCells[transformedSlaves[i]];
1637 forAll(slaveBCells, j)
1639 label slave = slaveBCells[j];
1641 // Check that same cell not already present untransformed
1642 if (findIndex(untrafoCells, slave)== -1)
1644 label procI = globalIndices.whichProcID(slave);
1645 label cellI = globalIndices.toLocal(procI, slave);
1646 myBCells[n++] = globalIndexAndTransform::encode
1655 myBCells.setSize(n);
1658 if (slaves.size() + transformedSlaves.size() == 0)
1660 globalPointBoundaryCells[pointI].clear();
1664 // Construct a map to get the cell data directly
1665 List<Map<label> > compactMap(Pstream::nProcs());
1667 globalPointTransformedBoundaryCellsPtr_.reset
1669 new labelListList(transformedCells.size())
1672 globalPointBoundaryCellsMapPtr_.reset
1677 globalPointBoundaryCells,
1681 globalPointTransformedBoundaryCellsPtr_(),
1686 globalPointBoundaryCells.setSize(coupledPatch().nPoints());
1687 globalPointTransformedBoundaryCellsPtr_().setSize(coupledPatch().nPoints());
1691 Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1692 << " coupled points:" << coupledPatch().nPoints()
1693 << " local boundary cells:" << globalIndices.localSize()
1694 << " additional coupled cells:"
1695 << globalPointBoundaryCellsMapPtr_().constructSize()
1696 - globalIndices.localSize()
1702 void Foam::globalMeshData::calcGlobalCoPointSlaves() const
1706 Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1707 << " calculating coupled master to collocated"
1708 << " slave point addressing." << endl;
1711 // Calculate connected points for master points.
1712 globalPoints globalData(mesh_, coupledPatch(), true, false);
1714 globalCoPointSlavesPtr_.reset
1718 globalData.pointPoints().xfer()
1721 globalCoPointSlavesMapPtr_.reset
1725 globalData.map().xfer()
1731 Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1732 << " finished calculating coupled master to collocated"
1733 << " slave point addressing." << endl;
1738 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1740 // Construct from polyMesh
1741 Foam::globalMeshData::globalMeshData(const polyMesh& mesh)
1743 processorTopology(mesh.boundaryMesh()),
1748 processorPatches_(0),
1749 processorPatchIndices_(0),
1750 processorPatchNeighbours_(0),
1752 sharedPointLabelsPtr_(NULL),
1753 sharedPointAddrPtr_(NULL),
1754 sharedPointGlobalLabelsPtr_(NULL),
1756 sharedEdgeLabelsPtr_(NULL),
1757 sharedEdgeAddrPtr_(NULL)
1763 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1765 Foam::globalMeshData::~globalMeshData()
1771 void Foam::globalMeshData::clearOut()
1774 nGlobalPoints_ = -1;
1775 sharedPointLabelsPtr_.clear();
1776 sharedPointAddrPtr_.clear();
1777 sharedPointGlobalLabelsPtr_.clear();
1781 sharedEdgeLabelsPtr_.clear();
1782 sharedEdgeAddrPtr_.clear();
1785 coupledPatchPtr_.clear();
1786 coupledPatchMeshEdgesPtr_.clear();
1787 coupledPatchMeshEdgeMapPtr_.clear();
1788 globalTransformsPtr_.clear();
1791 globalPointNumberingPtr_.clear();
1792 globalPointSlavesPtr_.clear();
1793 globalPointTransformedSlavesPtr_.clear();
1794 globalPointSlavesMapPtr_.clear();
1796 globalEdgeNumberingPtr_.clear();
1797 globalEdgeSlavesPtr_.clear();
1798 globalEdgeTransformedSlavesPtr_.clear();
1799 globalEdgeOrientationPtr_.clear();
1800 globalEdgeSlavesMapPtr_.clear();
1803 globalBoundaryFaceNumberingPtr_.clear();
1804 globalPointBoundaryFacesPtr_.clear();
1805 globalPointTransformedBoundaryFacesPtr_.clear();
1806 globalPointBoundaryFacesMapPtr_.clear();
1809 boundaryCellsPtr_.clear();
1810 globalBoundaryCellNumberingPtr_.clear();
1811 globalPointBoundaryCellsPtr_.clear();
1812 globalPointTransformedBoundaryCellsPtr_.clear();
1813 globalPointBoundaryCellsMapPtr_.clear();
1815 // Other: collocated points
1816 globalCoPointSlavesPtr_.clear();
1817 globalCoPointSlavesMapPtr_.clear();
1821 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1823 // Return shared point global labels.
1824 const Foam::labelList& Foam::globalMeshData::sharedPointGlobalLabels() const
1826 if (!sharedPointGlobalLabelsPtr_.valid())
1828 sharedPointGlobalLabelsPtr_.reset
1830 new labelList(sharedPointLabels().size())
1832 labelList& sharedPointGlobalLabels = sharedPointGlobalLabelsPtr_();
1836 "pointProcAddressing",
1837 mesh_.facesInstance()/mesh_.meshSubDir,
1842 if (addrHeader.headerOk())
1844 // There is a pointProcAddressing file so use it to get labels
1845 // on the original mesh
1846 Pout<< "globalMeshData::sharedPointGlobalLabels : "
1847 << "Reading pointProcAddressing" << endl;
1849 labelIOList pointProcAddressing(addrHeader);
1851 const labelList& pointLabels = sharedPointLabels();
1853 forAll(pointLabels, i)
1855 // Get my mesh point
1856 label pointI = pointLabels[i];
1858 // Map to mesh point of original mesh
1859 sharedPointGlobalLabels[i] = pointProcAddressing[pointI];
1864 Pout<< "globalMeshData::sharedPointGlobalLabels :"
1865 << " Setting pointProcAddressing to -1" << endl;
1867 sharedPointGlobalLabels = -1;
1870 return sharedPointGlobalLabelsPtr_();
1874 // Collect coordinates of shared points. (does parallel communication!)
1875 Foam::pointField Foam::globalMeshData::sharedPoints() const
1877 // Get all processors to send their shared points to master.
1878 // (not very efficient)
1880 pointField sharedPoints(nGlobalPoints());
1881 const labelList& pointAddr = sharedPointAddr();
1882 const labelList& pointLabels = sharedPointLabels();
1884 if (Pstream::master())
1887 // insert my own data first
1888 forAll(pointLabels, i)
1890 label sharedPointI = pointAddr[i];
1892 sharedPoints[sharedPointI] = mesh_.points()[pointLabels[i]];
1895 // Receive data from slaves and insert
1898 int slave=Pstream::firstSlave();
1899 slave<=Pstream::lastSlave();
1903 IPstream fromSlave(Pstream::blocking, slave);
1905 labelList nbrSharedPointAddr;
1906 pointField nbrSharedPoints;
1907 fromSlave >> nbrSharedPointAddr >> nbrSharedPoints;
1909 forAll(nbrSharedPointAddr, i)
1911 label sharedPointI = nbrSharedPointAddr[i];
1913 sharedPoints[sharedPointI] = nbrSharedPoints[i];
1920 int slave=Pstream::firstSlave();
1921 slave<=Pstream::lastSlave();
1929 sharedPoints.size()*sizeof(vector::zero)
1931 toSlave << sharedPoints;
1939 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
1943 << UIndirectList<point>(mesh_.points(), pointLabels)();
1946 // Receive sharedPoints
1948 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
1949 fromMaster >> sharedPoints;
1953 return sharedPoints;
1957 // Collect coordinates of shared points. (does parallel communication!)
1958 Foam::pointField Foam::globalMeshData::geometricSharedPoints() const
1960 // Get coords of my shared points
1961 pointField sharedPoints(mesh_.points(), sharedPointLabels());
1963 // Append from all processors
1964 combineReduce(sharedPoints, plusEqOp<pointField>());
1967 scalar tolDim = matchTol_ * mesh_.bounds().mag();
1969 // And see how many are unique
1971 pointField mergedPoints;
1975 sharedPoints, // coordinates to merge
1976 tolDim, // tolerance
1982 return mergedPoints;
1986 Foam::label Foam::globalMeshData::nGlobalPoints() const
1988 if (nGlobalPoints_ == -1)
1992 return nGlobalPoints_;
1996 const Foam::labelList& Foam::globalMeshData::sharedPointLabels() const
1998 if (!sharedPointLabelsPtr_.valid())
2002 return sharedPointLabelsPtr_();
2006 const Foam::labelList& Foam::globalMeshData::sharedPointAddr() const
2008 if (!sharedPointAddrPtr_.valid())
2012 return sharedPointAddrPtr_();
2016 Foam::label Foam::globalMeshData::nGlobalEdges() const
2018 if (nGlobalEdges_ == -1)
2022 return nGlobalEdges_;
2026 const Foam::labelList& Foam::globalMeshData::sharedEdgeLabels() const
2028 if (!sharedEdgeLabelsPtr_.valid())
2032 return sharedEdgeLabelsPtr_();
2036 const Foam::labelList& Foam::globalMeshData::sharedEdgeAddr() const
2038 if (!sharedEdgeAddrPtr_.valid())
2042 return sharedEdgeAddrPtr_();
2046 const Foam::indirectPrimitivePatch& Foam::globalMeshData::coupledPatch() const
2048 if (!coupledPatchPtr_.valid())
2050 const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
2054 forAll(bMesh, patchI)
2056 const polyPatch& pp = bMesh[patchI];
2060 nCoupled += pp.size();
2063 labelList coupledFaces(nCoupled);
2066 forAll(bMesh, patchI)
2068 const polyPatch& pp = bMesh[patchI];
2072 label faceI = pp.start();
2076 coupledFaces[nCoupled++] = faceI++;
2081 coupledPatchPtr_.reset
2083 new indirectPrimitivePatch
2096 Pout<< "globalMeshData::coupledPatch() :"
2097 << " constructed coupled faces patch:"
2098 << " faces:" << coupledPatchPtr_().size()
2099 << " points:" << coupledPatchPtr_().nPoints()
2103 return coupledPatchPtr_();
2107 const Foam::labelList& Foam::globalMeshData::coupledPatchMeshEdges() const
2109 if (!coupledPatchMeshEdgesPtr_.valid())
2111 coupledPatchMeshEdgesPtr_.reset
2115 coupledPatch().meshEdges
2123 return coupledPatchMeshEdgesPtr_();
2127 const Foam::Map<Foam::label>& Foam::globalMeshData::coupledPatchMeshEdgeMap()
2130 if (!coupledPatchMeshEdgeMapPtr_.valid())
2132 const labelList& me = coupledPatchMeshEdges();
2134 coupledPatchMeshEdgeMapPtr_.reset(new Map<label>(2*me.size()));
2135 Map<label>& em = coupledPatchMeshEdgeMapPtr_();
2139 em.insert(me[i], i);
2142 return coupledPatchMeshEdgeMapPtr_();
2146 const Foam::globalIndex& Foam::globalMeshData::globalPointNumbering() const
2148 if (!globalPointNumberingPtr_.valid())
2150 globalPointNumberingPtr_.reset
2152 new globalIndex(coupledPatch().nPoints())
2155 return globalPointNumberingPtr_();
2159 const Foam::globalIndexAndTransform&
2160 Foam::globalMeshData::globalTransforms() const
2162 if (!globalTransformsPtr_.valid())
2164 globalTransformsPtr_.reset(new globalIndexAndTransform(mesh_));
2166 return globalTransformsPtr_();
2170 const Foam::labelListList& Foam::globalMeshData::globalPointSlaves() const
2172 if (!globalPointSlavesPtr_.valid())
2174 calcGlobalPointSlaves();
2176 return globalPointSlavesPtr_();
2180 const Foam::labelListList& Foam::globalMeshData::globalPointTransformedSlaves()
2183 if (!globalPointTransformedSlavesPtr_.valid())
2185 calcGlobalPointSlaves();
2187 return globalPointTransformedSlavesPtr_();
2191 const Foam::mapDistribute& Foam::globalMeshData::globalPointSlavesMap() const
2193 if (!globalPointSlavesMapPtr_.valid())
2195 calcGlobalPointSlaves();
2197 return globalPointSlavesMapPtr_();
2201 const Foam::globalIndex& Foam::globalMeshData::globalEdgeNumbering() const
2203 if (!globalEdgeNumberingPtr_.valid())
2205 globalEdgeNumberingPtr_.reset
2207 new globalIndex(coupledPatch().nEdges())
2210 return globalEdgeNumberingPtr_();
2214 const Foam::labelListList& Foam::globalMeshData::globalEdgeSlaves() const
2216 if (!globalEdgeSlavesPtr_.valid())
2218 calcGlobalEdgeSlaves();
2220 return globalEdgeSlavesPtr_();
2224 const Foam::labelListList& Foam::globalMeshData::globalEdgeTransformedSlaves()
2227 if (!globalEdgeTransformedSlavesPtr_.valid())
2229 calcGlobalEdgeSlaves();
2231 return globalEdgeTransformedSlavesPtr_();
2235 const Foam::PackedBoolList& Foam::globalMeshData::globalEdgeOrientation() const
2237 if (!globalEdgeOrientationPtr_.valid())
2239 calcGlobalEdgeOrientation();
2241 return globalEdgeOrientationPtr_();
2245 const Foam::mapDistribute& Foam::globalMeshData::globalEdgeSlavesMap() const
2247 if (!globalEdgeSlavesMapPtr_.valid())
2249 calcGlobalEdgeSlaves();
2251 return globalEdgeSlavesMapPtr_();
2255 const Foam::globalIndex& Foam::globalMeshData::globalBoundaryFaceNumbering()
2258 if (!globalBoundaryFaceNumberingPtr_.valid())
2260 calcGlobalPointBoundaryFaces();
2262 return globalBoundaryFaceNumberingPtr_();
2266 const Foam::labelListList& Foam::globalMeshData::globalPointBoundaryFaces()
2269 if (!globalPointBoundaryFacesPtr_.valid())
2271 calcGlobalPointBoundaryFaces();
2273 return globalPointBoundaryFacesPtr_();
2277 const Foam::labelListList&
2278 Foam::globalMeshData::globalPointTransformedBoundaryFaces() const
2280 if (!globalPointTransformedBoundaryFacesPtr_.valid())
2282 calcGlobalPointBoundaryFaces();
2284 return globalPointTransformedBoundaryFacesPtr_();
2288 const Foam::mapDistribute& Foam::globalMeshData::globalPointBoundaryFacesMap()
2291 if (!globalPointBoundaryFacesMapPtr_.valid())
2293 calcGlobalPointBoundaryFaces();
2295 return globalPointBoundaryFacesMapPtr_();
2299 const Foam::labelList& Foam::globalMeshData::boundaryCells() const
2301 if (!boundaryCellsPtr_.valid())
2303 calcGlobalPointBoundaryCells();
2305 return boundaryCellsPtr_();
2309 const Foam::globalIndex& Foam::globalMeshData::globalBoundaryCellNumbering()
2312 if (!globalBoundaryCellNumberingPtr_.valid())
2314 calcGlobalPointBoundaryCells();
2316 return globalBoundaryCellNumberingPtr_();
2320 const Foam::labelListList& Foam::globalMeshData::globalPointBoundaryCells()
2323 if (!globalPointBoundaryCellsPtr_.valid())
2325 calcGlobalPointBoundaryCells();
2327 return globalPointBoundaryCellsPtr_();
2331 const Foam::labelListList&
2332 Foam::globalMeshData::globalPointTransformedBoundaryCells() const
2334 if (!globalPointTransformedBoundaryCellsPtr_.valid())
2336 calcGlobalPointBoundaryCells();
2338 return globalPointTransformedBoundaryCellsPtr_();
2342 const Foam::mapDistribute& Foam::globalMeshData::globalPointBoundaryCellsMap()
2345 if (!globalPointBoundaryCellsMapPtr_.valid())
2347 calcGlobalPointBoundaryCells();
2349 return globalPointBoundaryCellsMapPtr_();
2353 const Foam::labelListList& Foam::globalMeshData::globalCoPointSlaves() const
2355 if (!globalCoPointSlavesPtr_.valid())
2357 calcGlobalCoPointSlaves();
2359 return globalCoPointSlavesPtr_();
2363 const Foam::mapDistribute& Foam::globalMeshData::globalCoPointSlavesMap() const
2365 if (!globalCoPointSlavesMapPtr_.valid())
2367 calcGlobalCoPointSlaves();
2369 return globalCoPointSlavesMapPtr_();
2373 Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
2375 labelList& pointToGlobal,
2376 labelList& uniquePoints
2379 const indirectPrimitivePatch& cpp = coupledPatch();
2380 const globalIndex& globalCoupledPoints = globalPointNumbering();
2381 // Use collocated only
2382 const labelListList& pointSlaves = globalCoPointSlaves();
2383 const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2386 // Points are either
2387 // - master with slaves
2388 // - slave with a master
2389 // - other (since e.g. non-collocated cyclics not connected)
2391 labelList masterGlobalPoint(cpp.nPoints(), -1);
2392 forAll(masterGlobalPoint, pointI)
2394 const labelList& slavePoints = pointSlaves[pointI];
2395 if (slavePoints.size() > 0)
2397 masterGlobalPoint[pointI] = globalCoupledPoints.toGlobal(pointI);
2401 // Sync by taking max
2406 labelListList(cpp.nPoints()), // no transforms
2412 // 1. Count number of masters on my processor.
2414 PackedBoolList isMaster(mesh_.nPoints(), 1);
2415 forAll(pointSlaves, pointI)
2417 if (masterGlobalPoint[pointI] == -1)
2419 // unconnected point (e.g. from separated cyclic)
2424 masterGlobalPoint[pointI]
2425 == globalCoupledPoints.toGlobal(pointI)
2433 // connected slave point
2434 isMaster[cpp.meshPoints()[pointI]] = 0;
2438 label myUniquePoints = mesh_.nPoints() - cpp.nPoints() + nMaster;
2440 //Pout<< "Points :" << nl
2441 // << " mesh : " << mesh_.nPoints() << nl
2442 // << " of which coupled : " << cpp.nPoints() << nl
2443 // << " of which master : " << nMaster << nl
2447 // 2. Create global indexing for unique points.
2448 autoPtr<globalIndex> globalPointsPtr(new globalIndex(myUniquePoints));
2451 // 3. Assign global point numbers. Keep slaves unset.
2452 pointToGlobal.setSize(mesh_.nPoints());
2454 uniquePoints.setSize(myUniquePoints);
2457 forAll(isMaster, meshPointI)
2459 if (isMaster[meshPointI])
2461 pointToGlobal[meshPointI] = globalPointsPtr().toGlobal(nMaster);
2462 uniquePoints[nMaster] = meshPointI;
2468 // 4. Push global index for coupled points to slaves.
2470 labelList masterToGlobal(pointSlavesMap.constructSize(), -1);
2472 forAll(pointSlaves, pointI)
2474 const labelList& slaves = pointSlaves[pointI];
2476 if (slaves.size() > 0)
2478 // Duplicate master globalpoint into slave slots
2479 label meshPointI = cpp.meshPoints()[pointI];
2480 masterToGlobal[pointI] = pointToGlobal[meshPointI];
2483 masterToGlobal[slaves[i]] = masterToGlobal[pointI];
2489 pointSlavesMap.reverseDistribute(cpp.nPoints(), masterToGlobal);
2491 // On slave copy master index into overal map.
2492 forAll(pointSlaves, pointI)
2494 label meshPointI = cpp.meshPoints()[pointI];
2496 if (!isMaster[meshPointI])
2498 pointToGlobal[meshPointI] = masterToGlobal[pointI];
2503 return globalPointsPtr;
2507 Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
2509 const labelList& meshPoints,
2510 const Map<label>& meshPointMap,
2511 labelList& pointToGlobal,
2512 labelList& uniqueMeshPoints
2515 const indirectPrimitivePatch& cpp = coupledPatch();
2516 const labelListList& pointSlaves = globalCoPointSlaves();
2517 const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2520 // The patch points come in two variants:
2521 // - not on a coupled patch so guaranteed unique
2522 // - on a coupled patch
2523 // If the point is on a coupled patch the problem is that the
2524 // master-slave structure (globalPointSlaves etc.) assigns one of the
2525 // coupled points to be the master but this master point is not
2526 // necessarily on the patch itself! (it might just be connected to the
2527 // patch point via coupled patches).
2530 // Determine mapping:
2531 // - from patch point to coupled point (or -1)
2532 // - from coupled point to global patch point
2533 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2535 globalIndex globalPPoints(meshPoints.size());
2537 labelList patchToCoupled(meshPoints.size(), -1);
2539 labelList coupledToGlobalPatch(pointSlavesMap.constructSize(), -1);
2541 // Note: loop over patch since usually smaller
2542 forAll(meshPoints, patchPointI)
2544 label meshPointI = meshPoints[patchPointI];
2546 Map<label>::const_iterator iter = cpp.meshPointMap().find(meshPointI);
2548 if (iter != cpp.meshPointMap().end())
2550 patchToCoupled[patchPointI] = iter();
2551 coupledToGlobalPatch[iter()] = globalPPoints.toGlobal(patchPointI);
2556 //Pout<< "Patch:" << nl
2557 // << " points:" << meshPoints.size() << nl
2558 // << " of which on coupled patch:" << nCoupled << endl;
2561 // Determine master of connected points
2562 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2563 // Problem is that the coupled master might not be on the patch. So
2564 // work out the best patch-point master from all connected points.
2565 // - if the coupled master is on the patch it becomes the patch-point master
2566 // - else the slave with the lowest numbered patch point label
2568 // Get all data on master
2569 pointSlavesMap.distribute(coupledToGlobalPatch);
2570 forAll(pointSlaves, coupledPointI)
2572 const labelList& slaves = pointSlaves[coupledPointI];
2574 if (slaves.size() > 0)
2576 // I am master. What is the best candidate for patch-point master
2577 label masterI = labelMax;
2578 if (coupledToGlobalPatch[coupledPointI] != -1)
2580 // I am master and on the coupled patch. Use me.
2581 masterI = coupledToGlobalPatch[coupledPointI];
2585 // Get min of slaves as master.
2588 label slavePp = coupledToGlobalPatch[slaves[i]];
2589 if (slavePp != -1 && slavePp < masterI)
2596 if (masterI != labelMax)
2599 coupledToGlobalPatch[coupledPointI] = masterI;
2602 coupledToGlobalPatch[slaves[i]] = masterI;
2607 pointSlavesMap.reverseDistribute(cpp.nPoints(), coupledToGlobalPatch);
2610 // Generate compact numbering for master points
2611 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2612 // Now coupledToGlobalPatch is the globalIndex of the master point.
2613 // Now every processor can check whether they hold it and generate a
2614 // compact numbering.
2617 forAll(meshPoints, patchPointI)
2619 if (patchToCoupled[patchPointI] == -1)
2625 label coupledPointI = patchToCoupled[patchPointI];
2628 globalPPoints.toGlobal(patchPointI)
2629 == coupledToGlobalPatch[coupledPointI]
2638 autoPtr<globalIndex> globalPointsPtr(new globalIndex(nMasters));
2640 //Pout<< "Patch:" << nl
2641 // << " points:" << meshPoints.size() << nl
2642 // << " of which on coupled patch:" << nCoupled << nl
2643 // << " of which master:" << nMasters << endl;
2647 // Push back compact numbering for master point onto slaves
2648 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2650 pointToGlobal.setSize(meshPoints.size());
2652 uniqueMeshPoints.setSize(nMasters);
2654 // Sync master in global point numbering so all know the master point.
2655 // Initialise globalMaster to be -1 except at a globalMaster.
2656 labelList globalMaster(cpp.nPoints(), -1);
2659 forAll(meshPoints, patchPointI)
2661 if (patchToCoupled[patchPointI] == -1)
2663 uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
2667 label coupledPointI = patchToCoupled[patchPointI];
2670 globalPPoints.toGlobal(patchPointI)
2671 == coupledToGlobalPatch[coupledPointI]
2674 globalMaster[coupledPointI] =
2675 globalPointsPtr().toGlobal(nMasters);
2676 uniqueMeshPoints[nMasters++] = meshPoints[patchPointI];
2682 // Sync by taking max
2687 labelListList(cpp.nPoints()), // no transforms
2693 // Now everyone has the master point in globalPointsPtr numbering. Fill
2694 // in the pointToGlobal map.
2696 forAll(meshPoints, patchPointI)
2698 if (patchToCoupled[patchPointI] == -1)
2700 pointToGlobal[patchPointI] = globalPointsPtr().toGlobal(nMasters++);
2704 label coupledPointI = patchToCoupled[patchPointI];
2705 pointToGlobal[patchPointI] = globalMaster[coupledPointI];
2709 globalPPoints.toGlobal(patchPointI)
2710 == coupledToGlobalPatch[coupledPointI]
2718 return globalPointsPtr;
2722 void Foam::globalMeshData::movePoints(const pointField& newPoints)
2724 // Topology does not change and we don't store any geometry so nothing
2725 // needs to be done.
2726 // Only global transformations might change but this is not really
2731 // Update all data after morph
2732 void Foam::globalMeshData::updateMesh()
2734 // Clear out old data
2737 // Do processor patch addressing
2740 scalar tolDim = matchTol_ * mesh_.bounds().mag();
2744 Pout<< "globalMeshData : merge dist:" << tolDim << endl;
2747 // Total number of faces.
2748 nTotalFaces_ = returnReduce(mesh_.nFaces(), sumOp<label>());
2752 Pout<< "globalMeshData : nTotalFaces_:" << nTotalFaces_ << endl;
2755 nTotalCells_ = returnReduce(mesh_.nCells(), sumOp<label>());
2759 Pout<< "globalMeshData : nTotalCells_:" << nTotalCells_ << endl;
2762 nTotalPoints_ = returnReduce(mesh_.nPoints(), sumOp<label>());
2766 Pout<< "globalMeshData : nTotalPoints_:" << nTotalPoints_ << endl;
2771 // ************************************************************************* //