1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*----------------------------------------------------------------------------*/
27 #include "syncTools.H"
28 #include <OpenFOAM/polyMesh.H>
29 #include <OpenFOAM/processorPolyPatch.H>
30 #include <OpenFOAM/cyclicPolyPatch.H>
31 #include <OpenFOAM/globalMeshData.H>
32 #include <OpenFOAM/contiguous.H>
33 #include <OpenFOAM/transform.H>
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 void Foam::syncTools::separateList
40 const vectorField& separation,
47 void Foam::syncTools::separateList
49 const vectorField& separation,
56 void Foam::syncTools::separateList
58 const vectorField& separation,
64 // Combine val with existing value at index
65 template <class T, class CombineOp>
66 void Foam::syncTools::combine
74 typename Map<T>::iterator iter = pointValues.find(index);
76 if (iter != pointValues.end())
82 pointValues.insert(index, val);
87 // Combine val with existing value at (implicit index) e.
88 template <class T, class CombineOp>
89 void Foam::syncTools::combine
91 EdgeMap<T>& edgeValues,
97 typename EdgeMap<T>::iterator iter = edgeValues.find(index);
99 if (iter != edgeValues.end())
105 edgeValues.insert(index, val);
110 template <class T, class CombineOp>
111 void Foam::syncTools::syncPointMap
113 const polyMesh& mesh,
114 Map<T>& pointValues, // from mesh point label to value
115 const CombineOp& cop,
116 const bool applySeparation
119 const polyBoundaryMesh& patches = mesh.boundaryMesh();
121 if (!hasCouples(patches))
126 // Is there any coupled patch with transformation?
127 bool hasTransformation = false;
129 if (Pstream::parRun())
133 forAll(patches, patchI)
137 isA<processorPolyPatch>(patches[patchI])
138 && patches[patchI].nPoints() > 0
141 const processorPolyPatch& procPatch =
142 refCast<const processorPolyPatch>(patches[patchI]);
144 // Get data per patchPoint in neighbouring point numbers.
146 const labelList& meshPts = procPatch.meshPoints();
147 const labelList& nbrPts = procPatch.neighbPoints();
149 // Extract local values. Create map from nbrPoint to value.
150 // Note: how small initial size?
151 Map<T> patchInfo(meshPts.size() / 20);
155 typename Map<T>::const_iterator iter =
156 pointValues.find(meshPts[i]);
158 if (iter != pointValues.end())
162 patchInfo.insert(nbrPts[i], iter());
167 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
168 toNeighb << patchInfo;
173 // Receive and combine.
175 forAll(patches, patchI)
179 isA<processorPolyPatch>(patches[patchI])
180 && patches[patchI].nPoints() > 0
183 const processorPolyPatch& procPatch =
184 refCast<const processorPolyPatch>(patches[patchI]);
185 checkTransform(procPatch, applySeparation);
187 IPstream fromNb(Pstream::blocking, procPatch.neighbProcNo());
188 Map<T> nbrPatchInfo(fromNb);
190 if (!procPatch.parallel())
192 hasTransformation = true;
193 transformList(procPatch.forwardT(), nbrPatchInfo);
195 else if (applySeparation && procPatch.separated())
197 hasTransformation = true;
198 separateList(-procPatch.separation(), nbrPatchInfo);
201 const labelList& meshPts = procPatch.meshPoints();
203 // Only update those values which come from neighbour
216 meshPts[nbrIter.key()],
225 forAll(patches, patchI)
227 if (isA<cyclicPolyPatch>(patches[patchI]))
229 const cyclicPolyPatch& cycPatch =
230 refCast<const cyclicPolyPatch>(patches[patchI]);
231 checkTransform(cycPatch, applySeparation);
233 const edgeList& coupledPoints = cycPatch.coupledPoints();
234 const labelList& meshPts = cycPatch.meshPoints();
236 // Extract local values. Create map from nbrPoint to value.
237 Map<T> half0Values(meshPts.size() / 20);
238 Map<T> half1Values(meshPts.size() / 20);
240 forAll(coupledPoints, i)
242 const edge& e = coupledPoints[i];
244 typename Map<T>::const_iterator point0Fnd =
245 pointValues.find(meshPts[e[0]]);
247 if (point0Fnd != pointValues.end())
249 half0Values.insert(i, point0Fnd());
252 typename Map<T>::const_iterator point1Fnd =
253 pointValues.find(meshPts[e[1]]);
255 if (point1Fnd != pointValues.end())
257 half1Values.insert(i, point1Fnd());
261 if (!cycPatch.parallel())
263 hasTransformation = true;
264 transformList(cycPatch.reverseT(), half0Values);
265 transformList(cycPatch.forwardT(), half1Values);
267 else if (applySeparation && cycPatch.separated())
269 hasTransformation = true;
271 const vectorField& v = cycPatch.coupledPolyPatch::separation();
272 separateList(v, half0Values);
273 separateList(-v, half1Values);
276 forAll(coupledPoints, i)
278 const edge& e = coupledPoints[i];
280 typename Map<T>::const_iterator half1Fnd = half1Values.find(i);
282 if (half1Fnd != half1Values.end())
293 typename Map<T>::const_iterator half0Fnd = half0Values.find(i);
295 if (half0Fnd != half0Values.end())
309 //- Note: hasTransformation is only used for warning messages so
310 // reduction not strictly nessecary.
311 //reduce(hasTransformation, orOp<bool>());
313 // Synchronize multiple shared points.
314 const globalMeshData& pd = mesh.globalData();
316 if (pd.nGlobalPoints() > 0)
318 if (hasTransformation)
322 "syncTools<class T, class CombineOp>::syncPointMap"
323 "(const polyMesh&, Map<T>&, const CombineOp&"
325 ) << "There are decomposed cyclics in this mesh with"
326 << " transformations." << endl
327 << "This is not supported. The result will be incorrect"
330 // meshPoint per local index
331 const labelList& sharedPtLabels = pd.sharedPointLabels();
332 // global shared index per local index
333 const labelList& sharedPtAddr = pd.sharedPointAddr();
335 // Values on shared points. Keyed on global shared index.
336 Map<T> sharedPointValues(sharedPtAddr.size());
339 // Fill my entries in the shared points
340 forAll(sharedPtLabels, i)
342 label meshPointI = sharedPtLabels[i];
344 typename Map<T>::const_iterator fnd =
345 pointValues.find(meshPointI);
347 if (fnd != pointValues.end())
353 sharedPtAddr[i], // index
361 if (Pstream::parRun())
363 if (Pstream::master())
365 // Receive the edges using shared points from the slave.
368 int slave=Pstream::firstSlave();
369 slave<=Pstream::lastSlave();
373 IPstream fromSlave(Pstream::blocking, slave);
374 Map<T> nbrValues(fromSlave);
376 // Merge neighbouring values with my values
377 forAllConstIter(typename Map<T>, nbrValues, iter)
392 int slave=Pstream::firstSlave();
393 slave<=Pstream::lastSlave();
397 OPstream toSlave(Pstream::blocking, slave);
398 toSlave << sharedPointValues;
410 toMaster << sharedPointValues;
412 // Receive merged values
419 fromMaster >> sharedPointValues;
425 // Merge sharedPointValues (keyed on sharedPointAddr) into
426 // pointValues (keyed on mesh points).
428 // Map from global shared index to meshpoint
429 Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
430 forAll(sharedPtAddr, i)
432 sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
435 forAllConstIter(Map<label>, sharedToMeshPoint, iter)
437 // Do I have a value for my shared point
438 typename Map<T>::const_iterator sharedFnd =
439 sharedPointValues.find(iter.key());
441 if (sharedFnd != sharedPointValues.end())
456 template <class T, class CombineOp>
457 void Foam::syncTools::syncEdgeMap
459 const polyMesh& mesh,
460 EdgeMap<T>& edgeValues,
461 const CombineOp& cop,
462 const bool applySeparation
465 const polyBoundaryMesh& patches = mesh.boundaryMesh();
467 if (!hasCouples(patches))
473 // Do synchronisation without constructing globalEdge addressing
474 // (since this constructs mesh edge addressing)
477 // Swap proc patch info
478 // ~~~~~~~~~~~~~~~~~~~~
480 if (Pstream::parRun())
484 forAll(patches, patchI)
488 isA<processorPolyPatch>(patches[patchI])
489 && patches[patchI].nEdges() > 0
492 const processorPolyPatch& procPatch =
493 refCast<const processorPolyPatch>(patches[patchI]);
495 // Get data per patch edge in neighbouring edge.
497 const edgeList& edges = procPatch.edges();
498 const labelList& meshPts = procPatch.meshPoints();
499 const labelList& nbrPts = procPatch.neighbPoints();
501 EdgeMap<T> patchInfo(edges.size() / 20);
505 const edge& e = edges[i];
506 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
508 typename EdgeMap<T>::const_iterator iter =
509 edgeValues.find(meshEdge);
511 if (iter != edgeValues.end())
513 const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
515 if (nbrEdge[0] >= 0 && nbrEdge[1] >= 0)
517 patchInfo.insert(nbrEdge, iter());
522 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
523 toNeighb << patchInfo;
528 // Receive and combine.
530 forAll(patches, patchI)
534 isA<processorPolyPatch>(patches[patchI])
535 && patches[patchI].nEdges() > 0
538 const processorPolyPatch& procPatch =
539 refCast<const processorPolyPatch>(patches[patchI]);
540 checkTransform(procPatch, applySeparation);
542 const labelList& meshPts = procPatch.meshPoints();
544 IPstream fromNbr(Pstream::blocking, procPatch.neighbProcNo());
545 EdgeMap<T> nbrPatchInfo(fromNbr);
547 if (!procPatch.parallel())
549 transformList(procPatch.forwardT(), nbrPatchInfo);
551 else if (applySeparation && procPatch.separated())
553 separateList(-procPatch.separation(), nbrPatchInfo);
556 // Only update those values which come from neighbour
565 const edge& e = nbrIter.key();
566 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
584 forAll(patches, patchI)
586 if (isA<cyclicPolyPatch>(patches[patchI]))
588 const cyclicPolyPatch& cycPatch =
589 refCast<const cyclicPolyPatch>(patches[patchI]);
590 checkTransform(cycPatch, applySeparation);
592 const edgeList& coupledEdges = cycPatch.coupledEdges();
593 const labelList& meshPts = cycPatch.meshPoints();
594 const edgeList& edges = cycPatch.edges();
596 // Extract local values. Create map from nbrPoint to value.
597 Map<T> half0Values(meshPts.size() / 20);
598 Map<T> half1Values(meshPts.size() / 20);
600 forAll(coupledEdges, i)
602 const edge& twoEdges = coupledEdges[i];
605 const edge& e0 = edges[twoEdges[0]];
606 const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
608 typename EdgeMap<T>::const_iterator iter =
609 edgeValues.find(meshEdge0);
611 if (iter != edgeValues.end())
613 half0Values.insert(i, iter());
617 const edge& e1 = edges[twoEdges[1]];
618 const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
620 typename EdgeMap<T>::const_iterator iter =
621 edgeValues.find(meshEdge1);
623 if (iter != edgeValues.end())
625 half1Values.insert(i, iter());
633 if (!cycPatch.parallel())
635 transformList(cycPatch.reverseT(), half0Values);
636 transformList(cycPatch.forwardT(), half1Values);
638 else if (applySeparation && cycPatch.separated())
640 const vectorField& v = cycPatch.coupledPolyPatch::separation();
641 separateList(v, half0Values);
642 separateList(-v, half1Values);
646 // Extract and combine information
648 forAll(coupledEdges, i)
650 const edge& twoEdges = coupledEdges[i];
652 typename Map<T>::const_iterator half1Fnd =
655 if (half1Fnd != half1Values.end())
657 const edge& e0 = edges[twoEdges[0]];
658 const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
669 typename Map<T>::const_iterator half0Fnd =
671 if (half0Fnd != half0Values.end())
673 const edge& e1 = edges[twoEdges[1]];
674 const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
688 // Synchronize multiple shared points.
689 // Problem is that we don't want to construct shared edges so basically
690 // we do here like globalMeshData but then using sparse edge representation
691 // (EdgeMap instead of mesh.edges())
693 const globalMeshData& pd = mesh.globalData();
694 const labelList& sharedPtAddr = pd.sharedPointAddr();
695 const labelList& sharedPtLabels = pd.sharedPointLabels();
697 // 1. Create map from meshPoint to globalShared index.
698 Map<label> meshToShared(2*sharedPtLabels.size());
699 forAll(sharedPtLabels, i)
701 meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
704 // Values on shared points. From two sharedPtAddr indices to a value.
705 EdgeMap<T> sharedEdgeValues(meshToShared.size());
707 // From shared edge to mesh edge. Used for merging later on.
708 EdgeMap<edge> potentialSharedEdge(meshToShared.size());
710 // 2. Find any edges using two global shared points. These will always be
711 // on the outside of the mesh. (though might not be on coupled patch
712 // if is single edge and not on coupled face)
713 // Store value (if any) on sharedEdgeValues
714 for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
716 const face& f = mesh.faces()[faceI];
721 label v1 = f[f.fcIndex(fp)];
723 Map<label>::const_iterator v0Fnd = meshToShared.find(v0);
725 if (v0Fnd != meshToShared.end())
727 Map<label>::const_iterator v1Fnd = meshToShared.find(v1);
729 if (v1Fnd != meshToShared.end())
731 const edge meshEdge(v0, v1);
733 // edge in shared point labels
734 const edge sharedEdge(v0Fnd(), v1Fnd());
736 // Store mesh edge as a potential shared edge.
737 potentialSharedEdge.insert(sharedEdge, meshEdge);
739 typename EdgeMap<T>::const_iterator edgeFnd =
740 edgeValues.find(meshEdge);
742 if (edgeFnd != edgeValues.end())
744 // edge exists in edgeValues. See if already in map
745 // (since on same processor, e.g. cyclic)
760 // Now sharedEdgeValues will contain per potential sharedEdge the value.
761 // (potential since an edge having two shared points is not nessecary a
763 // Reduce this on the master.
765 if (Pstream::parRun())
767 if (Pstream::master())
769 // Receive the edges using shared points from the slave.
772 int slave=Pstream::firstSlave();
773 slave<=Pstream::lastSlave();
777 IPstream fromSlave(Pstream::blocking, slave);
778 EdgeMap<T> nbrValues(fromSlave);
780 // Merge neighbouring values with my values
781 forAllConstIter(typename EdgeMap<T>, nbrValues, iter)
796 int slave=Pstream::firstSlave();
797 slave<=Pstream::lastSlave();
802 OPstream toSlave(Pstream::blocking, slave);
803 toSlave << sharedEdgeValues;
810 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
811 toMaster << sharedEdgeValues;
813 // Receive merged values
815 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
816 fromMaster >> sharedEdgeValues;
822 // Merge sharedEdgeValues (keyed on sharedPointAddr) into edgeValues
823 // (keyed on mesh points).
825 // Loop over all my shared edges.
826 forAllConstIter(typename EdgeMap<edge>, potentialSharedEdge, iter)
828 const edge& sharedEdge = iter.key();
829 const edge& meshEdge = iter();
831 // Do I have a value for the shared edge?
832 typename EdgeMap<T>::const_iterator sharedFnd =
833 sharedEdgeValues.find(sharedEdge);
835 if (sharedFnd != sharedEdgeValues.end())
849 template <class T, class CombineOp>
850 void Foam::syncTools::syncPointList
852 const polyMesh& mesh,
853 UList<T>& pointValues,
854 const CombineOp& cop,
856 const bool applySeparation
859 if (pointValues.size() != mesh.nPoints())
863 "syncTools<class T, class CombineOp>::syncPointList"
864 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
866 ) << "Number of values " << pointValues.size()
867 << " is not equal to the number of points in the mesh "
868 << mesh.nPoints() << abort(FatalError);
871 const polyBoundaryMesh& patches = mesh.boundaryMesh();
873 if (!hasCouples(patches))
878 // Is there any coupled patch with transformation?
879 bool hasTransformation = false;
881 if (Pstream::parRun())
885 forAll(patches, patchI)
889 isA<processorPolyPatch>(patches[patchI])
890 && patches[patchI].nPoints() > 0
893 const processorPolyPatch& procPatch =
894 refCast<const processorPolyPatch>(patches[patchI]);
896 // Get data per patchPoint in neighbouring point numbers.
897 List<T> patchInfo(procPatch.nPoints(), nullValue);
899 const labelList& meshPts = procPatch.meshPoints();
900 const labelList& nbrPts = procPatch.neighbPoints();
902 forAll(nbrPts, pointI)
904 label nbrPointI = nbrPts[pointI];
905 if (nbrPointI >= 0 && nbrPointI < patchInfo.size())
907 patchInfo[nbrPointI] = pointValues[meshPts[pointI]];
911 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
917 // Receive and combine.
919 forAll(patches, patchI)
923 isA<processorPolyPatch>(patches[patchI])
924 && patches[patchI].nPoints() > 0
927 const processorPolyPatch& procPatch =
928 refCast<const processorPolyPatch>(patches[patchI]);
929 checkTransform(procPatch, applySeparation);
931 List<T> nbrPatchInfo(procPatch.nPoints());
933 // We do not know the number of points on the other side
934 // so cannot use Pstream::read.
938 procPatch.neighbProcNo()
940 fromNbr >> nbrPatchInfo;
942 // Null any value which is not on neighbouring processor
943 nbrPatchInfo.setSize(procPatch.nPoints(), nullValue);
945 if (!procPatch.parallel())
947 hasTransformation = true;
948 transformList(procPatch.forwardT(), nbrPatchInfo);
950 else if (applySeparation && procPatch.separated())
952 hasTransformation = true;
953 separateList(-procPatch.separation(), nbrPatchInfo);
956 const labelList& meshPts = procPatch.meshPoints();
958 forAll(meshPts, pointI)
960 label meshPointI = meshPts[pointI];
961 cop(pointValues[meshPointI], nbrPatchInfo[pointI]);
968 forAll(patches, patchI)
970 if (isA<cyclicPolyPatch>(patches[patchI]))
972 const cyclicPolyPatch& cycPatch =
973 refCast<const cyclicPolyPatch>(patches[patchI]);
975 checkTransform(cycPatch, applySeparation);
977 const edgeList& coupledPoints = cycPatch.coupledPoints();
978 const labelList& meshPts = cycPatch.meshPoints();
980 List<T> half0Values(coupledPoints.size());
981 List<T> half1Values(coupledPoints.size());
983 forAll(coupledPoints, i)
985 const edge& e = coupledPoints[i];
987 label point0 = meshPts[e[0]];
988 label point1 = meshPts[e[1]];
990 half0Values[i] = pointValues[point0];
991 half1Values[i] = pointValues[point1];
994 if (!cycPatch.parallel())
996 hasTransformation = true;
997 transformList(cycPatch.reverseT(), half0Values);
998 transformList(cycPatch.forwardT(), half1Values);
1000 else if (applySeparation && cycPatch.separated())
1002 hasTransformation = true;
1003 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1004 separateList(v, half0Values);
1005 separateList(-v, half1Values);
1008 forAll(coupledPoints, i)
1010 const edge& e = coupledPoints[i];
1012 label point0 = meshPts[e[0]];
1013 label point1 = meshPts[e[1]];
1015 cop(pointValues[point0], half1Values[i]);
1016 cop(pointValues[point1], half0Values[i]);
1021 //- Note: hasTransformation is only used for warning messages so
1022 // reduction not strictly nessecary.
1023 //reduce(hasTransformation, orOp<bool>());
1025 // Synchronize multiple shared points.
1026 const globalMeshData& pd = mesh.globalData();
1028 if (pd.nGlobalPoints() > 0)
1030 if (hasTransformation)
1034 "syncTools<class T, class CombineOp>::syncPointList"
1035 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1037 ) << "There are decomposed cyclics in this mesh with"
1038 << " transformations." << endl
1039 << "This is not supported. The result will be incorrect"
1044 // Values on shared points.
1045 List<T> sharedPts(pd.nGlobalPoints(), nullValue);
1047 forAll(pd.sharedPointLabels(), i)
1049 label meshPointI = pd.sharedPointLabels()[i];
1050 // Fill my entries in the shared points
1051 sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
1054 // Combine on master.
1055 Pstream::listCombineGather(sharedPts, cop);
1056 Pstream::listCombineScatter(sharedPts);
1058 // Now we will all have the same information. Merge it back with
1059 // my local information.
1060 forAll(pd.sharedPointLabels(), i)
1062 label meshPointI = pd.sharedPointLabels()[i];
1063 pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
1069 template <class T, class CombineOp>
1070 void Foam::syncTools::syncPointList
1072 const polyMesh& mesh,
1073 const labelList& meshPoints,
1074 UList<T>& pointValues,
1075 const CombineOp& cop,
1077 const bool applySeparation
1080 if (pointValues.size() != meshPoints.size())
1084 "syncTools<class T, class CombineOp>::syncPointList"
1085 "(const polyMesh&, const labelList&, UList<T>&, const CombineOp&"
1086 ", const T&, const bool)"
1087 ) << "Number of values " << pointValues.size()
1088 << " is not equal to the number of points "
1089 << meshPoints.size() << abort(FatalError);
1092 if (!hasCouples(mesh.boundaryMesh()))
1097 List<T> meshValues(mesh.nPoints(), nullValue);
1099 forAll(meshPoints, i)
1101 meshValues[meshPoints[i]] = pointValues[i];
1104 syncTools::syncPointList
1109 nullValue, // null value
1110 applySeparation // separation
1113 forAll(meshPoints, i)
1115 pointValues[i] = meshValues[meshPoints[i]];
1120 template <class T, class CombineOp>
1121 void Foam::syncTools::syncEdgeList
1123 const polyMesh& mesh,
1124 UList<T>& edgeValues,
1125 const CombineOp& cop,
1127 const bool applySeparation
1130 if (edgeValues.size() != mesh.nEdges())
1134 "syncTools<class T, class CombineOp>::syncEdgeList"
1135 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1137 ) << "Number of values " << edgeValues.size()
1138 << " is not equal to the number of edges in the mesh "
1139 << mesh.nEdges() << abort(FatalError);
1142 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1144 if (!hasCouples(patches))
1149 // Is there any coupled patch with transformation?
1150 bool hasTransformation = false;
1152 if (Pstream::parRun())
1156 forAll(patches, patchI)
1160 isA<processorPolyPatch>(patches[patchI])
1161 && patches[patchI].nEdges() > 0
1164 const processorPolyPatch& procPatch =
1165 refCast<const processorPolyPatch>(patches[patchI]);
1167 const labelList& meshEdges = procPatch.meshEdges();
1168 const labelList& neighbEdges = procPatch.neighbEdges();
1170 // Get region per patch edge in neighbouring edge numbers.
1171 List<T> patchInfo(procPatch.nEdges(), nullValue);
1173 forAll(neighbEdges, edgeI)
1175 label nbrEdgeI = neighbEdges[edgeI];
1177 if (nbrEdgeI >= 0 && nbrEdgeI < patchInfo.size())
1179 patchInfo[nbrEdgeI] = edgeValues[meshEdges[edgeI]];
1183 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1188 // Receive and combine.
1190 forAll(patches, patchI)
1194 isA<processorPolyPatch>(patches[patchI])
1195 && patches[patchI].nEdges() > 0
1198 const processorPolyPatch& procPatch =
1199 refCast<const processorPolyPatch>(patches[patchI]);
1201 checkTransform(procPatch, applySeparation);
1203 const labelList& meshEdges = procPatch.meshEdges();
1205 // Receive from neighbour. Is per patch edge the region of the
1206 // neighbouring patch edge.
1207 List<T> nbrPatchInfo(procPatch.nEdges());
1213 procPatch.neighbProcNo()
1215 fromNeighb >> nbrPatchInfo;
1217 // Null any value which is not on neighbouring processor
1218 nbrPatchInfo.setSize(procPatch.nEdges(), nullValue);
1220 if (!procPatch.parallel())
1222 hasTransformation = true;
1223 transformList(procPatch.forwardT(), nbrPatchInfo);
1225 else if (applySeparation && procPatch.separated())
1227 hasTransformation = true;
1228 separateList(-procPatch.separation(), nbrPatchInfo);
1231 forAll(meshEdges, edgeI)
1233 label meshEdgeI = meshEdges[edgeI];
1235 cop(edgeValues[meshEdgeI], nbrPatchInfo[edgeI]);
1242 forAll(patches, patchI)
1244 if (isA<cyclicPolyPatch>(patches[patchI]))
1246 const cyclicPolyPatch& cycPatch =
1247 refCast<const cyclicPolyPatch>(patches[patchI]);
1249 checkTransform(cycPatch, applySeparation);
1251 const edgeList& coupledEdges = cycPatch.coupledEdges();
1252 const labelList& meshEdges = cycPatch.meshEdges();
1254 List<T> half0Values(coupledEdges.size());
1255 List<T> half1Values(coupledEdges.size());
1257 forAll(coupledEdges, i)
1259 const edge& e = coupledEdges[i];
1261 label meshEdge0 = meshEdges[e[0]];
1262 label meshEdge1 = meshEdges[e[1]];
1264 half0Values[i] = edgeValues[meshEdge0];
1265 half1Values[i] = edgeValues[meshEdge1];
1268 if (!cycPatch.parallel())
1270 hasTransformation = true;
1271 transformList(cycPatch.reverseT(), half0Values);
1272 transformList(cycPatch.forwardT(), half1Values);
1274 else if (applySeparation && cycPatch.separated())
1276 hasTransformation = true;
1278 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1279 separateList(v, half0Values);
1280 separateList(-v, half1Values);
1283 forAll(coupledEdges, i)
1285 const edge& e = coupledEdges[i];
1287 label meshEdge0 = meshEdges[e[0]];
1288 label meshEdge1 = meshEdges[e[1]];
1290 cop(edgeValues[meshEdge0], half1Values[i]);
1291 cop(edgeValues[meshEdge1], half0Values[i]);
1296 //- Note: hasTransformation is only used for warning messages so
1297 // reduction not strictly nessecary.
1298 //reduce(hasTransformation, orOp<bool>());
1300 // Do the multiple shared edges
1301 const globalMeshData& pd = mesh.globalData();
1303 if (pd.nGlobalEdges() > 0)
1305 if (hasTransformation)
1309 "syncTools<class T, class CombineOp>::syncEdgeList"
1310 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1312 ) << "There are decomposed cyclics in this mesh with"
1313 << " transformations." << endl
1314 << "This is not supported. The result will be incorrect"
1318 // Values on shared edges.
1319 List<T> sharedPts(pd.nGlobalEdges(), nullValue);
1321 forAll(pd.sharedEdgeLabels(), i)
1323 label meshEdgeI = pd.sharedEdgeLabels()[i];
1325 // Fill my entries in the shared edges
1326 sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
1329 // Combine on master.
1330 Pstream::listCombineGather(sharedPts, cop);
1331 Pstream::listCombineScatter(sharedPts);
1333 // Now we will all have the same information. Merge it back with
1334 // my local information.
1335 forAll(pd.sharedEdgeLabels(), i)
1337 label meshEdgeI = pd.sharedEdgeLabels()[i];
1338 edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
1344 template <class T, class CombineOp>
1345 void Foam::syncTools::syncBoundaryFaceList
1347 const polyMesh& mesh,
1348 UList<T>& faceValues,
1349 const CombineOp& cop,
1350 const bool applySeparation
1353 const label nBFaces = mesh.nFaces() - mesh.nInternalFaces();
1355 if (faceValues.size() != nBFaces)
1359 "syncTools<class T, class CombineOp>::syncBoundaryFaceList"
1360 "(const polyMesh&, UList<T>&, const CombineOp&"
1362 ) << "Number of values " << faceValues.size()
1363 << " is not equal to the number of boundary faces in the mesh "
1364 << nBFaces << abort(FatalError);
1367 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1369 if (!hasCouples(patches))
1375 if (Pstream::parRun())
1379 forAll(patches, patchI)
1383 isA<processorPolyPatch>(patches[patchI])
1384 && patches[patchI].size() > 0
1387 const processorPolyPatch& procPatch =
1388 refCast<const processorPolyPatch>(patches[patchI]);
1390 label patchStart = procPatch.start()-mesh.nInternalFaces();
1392 if (contiguous<T>())
1397 procPatch.neighbProcNo(),
1398 reinterpret_cast<const char*>(&faceValues[patchStart]),
1399 procPatch.size()*sizeof(T)
1404 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1406 SubList<T>(faceValues, procPatch.size(), patchStart);
1412 // Receive and combine.
1414 forAll(patches, patchI)
1418 isA<processorPolyPatch>(patches[patchI])
1419 && patches[patchI].size() > 0
1422 const processorPolyPatch& procPatch =
1423 refCast<const processorPolyPatch>(patches[patchI]);
1425 List<T> nbrPatchInfo(procPatch.size());
1427 if (contiguous<T>())
1432 procPatch.neighbProcNo(),
1433 reinterpret_cast<char*>(nbrPatchInfo.begin()),
1434 nbrPatchInfo.byteSize()
1442 procPatch.neighbProcNo()
1444 fromNeighb >> nbrPatchInfo;
1447 if (!procPatch.parallel())
1449 transformList(procPatch.forwardT(), nbrPatchInfo);
1451 else if (applySeparation && procPatch.separated())
1453 separateList(-procPatch.separation(), nbrPatchInfo);
1457 label bFaceI = procPatch.start()-mesh.nInternalFaces();
1459 forAll(nbrPatchInfo, i)
1461 cop(faceValues[bFaceI++], nbrPatchInfo[i]);
1468 forAll(patches, patchI)
1470 if (isA<cyclicPolyPatch>(patches[patchI]))
1472 const cyclicPolyPatch& cycPatch =
1473 refCast<const cyclicPolyPatch>(patches[patchI]);
1475 label patchStart = cycPatch.start()-mesh.nInternalFaces();
1477 label half = cycPatch.size()/2;
1478 label half1Start = patchStart+half;
1480 List<T> half0Values(SubList<T>(faceValues, half, patchStart));
1481 List<T> half1Values(SubList<T>(faceValues, half, half1Start));
1483 if (!cycPatch.parallel())
1485 transformList(cycPatch.reverseT(), half0Values);
1486 transformList(cycPatch.forwardT(), half1Values);
1488 else if (applySeparation && cycPatch.separated())
1490 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1491 separateList(v, half0Values);
1492 separateList(-v, half1Values);
1495 label i0 = patchStart;
1496 forAll(half1Values, i)
1498 cop(faceValues[i0++], half1Values[i]);
1501 label i1 = half1Start;
1502 forAll(half0Values, i)
1504 cop(faceValues[i1++], half0Values[i]);
1511 template <class T, class CombineOp>
1512 void Foam::syncTools::syncFaceList
1514 const polyMesh& mesh,
1515 UList<T>& faceValues,
1516 const CombineOp& cop,
1517 const bool applySeparation
1520 if (faceValues.size() != mesh.nFaces())
1524 "syncTools<class T, class CombineOp>::syncFaceList"
1525 "(const polyMesh&, UList<T>&, const CombineOp&"
1527 ) << "Number of values " << faceValues.size()
1528 << " is not equal to the number of faces in the mesh "
1529 << mesh.nFaces() << abort(FatalError);
1532 SubList<T> bndValues
1535 mesh.nFaces()-mesh.nInternalFaces(),
1536 mesh.nInternalFaces()
1539 syncBoundaryFaceList
1550 void Foam::syncTools::swapBoundaryFaceList
1552 const polyMesh& mesh,
1553 UList<T>& faceValues,
1554 const bool applySeparation
1557 syncBoundaryFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
1562 void Foam::syncTools::swapFaceList
1564 const polyMesh& mesh,
1565 UList<T>& faceValues,
1566 const bool applySeparation
1569 syncFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
1573 template <unsigned nBits, class CombineOp>
1574 void Foam::syncTools::syncFaceList
1576 const polyMesh& mesh,
1577 PackedList<nBits>& faceValues,
1578 const CombineOp& cop
1581 if (faceValues.size() != mesh.nFaces())
1585 "syncTools<unsigned nBits, class CombineOp>::syncFaceList"
1586 "(const polyMesh&, PackedList<nBits>&, const CombineOp&)"
1587 ) << "Number of values " << faceValues.size()
1588 << " is not equal to the number of faces in the mesh "
1589 << mesh.nFaces() << abort(FatalError);
1592 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1594 if (!hasCouples(patches))
1599 // Patch data (proc patches only).
1600 List<List<unsigned int> > patchValues(patches.size());
1602 if (Pstream::parRun())
1606 forAll(patches, patchI)
1610 isA<processorPolyPatch>(patches[patchI])
1611 && patches[patchI].size() > 0
1614 const processorPolyPatch& procPatch =
1615 refCast<const processorPolyPatch>(patches[patchI]);
1617 patchValues[patchI].setSize(procPatch.size());
1618 forAll(procPatch, i)
1620 patchValues[patchI][i] =
1621 faceValues.get(procPatch.start()+i);
1624 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1625 toNbr << patchValues[patchI];
1630 // Receive and combine.
1632 forAll(patches, patchI)
1636 isA<processorPolyPatch>(patches[patchI])
1637 && patches[patchI].size() > 0
1640 const processorPolyPatch& procPatch =
1641 refCast<const processorPolyPatch>(patches[patchI]);
1647 procPatch.neighbProcNo()
1649 fromNbr >> patchValues[patchI];
1652 // Combine (bitwise)
1653 forAll(procPatch, i)
1655 unsigned int patchVal = patchValues[patchI][i];
1656 label meshFaceI = procPatch.start()+i;
1657 unsigned int faceVal = faceValues.get(meshFaceI);
1658 cop(faceVal, patchVal);
1659 faceValues.set(meshFaceI, faceVal);
1666 forAll(patches, patchI)
1668 if (isA<cyclicPolyPatch>(patches[patchI]))
1670 const cyclicPolyPatch& cycPatch =
1671 refCast<const cyclicPolyPatch>(patches[patchI]);
1673 label half = cycPatch.size()/2;
1675 for (label i = 0; i < half; i++)
1677 label meshFace0 = cycPatch.start()+i;
1678 unsigned int val0 = faceValues.get(meshFace0);
1679 label meshFace1 = meshFace0 + half;
1680 unsigned int val1 = faceValues.get(meshFace1);
1682 unsigned int t = val0;
1684 faceValues.set(meshFace0, t);
1687 faceValues.set(meshFace1, val1);
1694 template <unsigned nBits>
1695 void Foam::syncTools::swapFaceList
1697 const polyMesh& mesh,
1698 PackedList<nBits>& faceValues
1701 syncFaceList(mesh, faceValues, eqOp<unsigned int>());
1705 template <unsigned nBits, class CombineOp>
1706 void Foam::syncTools::syncPointList
1708 const polyMesh& mesh,
1709 PackedList<nBits>& pointValues,
1710 const CombineOp& cop,
1711 const unsigned int nullValue
1714 if (pointValues.size() != mesh.nPoints())
1718 "syncTools<unsigned nBits, class CombineOp>::syncPointList"
1719 "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
1720 ", const unsigned int&)"
1721 ) << "Number of values " << pointValues.size()
1722 << " is not equal to the number of points in the mesh "
1723 << mesh.nPoints() << abort(FatalError);
1726 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1728 if (!hasCouples(patches))
1733 // Patch data (proc patches only).
1734 List<List<unsigned int> > patchValues(patches.size());
1736 if (Pstream::parRun())
1740 forAll(patches, patchI)
1744 isA<processorPolyPatch>(patches[patchI])
1745 && patches[patchI].nPoints() > 0
1748 const processorPolyPatch& procPatch =
1749 refCast<const processorPolyPatch>(patches[patchI]);
1751 patchValues[patchI].setSize(procPatch.nPoints());
1752 patchValues[patchI] = nullValue;
1754 const labelList& meshPts = procPatch.meshPoints();
1755 const labelList& nbrPts = procPatch.neighbPoints();
1757 forAll(nbrPts, pointI)
1759 label nbrPointI = nbrPts[pointI];
1760 if (nbrPointI >= 0 && nbrPointI < procPatch.nPoints())
1762 patchValues[patchI][nbrPointI] =
1763 pointValues.get(meshPts[pointI]);
1767 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1768 toNbr << patchValues[patchI];
1773 // Receive and combine.
1775 forAll(patches, patchI)
1779 isA<processorPolyPatch>(patches[patchI])
1780 && patches[patchI].nPoints() > 0
1783 const processorPolyPatch& procPatch =
1784 refCast<const processorPolyPatch>(patches[patchI]);
1787 // We do not know the number of points on the other side
1788 // so cannot use Pstream::read.
1792 procPatch.neighbProcNo()
1794 fromNbr >> patchValues[patchI];
1797 // Null any value which is not on neighbouring processor
1798 patchValues[patchI].setSize(procPatch.nPoints(), nullValue);
1800 const labelList& meshPts = procPatch.meshPoints();
1802 forAll(meshPts, pointI)
1804 label meshPointI = meshPts[pointI];
1805 unsigned int pointVal = pointValues.get(meshPointI);
1806 cop(pointVal, patchValues[patchI][pointI]);
1807 pointValues.set(meshPointI, pointVal);
1814 forAll(patches, patchI)
1816 if (isA<cyclicPolyPatch>(patches[patchI]))
1818 const cyclicPolyPatch& cycPatch =
1819 refCast<const cyclicPolyPatch>(patches[patchI]);
1821 const edgeList& coupledPoints = cycPatch.coupledPoints();
1822 const labelList& meshPts = cycPatch.meshPoints();
1824 forAll(coupledPoints, i)
1826 const edge& e = coupledPoints[i];
1828 label point0 = meshPts[e[0]];
1829 label point1 = meshPts[e[1]];
1831 unsigned int val0 = pointValues.get(point0);
1832 unsigned int t = val0;
1833 unsigned int val1 = pointValues.get(point1);
1836 pointValues.set(point0, t);
1838 pointValues.set(point1, val1);
1843 // Synchronize multiple shared points.
1844 const globalMeshData& pd = mesh.globalData();
1846 if (pd.nGlobalPoints() > 0)
1848 // Values on shared points. Use unpacked storage for ease!
1849 List<unsigned int> sharedPts(pd.nGlobalPoints(), nullValue);
1851 forAll(pd.sharedPointLabels(), i)
1853 label meshPointI = pd.sharedPointLabels()[i];
1854 // Fill my entries in the shared points
1855 sharedPts[pd.sharedPointAddr()[i]] = pointValues.get(meshPointI);
1858 // Combine on master.
1859 Pstream::listCombineGather(sharedPts, cop);
1860 Pstream::listCombineScatter(sharedPts);
1862 // Now we will all have the same information. Merge it back with
1863 // my local information.
1864 forAll(pd.sharedPointLabels(), i)
1866 label meshPointI = pd.sharedPointLabels()[i];
1867 pointValues.set(meshPointI, sharedPts[pd.sharedPointAddr()[i]]);
1873 template <unsigned nBits, class CombineOp>
1874 void Foam::syncTools::syncEdgeList
1876 const polyMesh& mesh,
1877 PackedList<nBits>& edgeValues,
1878 const CombineOp& cop,
1879 const unsigned int nullValue
1882 if (edgeValues.size() != mesh.nEdges())
1886 "syncTools<unsigned nBits, class CombineOp>::syncEdgeList"
1887 "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
1888 ", const unsigned int&)"
1889 ) << "Number of values " << edgeValues.size()
1890 << " is not equal to the number of edges in the mesh "
1891 << mesh.nEdges() << abort(FatalError);
1894 const polyBoundaryMesh& patches = mesh.boundaryMesh();
1896 if (!hasCouples(patches))
1901 // Patch data (proc patches only).
1902 List<List<unsigned int> > patchValues(patches.size());
1904 if (Pstream::parRun())
1908 forAll(patches, patchI)
1912 isA<processorPolyPatch>(patches[patchI])
1913 && patches[patchI].nEdges() > 0
1916 const processorPolyPatch& procPatch =
1917 refCast<const processorPolyPatch>(patches[patchI]);
1919 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
1921 const labelList& meshEdges = procPatch.meshEdges();
1922 const labelList& neighbEdges = procPatch.neighbEdges();
1924 forAll(neighbEdges, edgeI)
1926 label nbrEdgeI = neighbEdges[edgeI];
1927 if (nbrEdgeI >= 0 && nbrEdgeI < procPatch.nEdges())
1929 patchValues[patchI][nbrEdgeI] =
1930 edgeValues.get(meshEdges[edgeI]);
1934 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1935 toNbr << patchValues[patchI];
1940 // Receive and combine.
1942 forAll(patches, patchI)
1946 isA<processorPolyPatch>(patches[patchI])
1947 && patches[patchI].nEdges() > 0
1950 const processorPolyPatch& procPatch =
1951 refCast<const processorPolyPatch>(patches[patchI]);
1957 procPatch.neighbProcNo()
1959 fromNeighb >> patchValues[patchI];
1962 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
1964 const labelList& meshEdges = procPatch.meshEdges();
1966 forAll(meshEdges, edgeI)
1968 unsigned int patchVal = patchValues[patchI][edgeI];
1969 label meshEdgeI = meshEdges[edgeI];
1970 unsigned int edgeVal = edgeValues.get(meshEdgeI);
1971 cop(edgeVal, patchVal);
1972 edgeValues.set(meshEdgeI, edgeVal);
1979 forAll(patches, patchI)
1981 if (isA<cyclicPolyPatch>(patches[patchI]))
1983 const cyclicPolyPatch& cycPatch =
1984 refCast<const cyclicPolyPatch>(patches[patchI]);
1986 const edgeList& coupledEdges = cycPatch.coupledEdges();
1987 const labelList& meshEdges = cycPatch.meshEdges();
1989 forAll(coupledEdges, i)
1991 const edge& e = coupledEdges[i];
1993 label edge0 = meshEdges[e[0]];
1994 label edge1 = meshEdges[e[1]];
1996 unsigned int val0 = edgeValues.get(edge0);
1997 unsigned int t = val0;
1998 unsigned int val1 = edgeValues.get(edge1);
2001 edgeValues.set(edge0, t);
2003 edgeValues.set(edge1, val1);
2008 // Synchronize multiple shared edges.
2009 const globalMeshData& pd = mesh.globalData();
2011 if (pd.nGlobalEdges() > 0)
2013 // Values on shared edges. Use unpacked storage for ease!
2014 List<unsigned int> sharedPts(pd.nGlobalEdges(), nullValue);
2016 forAll(pd.sharedEdgeLabels(), i)
2018 label meshEdgeI = pd.sharedEdgeLabels()[i];
2019 // Fill my entries in the shared edges
2020 sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues.get(meshEdgeI);
2023 // Combine on master.
2024 Pstream::listCombineGather(sharedPts, cop);
2025 Pstream::listCombineScatter(sharedPts);
2027 // Now we will all have the same information. Merge it back with
2028 // my local information.
2029 forAll(pd.sharedEdgeLabels(), i)
2031 label meshEdgeI = pd.sharedEdgeLabels()[i];
2032 edgeValues.set(meshEdgeI, sharedPts[pd.sharedEdgeAddr()[i]]);
2038 // ************************ vim: set sw=4 sts=4 et: ************************ //