1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "syncTools.H"
28 #include "processorPolyPatch.H"
29 #include "cyclicPolyPatch.H"
30 #include "globalMeshData.H"
31 #include "contiguous.H"
32 #include "transform.H"
34 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
37 void Foam::syncTools::separateList
39 const vectorField& separation,
46 void Foam::syncTools::separateList
48 const vectorField& separation,
55 void Foam::syncTools::separateList
57 const vectorField& separation,
63 // Combine val with existing value at index
64 template <class T, class CombineOp>
65 void Foam::syncTools::combine
73 typename Map<T>::iterator iter = pointValues.find(index);
75 if (iter != pointValues.end())
81 pointValues.insert(index, val);
86 // Combine val with existing value at (implicit index) e.
87 template <class T, class CombineOp>
88 void Foam::syncTools::combine
90 EdgeMap<T>& edgeValues,
96 typename EdgeMap<T>::iterator iter = edgeValues.find(index);
98 if (iter != edgeValues.end())
104 edgeValues.insert(index, val);
109 template <class T, class CombineOp>
110 void Foam::syncTools::syncPointMap
112 const polyMesh& mesh,
113 Map<T>& pointValues, // from mesh point label to value
114 const CombineOp& cop,
115 const bool applySeparation
118 const polyBoundaryMesh& patches = mesh.boundaryMesh();
120 if (!hasCouples(patches))
125 // Is there any coupled patch with transformation?
126 bool hasTransformation = false;
128 if (Pstream::parRun())
132 forAll(patches, patchI)
136 isA<processorPolyPatch>(patches[patchI])
137 && patches[patchI].nPoints() > 0
140 const processorPolyPatch& procPatch =
141 refCast<const processorPolyPatch>(patches[patchI]);
143 // Get data per patchPoint in neighbouring point numbers.
145 const labelList& meshPts = procPatch.meshPoints();
146 const labelList& nbrPts = procPatch.neighbPoints();
148 // Extract local values. Create map from nbrPoint to value.
149 // Note: how small initial size?
150 Map<T> patchInfo(meshPts.size() / 20);
154 typename Map<T>::const_iterator iter =
155 pointValues.find(meshPts[i]);
157 if (iter != pointValues.end())
161 patchInfo.insert(nbrPts[i], iter());
166 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
167 toNeighb << patchInfo;
172 // Receive and combine.
174 forAll(patches, patchI)
178 isA<processorPolyPatch>(patches[patchI])
179 && patches[patchI].nPoints() > 0
182 const processorPolyPatch& procPatch =
183 refCast<const processorPolyPatch>(patches[patchI]);
184 checkTransform(procPatch, applySeparation);
186 IPstream fromNb(Pstream::blocking, procPatch.neighbProcNo());
187 Map<T> nbrPatchInfo(fromNb);
189 if (!procPatch.parallel())
191 hasTransformation = true;
192 transformList(procPatch.forwardT(), nbrPatchInfo);
194 else if (applySeparation && procPatch.separated())
196 hasTransformation = true;
197 separateList(-procPatch.separation(), nbrPatchInfo);
200 const labelList& meshPts = procPatch.meshPoints();
202 // Only update those values which come from neighbour
215 meshPts[nbrIter.key()],
224 forAll(patches, patchI)
226 if (isA<cyclicPolyPatch>(patches[patchI]))
228 const cyclicPolyPatch& cycPatch =
229 refCast<const cyclicPolyPatch>(patches[patchI]);
230 checkTransform(cycPatch, applySeparation);
232 const edgeList& coupledPoints = cycPatch.coupledPoints();
233 const labelList& meshPts = cycPatch.meshPoints();
235 // Extract local values. Create map from nbrPoint to value.
236 Map<T> half0Values(meshPts.size() / 20);
237 Map<T> half1Values(meshPts.size() / 20);
239 forAll(coupledPoints, i)
241 const edge& e = coupledPoints[i];
243 typename Map<T>::const_iterator point0Fnd =
244 pointValues.find(meshPts[e[0]]);
246 if (point0Fnd != pointValues.end())
248 half0Values.insert(i, point0Fnd());
251 typename Map<T>::const_iterator point1Fnd =
252 pointValues.find(meshPts[e[1]]);
254 if (point1Fnd != pointValues.end())
256 half1Values.insert(i, point1Fnd());
260 if (!cycPatch.parallel())
262 hasTransformation = true;
263 transformList(cycPatch.reverseT(), half0Values);
264 transformList(cycPatch.forwardT(), half1Values);
266 else if (applySeparation && cycPatch.separated())
268 hasTransformation = true;
270 const vectorField& v = cycPatch.coupledPolyPatch::separation();
271 separateList(v, half0Values);
272 separateList(-v, half1Values);
275 forAll(coupledPoints, i)
277 const edge& e = coupledPoints[i];
279 typename Map<T>::const_iterator half1Fnd = half1Values.find(i);
281 if (half1Fnd != half1Values.end())
292 typename Map<T>::const_iterator half0Fnd = half0Values.find(i);
294 if (half0Fnd != half0Values.end())
308 // Note: hasTransformation is only used for warning messages so
309 // reduction not strictly nessecary.
310 // reduce(hasTransformation, orOp<bool>());
312 // Synchronize multiple shared points.
313 const globalMeshData& pd = mesh.globalData();
315 if (pd.nGlobalPoints() > 0)
317 if (hasTransformation)
321 "syncTools<class T, class CombineOp>::syncPointMap"
322 "(const polyMesh&, Map<T>&, const CombineOp&"
324 ) << "There are decomposed cyclics in this mesh with"
325 << " transformations." << endl
326 << "This is not supported. The result will be incorrect"
329 // meshPoint per local index
330 const labelList& sharedPtLabels = pd.sharedPointLabels();
331 // global shared index per local index
332 const labelList& sharedPtAddr = pd.sharedPointAddr();
334 // Values on shared points. Keyed on global shared index.
335 Map<T> sharedPointValues(sharedPtAddr.size());
338 // Fill my entries in the shared points
339 forAll(sharedPtLabels, i)
341 label meshPointI = sharedPtLabels[i];
343 typename Map<T>::const_iterator fnd =
344 pointValues.find(meshPointI);
346 if (fnd != pointValues.end())
352 sharedPtAddr[i], // index
360 if (Pstream::parRun())
362 if (Pstream::master())
364 // Receive the edges using shared points from the slave.
367 int slave=Pstream::firstSlave();
368 slave<=Pstream::lastSlave();
372 IPstream fromSlave(Pstream::blocking, slave);
373 Map<T> nbrValues(fromSlave);
375 // Merge neighbouring values with my values
376 forAllConstIter(typename Map<T>, nbrValues, iter)
391 int slave=Pstream::firstSlave();
392 slave<=Pstream::lastSlave();
396 OPstream toSlave(Pstream::blocking, slave);
397 toSlave << sharedPointValues;
409 toMaster << sharedPointValues;
411 // Receive merged values
418 fromMaster >> sharedPointValues;
424 // Merge sharedPointValues (keyed on sharedPointAddr) into
425 // pointValues (keyed on mesh points).
427 // Map from global shared index to meshpoint
428 Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
429 forAll(sharedPtAddr, i)
431 sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
434 forAllConstIter(Map<label>, sharedToMeshPoint, iter)
436 // Do I have a value for my shared point
437 typename Map<T>::const_iterator sharedFnd =
438 sharedPointValues.find(iter.key());
440 if (sharedFnd != sharedPointValues.end())
455 template <class T, class CombineOp>
456 void Foam::syncTools::syncEdgeMap
458 const polyMesh& mesh,
459 EdgeMap<T>& edgeValues,
460 const CombineOp& cop,
461 const bool applySeparation
464 const polyBoundaryMesh& patches = mesh.boundaryMesh();
466 if (!hasCouples(patches))
472 // Do synchronisation without constructing globalEdge addressing
473 // (since this constructs mesh edge addressing)
476 // Swap proc patch info
477 // ~~~~~~~~~~~~~~~~~~~~
479 if (Pstream::parRun())
483 forAll(patches, patchI)
487 isA<processorPolyPatch>(patches[patchI])
488 && patches[patchI].nEdges() > 0
491 const processorPolyPatch& procPatch =
492 refCast<const processorPolyPatch>(patches[patchI]);
494 // Get data per patch edge in neighbouring edge.
496 const edgeList& edges = procPatch.edges();
497 const labelList& meshPts = procPatch.meshPoints();
498 const labelList& nbrPts = procPatch.neighbPoints();
500 EdgeMap<T> patchInfo(edges.size() / 20);
504 const edge& e = edges[i];
505 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
507 typename EdgeMap<T>::const_iterator iter =
508 edgeValues.find(meshEdge);
510 if (iter != edgeValues.end())
512 const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
514 if (nbrEdge[0] >= 0 && nbrEdge[1] >= 0)
516 patchInfo.insert(nbrEdge, iter());
521 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
522 toNeighb << patchInfo;
527 // Receive and combine.
529 forAll(patches, patchI)
533 isA<processorPolyPatch>(patches[patchI])
534 && patches[patchI].nEdges() > 0
537 const processorPolyPatch& procPatch =
538 refCast<const processorPolyPatch>(patches[patchI]);
539 checkTransform(procPatch, applySeparation);
541 const labelList& meshPts = procPatch.meshPoints();
543 IPstream fromNbr(Pstream::blocking, procPatch.neighbProcNo());
544 EdgeMap<T> nbrPatchInfo(fromNbr);
546 if (!procPatch.parallel())
548 transformList(procPatch.forwardT(), nbrPatchInfo);
550 else if (applySeparation && procPatch.separated())
552 separateList(-procPatch.separation(), nbrPatchInfo);
555 // Only update those values which come from neighbour
564 const edge& e = nbrIter.key();
565 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
583 forAll(patches, patchI)
585 if (isA<cyclicPolyPatch>(patches[patchI]))
587 const cyclicPolyPatch& cycPatch =
588 refCast<const cyclicPolyPatch>(patches[patchI]);
589 checkTransform(cycPatch, applySeparation);
591 const edgeList& coupledEdges = cycPatch.coupledEdges();
592 const labelList& meshPts = cycPatch.meshPoints();
593 const edgeList& edges = cycPatch.edges();
595 // Extract local values. Create map from nbrPoint to value.
596 Map<T> half0Values(meshPts.size() / 20);
597 Map<T> half1Values(meshPts.size() / 20);
599 forAll(coupledEdges, i)
601 const edge& twoEdges = coupledEdges[i];
604 const edge& e0 = edges[twoEdges[0]];
605 const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
607 typename EdgeMap<T>::const_iterator iter =
608 edgeValues.find(meshEdge0);
610 if (iter != edgeValues.end())
612 half0Values.insert(i, iter());
616 const edge& e1 = edges[twoEdges[1]];
617 const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
619 typename EdgeMap<T>::const_iterator iter =
620 edgeValues.find(meshEdge1);
622 if (iter != edgeValues.end())
624 half1Values.insert(i, iter());
632 if (!cycPatch.parallel())
634 transformList(cycPatch.reverseT(), half0Values);
635 transformList(cycPatch.forwardT(), half1Values);
637 else if (applySeparation && cycPatch.separated())
639 const vectorField& v = cycPatch.coupledPolyPatch::separation();
640 separateList(v, half0Values);
641 separateList(-v, half1Values);
645 // Extract and combine information
647 forAll(coupledEdges, i)
649 const edge& twoEdges = coupledEdges[i];
651 typename Map<T>::const_iterator half1Fnd =
654 if (half1Fnd != half1Values.end())
656 const edge& e0 = edges[twoEdges[0]];
657 const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
668 typename Map<T>::const_iterator half0Fnd =
670 if (half0Fnd != half0Values.end())
672 const edge& e1 = edges[twoEdges[1]];
673 const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
687 // Synchronize multiple shared points.
688 // Problem is that we don't want to construct shared edges so basically
689 // we do here like globalMeshData but then using sparse edge representation
690 // (EdgeMap instead of mesh.edges())
692 const globalMeshData& pd = mesh.globalData();
693 const labelList& sharedPtAddr = pd.sharedPointAddr();
694 const labelList& sharedPtLabels = pd.sharedPointLabels();
696 // 1. Create map from meshPoint to globalShared index.
697 Map<label> meshToShared(2*sharedPtLabels.size());
698 forAll(sharedPtLabels, i)
700 meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
703 // Values on shared points. From two sharedPtAddr indices to a value.
704 EdgeMap<T> sharedEdgeValues(meshToShared.size());
706 // From shared edge to mesh edge. Used for merging later on.
707 EdgeMap<edge> potentialSharedEdge(meshToShared.size());
709 // 2. Find any edges using two global shared points. These will always be
710 // on the outside of the mesh. (though might not be on coupled patch
711 // if is single edge and not on coupled face)
712 // Store value (if any) on sharedEdgeValues
713 for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
715 const face& f = mesh.faces()[faceI];
720 label v1 = f[f.fcIndex(fp)];
722 Map<label>::const_iterator v0Fnd = meshToShared.find(v0);
724 if (v0Fnd != meshToShared.end())
726 Map<label>::const_iterator v1Fnd = meshToShared.find(v1);
728 if (v1Fnd != meshToShared.end())
730 const edge meshEdge(v0, v1);
732 // edge in shared point labels
733 const edge sharedEdge(v0Fnd(), v1Fnd());
735 // Store mesh edge as a potential shared edge.
736 potentialSharedEdge.insert(sharedEdge, meshEdge);
738 typename EdgeMap<T>::const_iterator edgeFnd =
739 edgeValues.find(meshEdge);
741 if (edgeFnd != edgeValues.end())
743 // edge exists in edgeValues. See if already in map
744 // (since on same processor, e.g. cyclic)
759 // Now sharedEdgeValues will contain per potential sharedEdge the value.
760 // (potential since an edge having two shared points is not nessecary a
762 // Reduce this on the master.
764 if (Pstream::parRun())
766 if (Pstream::master())
768 // Receive the edges using shared points from the slave.
771 int slave=Pstream::firstSlave();
772 slave<=Pstream::lastSlave();
776 IPstream fromSlave(Pstream::blocking, slave);
777 EdgeMap<T> nbrValues(fromSlave);
779 // Merge neighbouring values with my values
780 forAllConstIter(typename EdgeMap<T>, nbrValues, iter)
795 int slave=Pstream::firstSlave();
796 slave<=Pstream::lastSlave();
801 OPstream toSlave(Pstream::blocking, slave);
802 toSlave << sharedEdgeValues;
809 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
810 toMaster << sharedEdgeValues;
812 // Receive merged values
814 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
815 fromMaster >> sharedEdgeValues;
821 // Merge sharedEdgeValues (keyed on sharedPointAddr) into edgeValues
822 // (keyed on mesh points).
824 // Loop over all my shared edges.
825 forAllConstIter(typename EdgeMap<edge>, potentialSharedEdge, iter)
827 const edge& sharedEdge = iter.key();
828 const edge& meshEdge = iter();
830 // Do I have a value for the shared edge?
831 typename EdgeMap<T>::const_iterator sharedFnd =
832 sharedEdgeValues.find(sharedEdge);
834 if (sharedFnd != sharedEdgeValues.end())
848 template <class T, class CombineOp>
849 void Foam::syncTools::syncPointList
851 const polyMesh& mesh,
852 UList<T>& pointValues,
853 const CombineOp& cop,
855 const bool applySeparation
858 if (pointValues.size() != mesh.nPoints())
862 "syncTools<class T, class CombineOp>::syncPointList"
863 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
865 ) << "Number of values " << pointValues.size()
866 << " is not equal to the number of points in the mesh "
867 << mesh.nPoints() << abort(FatalError);
870 const polyBoundaryMesh& patches = mesh.boundaryMesh();
872 if (!hasCouples(patches))
877 // Is there any coupled patch with transformation?
878 bool hasTransformation = false;
880 if (Pstream::parRun())
884 forAll(patches, patchI)
888 isA<processorPolyPatch>(patches[patchI])
889 && patches[patchI].nPoints() > 0
892 const processorPolyPatch& procPatch =
893 refCast<const processorPolyPatch>(patches[patchI]);
895 // Get data per patchPoint in neighbouring point numbers.
896 List<T> patchInfo(procPatch.nPoints(), nullValue);
898 const labelList& meshPts = procPatch.meshPoints();
899 const labelList& nbrPts = procPatch.neighbPoints();
901 forAll(nbrPts, pointI)
903 label nbrPointI = nbrPts[pointI];
904 if (nbrPointI >= 0 && nbrPointI < patchInfo.size())
906 patchInfo[nbrPointI] = pointValues[meshPts[pointI]];
910 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
916 // Receive and combine.
918 forAll(patches, patchI)
922 isA<processorPolyPatch>(patches[patchI])
923 && patches[patchI].nPoints() > 0
926 const processorPolyPatch& procPatch =
927 refCast<const processorPolyPatch>(patches[patchI]);
928 checkTransform(procPatch, applySeparation);
930 List<T> nbrPatchInfo(procPatch.nPoints());
932 // We do not know the number of points on the other side
933 // so cannot use Pstream::read.
937 procPatch.neighbProcNo()
939 fromNbr >> nbrPatchInfo;
941 // Null any value which is not on neighbouring processor
942 nbrPatchInfo.setSize(procPatch.nPoints(), nullValue);
944 if (!procPatch.parallel())
946 hasTransformation = true;
947 transformList(procPatch.forwardT(), nbrPatchInfo);
949 else if (applySeparation && procPatch.separated())
951 hasTransformation = true;
952 separateList(-procPatch.separation(), nbrPatchInfo);
955 const labelList& meshPts = procPatch.meshPoints();
957 forAll(meshPts, pointI)
959 label meshPointI = meshPts[pointI];
960 cop(pointValues[meshPointI], nbrPatchInfo[pointI]);
967 forAll(patches, patchI)
969 if (isA<cyclicPolyPatch>(patches[patchI]))
971 const cyclicPolyPatch& cycPatch =
972 refCast<const cyclicPolyPatch>(patches[patchI]);
974 checkTransform(cycPatch, applySeparation);
976 const edgeList& coupledPoints = cycPatch.coupledPoints();
977 const labelList& meshPts = cycPatch.meshPoints();
979 List<T> half0Values(coupledPoints.size());
980 List<T> half1Values(coupledPoints.size());
982 forAll(coupledPoints, i)
984 const edge& e = coupledPoints[i];
986 label point0 = meshPts[e[0]];
987 label point1 = meshPts[e[1]];
989 half0Values[i] = pointValues[point0];
990 half1Values[i] = pointValues[point1];
993 if (!cycPatch.parallel())
995 hasTransformation = true;
996 transformList(cycPatch.reverseT(), half0Values);
997 transformList(cycPatch.forwardT(), half1Values);
999 else if (applySeparation && cycPatch.separated())
1001 hasTransformation = true;
1002 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1003 separateList(v, half0Values);
1004 separateList(-v, half1Values);
1007 forAll(coupledPoints, i)
1009 const edge& e = coupledPoints[i];
1011 label point0 = meshPts[e[0]];
1012 label point1 = meshPts[e[1]];
1014 cop(pointValues[point0], half1Values[i]);
1015 cop(pointValues[point1], half0Values[i]);
1020 //- Note: hasTransformation is only used for warning messages so
1021 // reduction not strictly nessecary.
1022 //reduce(hasTransformation, orOp<bool>());
1024 // Synchronize multiple shared points.
1025 const globalMeshData& pd = mesh.globalData();
1027 if (pd.nGlobalPoints() > 0)
1029 if (hasTransformation)
1033 "syncTools<class T, class CombineOp>::syncPointList"
1034 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1036 ) << "There are decomposed cyclics in this mesh with"
1037 << " transformations." << endl
1038 << "This is not supported. The result will be incorrect"
1043 // Values on shared points.
1044 List<T> sharedPts(pd.nGlobalPoints(), nullValue);
1046 forAll(pd.sharedPointLabels(), i)
1048 label meshPointI = pd.sharedPointLabels()[i];
1049 // Fill my entries in the shared points
1050 sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
1053 // Combine on master.
1054 Pstream::listCombineGather(sharedPts, cop);
1055 Pstream::listCombineScatter(sharedPts);
1057 // Now we will all have the same information. Merge it back with
1058 // my local information.
1059 forAll(pd.sharedPointLabels(), i)
1061 label meshPointI = pd.sharedPointLabels()[i];
1062 pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
1068 template <class T, class CombineOp>
1069 void Foam::syncTools::syncPointList
1071 const polyMesh& mesh,
1072 const labelList& meshPoints,
1073 UList<T>& pointValues,
1074 const CombineOp& cop,
1076 const bool applySeparation
1079 if (pointValues.size() != meshPoints.size())
1083 "syncTools<class T, class CombineOp>::syncPointList"
1084 "(const polyMesh&, const labelList&, UList<T>&, const CombineOp&"
1085 ", const T&, const bool)"
1086 ) << "Number of values " << pointValues.size()
1087 << " is not equal to the number of points "
1088 << meshPoints.size() << abort(FatalError);
1091 if (!hasCouples(mesh.boundaryMesh()))
1096 List<T> meshValues(mesh.nPoints(), nullValue);
1098 forAll(meshPoints, i)
1100 meshValues[meshPoints[i]] = pointValues[i];
1103 syncTools::syncPointList
1108 nullValue, // null value
1109 applySeparation // separation
1112 forAll(meshPoints, i)
1114 pointValues[i] = meshValues[meshPoints[i]];
1119 template <class T, class CombineOp>
1120 void Foam::syncTools::syncEdgeList
1122 const polyMesh& mesh,
1123 UList<T>& edgeValues,
1124 const CombineOp& cop,
1126 const bool applySeparation
1129 if (edgeValues.size() != mesh.nEdges())
1133 "syncTools<class T, class CombineOp>::syncEdgeList"
1134 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1136 ) << "Number of values " << edgeValues.size()
1137 << " is not equal to the number of edges in the mesh "
1138 << mesh.nEdges() << abort(FatalError);
1141 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1143 if (!hasCouples(patches))
1148 // Is there any coupled patch with transformation?
1149 bool hasTransformation = false;
1151 if (Pstream::parRun())
1155 forAll(patches, patchI)
1159 isA<processorPolyPatch>(patches[patchI])
1160 && patches[patchI].nEdges() > 0
1163 const processorPolyPatch& procPatch =
1164 refCast<const processorPolyPatch>(patches[patchI]);
1166 const labelList& meshEdges = procPatch.meshEdges();
1167 const labelList& neighbEdges = procPatch.neighbEdges();
1169 // Get region per patch edge in neighbouring edge numbers.
1170 List<T> patchInfo(procPatch.nEdges(), nullValue);
1172 forAll(neighbEdges, edgeI)
1174 label nbrEdgeI = neighbEdges[edgeI];
1176 if (nbrEdgeI >= 0 && nbrEdgeI < patchInfo.size())
1178 patchInfo[nbrEdgeI] = edgeValues[meshEdges[edgeI]];
1182 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1187 // Receive and combine.
1189 forAll(patches, patchI)
1193 isA<processorPolyPatch>(patches[patchI])
1194 && patches[patchI].nEdges() > 0
1197 const processorPolyPatch& procPatch =
1198 refCast<const processorPolyPatch>(patches[patchI]);
1200 checkTransform(procPatch, applySeparation);
1202 const labelList& meshEdges = procPatch.meshEdges();
1204 // Receive from neighbour. Is per patch edge the region of the
1205 // neighbouring patch edge.
1206 List<T> nbrPatchInfo(procPatch.nEdges());
1212 procPatch.neighbProcNo()
1214 fromNeighb >> nbrPatchInfo;
1216 // Null any value which is not on neighbouring processor
1217 nbrPatchInfo.setSize(procPatch.nEdges(), nullValue);
1219 if (!procPatch.parallel())
1221 hasTransformation = true;
1222 transformList(procPatch.forwardT(), nbrPatchInfo);
1224 else if (applySeparation && procPatch.separated())
1226 hasTransformation = true;
1227 separateList(-procPatch.separation(), nbrPatchInfo);
1230 forAll(meshEdges, edgeI)
1232 label meshEdgeI = meshEdges[edgeI];
1234 cop(edgeValues[meshEdgeI], nbrPatchInfo[edgeI]);
1241 forAll(patches, patchI)
1243 if (isA<cyclicPolyPatch>(patches[patchI]))
1245 const cyclicPolyPatch& cycPatch =
1246 refCast<const cyclicPolyPatch>(patches[patchI]);
1248 checkTransform(cycPatch, applySeparation);
1250 const edgeList& coupledEdges = cycPatch.coupledEdges();
1251 const labelList& meshEdges = cycPatch.meshEdges();
1253 List<T> half0Values(coupledEdges.size());
1254 List<T> half1Values(coupledEdges.size());
1256 forAll(coupledEdges, i)
1258 const edge& e = coupledEdges[i];
1260 label meshEdge0 = meshEdges[e[0]];
1261 label meshEdge1 = meshEdges[e[1]];
1263 half0Values[i] = edgeValues[meshEdge0];
1264 half1Values[i] = edgeValues[meshEdge1];
1267 if (!cycPatch.parallel())
1269 hasTransformation = true;
1270 transformList(cycPatch.reverseT(), half0Values);
1271 transformList(cycPatch.forwardT(), half1Values);
1273 else if (applySeparation && cycPatch.separated())
1275 hasTransformation = true;
1277 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1278 separateList(v, half0Values);
1279 separateList(-v, half1Values);
1282 forAll(coupledEdges, i)
1284 const edge& e = coupledEdges[i];
1286 label meshEdge0 = meshEdges[e[0]];
1287 label meshEdge1 = meshEdges[e[1]];
1289 cop(edgeValues[meshEdge0], half1Values[i]);
1290 cop(edgeValues[meshEdge1], half0Values[i]);
1295 //- Note: hasTransformation is only used for warning messages so
1296 // reduction not strictly nessecary.
1297 //reduce(hasTransformation, orOp<bool>());
1299 // Do the multiple shared edges
1300 const globalMeshData& pd = mesh.globalData();
1302 if (pd.nGlobalEdges() > 0)
1304 if (hasTransformation)
1308 "syncTools<class T, class CombineOp>::syncEdgeList"
1309 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1311 ) << "There are decomposed cyclics in this mesh with"
1312 << " transformations." << endl
1313 << "This is not supported. The result will be incorrect"
1317 // Values on shared edges.
1318 List<T> sharedPts(pd.nGlobalEdges(), nullValue);
1320 forAll(pd.sharedEdgeLabels(), i)
1322 label meshEdgeI = pd.sharedEdgeLabels()[i];
1324 // Fill my entries in the shared edges
1325 sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
1328 // Combine on master.
1329 Pstream::listCombineGather(sharedPts, cop);
1330 Pstream::listCombineScatter(sharedPts);
1332 // Now we will all have the same information. Merge it back with
1333 // my local information.
1334 forAll(pd.sharedEdgeLabels(), i)
1336 label meshEdgeI = pd.sharedEdgeLabels()[i];
1337 edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
1343 template <class T, class CombineOp>
1344 void Foam::syncTools::syncBoundaryFaceList
1346 const polyMesh& mesh,
1347 UList<T>& faceValues,
1348 const CombineOp& cop,
1349 const bool applySeparation
1352 const label nBFaces = mesh.nFaces() - mesh.nInternalFaces();
1354 if (faceValues.size() != nBFaces)
1358 "syncTools<class T, class CombineOp>::syncBoundaryFaceList"
1359 "(const polyMesh&, UList<T>&, const CombineOp&"
1361 ) << "Number of values " << faceValues.size()
1362 << " is not equal to the number of boundary faces in the mesh "
1363 << nBFaces << abort(FatalError);
1366 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1368 if (!hasCouples(patches))
1374 if (Pstream::parRun())
1378 forAll(patches, patchI)
1382 isA<processorPolyPatch>(patches[patchI])
1383 && patches[patchI].size() > 0
1386 const processorPolyPatch& procPatch =
1387 refCast<const processorPolyPatch>(patches[patchI]);
1389 label patchStart = procPatch.start()-mesh.nInternalFaces();
1391 if (contiguous<T>())
1396 procPatch.neighbProcNo(),
1397 reinterpret_cast<const char*>(&faceValues[patchStart]),
1398 procPatch.size()*sizeof(T)
1403 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1405 SubList<T>(faceValues, procPatch.size(), patchStart);
1411 // Receive and combine.
1413 forAll(patches, patchI)
1417 isA<processorPolyPatch>(patches[patchI])
1418 && patches[patchI].size() > 0
1421 const processorPolyPatch& procPatch =
1422 refCast<const processorPolyPatch>(patches[patchI]);
1424 List<T> nbrPatchInfo(procPatch.size());
1426 if (contiguous<T>())
1431 procPatch.neighbProcNo(),
1432 reinterpret_cast<char*>(nbrPatchInfo.begin()),
1433 nbrPatchInfo.byteSize()
1441 procPatch.neighbProcNo()
1443 fromNeighb >> nbrPatchInfo;
1446 if (!procPatch.parallel())
1448 transformList(procPatch.forwardT(), nbrPatchInfo);
1450 else if (applySeparation && procPatch.separated())
1452 separateList(-procPatch.separation(), nbrPatchInfo);
1456 label bFaceI = procPatch.start()-mesh.nInternalFaces();
1458 forAll(nbrPatchInfo, i)
1460 cop(faceValues[bFaceI++], nbrPatchInfo[i]);
1467 forAll(patches, patchI)
1469 if (isA<cyclicPolyPatch>(patches[patchI]))
1471 const cyclicPolyPatch& cycPatch =
1472 refCast<const cyclicPolyPatch>(patches[patchI]);
1474 label patchStart = cycPatch.start()-mesh.nInternalFaces();
1476 label half = cycPatch.size()/2;
1477 label half1Start = patchStart+half;
1479 List<T> half0Values(SubList<T>(faceValues, half, patchStart));
1480 List<T> half1Values(SubList<T>(faceValues, half, half1Start));
1482 if (!cycPatch.parallel())
1484 transformList(cycPatch.reverseT(), half0Values);
1485 transformList(cycPatch.forwardT(), half1Values);
1487 else if (applySeparation && cycPatch.separated())
1489 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1490 separateList(v, half0Values);
1491 separateList(-v, half1Values);
1494 label i0 = patchStart;
1495 forAll(half1Values, i)
1497 cop(faceValues[i0++], half1Values[i]);
1500 label i1 = half1Start;
1501 forAll(half0Values, i)
1503 cop(faceValues[i1++], half0Values[i]);
1510 template <class T, class CombineOp>
1511 void Foam::syncTools::syncFaceList
1513 const polyMesh& mesh,
1514 UList<T>& faceValues,
1515 const CombineOp& cop,
1516 const bool applySeparation
1519 if (faceValues.size() != mesh.nFaces())
1523 "syncTools<class T, class CombineOp>::syncFaceList"
1524 "(const polyMesh&, UList<T>&, const CombineOp&"
1526 ) << "Number of values " << faceValues.size()
1527 << " is not equal to the number of faces in the mesh "
1528 << mesh.nFaces() << abort(FatalError);
1531 SubList<T> bndValues
1534 mesh.nFaces()-mesh.nInternalFaces(),
1535 mesh.nInternalFaces()
1538 syncBoundaryFaceList
1549 void Foam::syncTools::swapBoundaryFaceList
1551 const polyMesh& mesh,
1552 UList<T>& faceValues,
1553 const bool applySeparation
1556 syncBoundaryFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
1561 void Foam::syncTools::swapFaceList
1563 const polyMesh& mesh,
1564 UList<T>& faceValues,
1565 const bool applySeparation
1568 syncFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
1572 template <unsigned nBits, class CombineOp>
1573 void Foam::syncTools::syncFaceList
1575 const polyMesh& mesh,
1576 PackedList<nBits>& faceValues,
1577 const CombineOp& cop
1580 if (faceValues.size() != mesh.nFaces())
1584 "syncTools<unsigned nBits, class CombineOp>::syncFaceList"
1585 "(const polyMesh&, PackedList<nBits>&, const CombineOp&)"
1586 ) << "Number of values " << faceValues.size()
1587 << " is not equal to the number of faces in the mesh "
1588 << mesh.nFaces() << abort(FatalError);
1591 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1593 if (!hasCouples(patches))
1598 // Patch data (proc patches only).
1599 List<List<unsigned int> > patchValues(patches.size());
1601 if (Pstream::parRun())
1605 forAll(patches, patchI)
1609 isA<processorPolyPatch>(patches[patchI])
1610 && patches[patchI].size() > 0
1613 const processorPolyPatch& procPatch =
1614 refCast<const processorPolyPatch>(patches[patchI]);
1616 patchValues[patchI].setSize(procPatch.size());
1617 forAll(procPatch, i)
1619 patchValues[patchI][i] =
1620 faceValues.get(procPatch.start()+i);
1623 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1624 toNbr << patchValues[patchI];
1629 // Receive and combine.
1631 forAll(patches, patchI)
1635 isA<processorPolyPatch>(patches[patchI])
1636 && patches[patchI].size() > 0
1639 const processorPolyPatch& procPatch =
1640 refCast<const processorPolyPatch>(patches[patchI]);
1646 procPatch.neighbProcNo()
1648 fromNbr >> patchValues[patchI];
1651 // Combine (bitwise)
1652 forAll(procPatch, i)
1654 unsigned int patchVal = patchValues[patchI][i];
1655 label meshFaceI = procPatch.start()+i;
1656 unsigned int faceVal = faceValues.get(meshFaceI);
1657 cop(faceVal, patchVal);
1658 faceValues.set(meshFaceI, faceVal);
1665 forAll(patches, patchI)
1667 if (isA<cyclicPolyPatch>(patches[patchI]))
1669 const cyclicPolyPatch& cycPatch =
1670 refCast<const cyclicPolyPatch>(patches[patchI]);
1672 label half = cycPatch.size()/2;
1674 for (label i = 0; i < half; i++)
1676 label meshFace0 = cycPatch.start()+i;
1677 unsigned int val0 = faceValues.get(meshFace0);
1678 label meshFace1 = meshFace0 + half;
1679 unsigned int val1 = faceValues.get(meshFace1);
1681 unsigned int t = val0;
1683 faceValues.set(meshFace0, t);
1686 faceValues.set(meshFace1, val1);
1693 template <unsigned nBits>
1694 void Foam::syncTools::swapFaceList
1696 const polyMesh& mesh,
1697 PackedList<nBits>& faceValues
1700 syncFaceList(mesh, faceValues, eqOp<unsigned int>());
1704 template <unsigned nBits, class CombineOp>
1705 void Foam::syncTools::syncPointList
1707 const polyMesh& mesh,
1708 PackedList<nBits>& pointValues,
1709 const CombineOp& cop,
1710 const unsigned int nullValue
1713 if (pointValues.size() != mesh.nPoints())
1717 "syncTools<unsigned nBits, class CombineOp>::syncPointList"
1718 "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
1719 ", const unsigned int&)"
1720 ) << "Number of values " << pointValues.size()
1721 << " is not equal to the number of points in the mesh "
1722 << mesh.nPoints() << abort(FatalError);
1725 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1727 if (!hasCouples(patches))
1732 // Patch data (proc patches only).
1733 List<List<unsigned int> > patchValues(patches.size());
1735 if (Pstream::parRun())
1739 forAll(patches, patchI)
1743 isA<processorPolyPatch>(patches[patchI])
1744 && patches[patchI].nPoints() > 0
1747 const processorPolyPatch& procPatch =
1748 refCast<const processorPolyPatch>(patches[patchI]);
1750 patchValues[patchI].setSize(procPatch.nPoints());
1751 patchValues[patchI] = nullValue;
1753 const labelList& meshPts = procPatch.meshPoints();
1754 const labelList& nbrPts = procPatch.neighbPoints();
1756 forAll(nbrPts, pointI)
1758 label nbrPointI = nbrPts[pointI];
1759 if (nbrPointI >= 0 && nbrPointI < procPatch.nPoints())
1761 patchValues[patchI][nbrPointI] =
1762 pointValues.get(meshPts[pointI]);
1766 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1767 toNbr << patchValues[patchI];
1772 // Receive and combine.
1774 forAll(patches, patchI)
1778 isA<processorPolyPatch>(patches[patchI])
1779 && patches[patchI].nPoints() > 0
1782 const processorPolyPatch& procPatch =
1783 refCast<const processorPolyPatch>(patches[patchI]);
1786 // We do not know the number of points on the other side
1787 // so cannot use Pstream::read.
1791 procPatch.neighbProcNo()
1793 fromNbr >> patchValues[patchI];
1796 // Null any value which is not on neighbouring processor
1797 patchValues[patchI].setSize(procPatch.nPoints(), nullValue);
1799 const labelList& meshPts = procPatch.meshPoints();
1801 forAll(meshPts, pointI)
1803 label meshPointI = meshPts[pointI];
1804 unsigned int pointVal = pointValues.get(meshPointI);
1805 cop(pointVal, patchValues[patchI][pointI]);
1806 pointValues.set(meshPointI, pointVal);
1813 forAll(patches, patchI)
1815 if (isA<cyclicPolyPatch>(patches[patchI]))
1817 const cyclicPolyPatch& cycPatch =
1818 refCast<const cyclicPolyPatch>(patches[patchI]);
1820 const edgeList& coupledPoints = cycPatch.coupledPoints();
1821 const labelList& meshPts = cycPatch.meshPoints();
1823 forAll(coupledPoints, i)
1825 const edge& e = coupledPoints[i];
1827 label point0 = meshPts[e[0]];
1828 label point1 = meshPts[e[1]];
1830 unsigned int val0 = pointValues.get(point0);
1831 unsigned int t = val0;
1832 unsigned int val1 = pointValues.get(point1);
1835 pointValues.set(point0, t);
1837 pointValues.set(point1, val1);
1842 // Synchronize multiple shared points.
1843 const globalMeshData& pd = mesh.globalData();
1845 if (pd.nGlobalPoints() > 0)
1847 // Values on shared points. Use unpacked storage for ease!
1848 List<unsigned int> sharedPts(pd.nGlobalPoints(), nullValue);
1850 forAll(pd.sharedPointLabels(), i)
1852 label meshPointI = pd.sharedPointLabels()[i];
1853 // Fill my entries in the shared points
1854 sharedPts[pd.sharedPointAddr()[i]] = pointValues.get(meshPointI);
1857 // Combine on master.
1858 Pstream::listCombineGather(sharedPts, cop);
1859 Pstream::listCombineScatter(sharedPts);
1861 // Now we will all have the same information. Merge it back with
1862 // my local information.
1863 forAll(pd.sharedPointLabels(), i)
1865 label meshPointI = pd.sharedPointLabels()[i];
1866 pointValues.set(meshPointI, sharedPts[pd.sharedPointAddr()[i]]);
1872 template <unsigned nBits, class CombineOp>
1873 void Foam::syncTools::syncEdgeList
1875 const polyMesh& mesh,
1876 PackedList<nBits>& edgeValues,
1877 const CombineOp& cop,
1878 const unsigned int nullValue
1881 if (edgeValues.size() != mesh.nEdges())
1885 "syncTools<unsigned nBits, class CombineOp>::syncEdgeList"
1886 "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
1887 ", const unsigned int&)"
1888 ) << "Number of values " << edgeValues.size()
1889 << " is not equal to the number of edges in the mesh "
1890 << mesh.nEdges() << abort(FatalError);
1893 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1895 if (!hasCouples(patches))
1900 // Patch data (proc patches only).
1901 List<List<unsigned int> > patchValues(patches.size());
1903 if (Pstream::parRun())
1907 forAll(patches, patchI)
1911 isA<processorPolyPatch>(patches[patchI])
1912 && patches[patchI].nEdges() > 0
1915 const processorPolyPatch& procPatch =
1916 refCast<const processorPolyPatch>(patches[patchI]);
1918 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
1920 const labelList& meshEdges = procPatch.meshEdges();
1921 const labelList& neighbEdges = procPatch.neighbEdges();
1923 forAll(neighbEdges, edgeI)
1925 label nbrEdgeI = neighbEdges[edgeI];
1926 if (nbrEdgeI >= 0 && nbrEdgeI < procPatch.nEdges())
1928 patchValues[patchI][nbrEdgeI] =
1929 edgeValues.get(meshEdges[edgeI]);
1933 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1934 toNbr << patchValues[patchI];
1939 // Receive and combine.
1941 forAll(patches, patchI)
1945 isA<processorPolyPatch>(patches[patchI])
1946 && patches[patchI].nEdges() > 0
1949 const processorPolyPatch& procPatch =
1950 refCast<const processorPolyPatch>(patches[patchI]);
1956 procPatch.neighbProcNo()
1958 fromNeighb >> patchValues[patchI];
1961 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
1963 const labelList& meshEdges = procPatch.meshEdges();
1965 forAll(meshEdges, edgeI)
1967 unsigned int patchVal = patchValues[patchI][edgeI];
1968 label meshEdgeI = meshEdges[edgeI];
1969 unsigned int edgeVal = edgeValues.get(meshEdgeI);
1970 cop(edgeVal, patchVal);
1971 edgeValues.set(meshEdgeI, edgeVal);
1978 forAll(patches, patchI)
1980 if (isA<cyclicPolyPatch>(patches[patchI]))
1982 const cyclicPolyPatch& cycPatch =
1983 refCast<const cyclicPolyPatch>(patches[patchI]);
1985 const edgeList& coupledEdges = cycPatch.coupledEdges();
1986 const labelList& meshEdges = cycPatch.meshEdges();
1988 forAll(coupledEdges, i)
1990 const edge& e = coupledEdges[i];
1992 label edge0 = meshEdges[e[0]];
1993 label edge1 = meshEdges[e[1]];
1995 unsigned int val0 = edgeValues.get(edge0);
1996 unsigned int t = val0;
1997 unsigned int val1 = edgeValues.get(edge1);
2000 edgeValues.set(edge0, t);
2002 edgeValues.set(edge1, val1);
2007 // Synchronize multiple shared edges.
2008 const globalMeshData& pd = mesh.globalData();
2010 if (pd.nGlobalEdges() > 0)
2012 // Values on shared edges. Use unpacked storage for ease!
2013 List<unsigned int> sharedPts(pd.nGlobalEdges(), nullValue);
2015 forAll(pd.sharedEdgeLabels(), i)
2017 label meshEdgeI = pd.sharedEdgeLabels()[i];
2018 // Fill my entries in the shared edges
2019 sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues.get(meshEdgeI);
2022 // Combine on master.
2023 Pstream::listCombineGather(sharedPts, cop);
2024 Pstream::listCombineScatter(sharedPts);
2026 // Now we will all have the same information. Merge it back with
2027 // my local information.
2028 forAll(pd.sharedEdgeLabels(), i)
2030 label meshEdgeI = pd.sharedEdgeLabels()[i];
2031 edgeValues.set(meshEdgeI, sharedPts[pd.sharedEdgeAddr()[i]]);
2037 // ************************************************************************* //