Merge branch 'upstream/OpenFOAM' into master
[freefoam.git] / src / OpenFOAM / meshes / polyMesh / syncTools / syncToolsTemplates.C
blob4984ae3e1d22c557ffbfa426998bd785b9778756
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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  * * * * * * * * * * * * * //
37 template <class T>
38 void Foam::syncTools::separateList
40     const vectorField& separation,
41     UList<T>& field
46 template <class T>
47 void Foam::syncTools::separateList
49     const vectorField& separation,
50     Map<T>& field
55 template <class T>
56 void Foam::syncTools::separateList
58     const vectorField& separation,
59     EdgeMap<T>& field
64 // Combine val with existing value at index
65 template <class T, class CombineOp>
66 void Foam::syncTools::combine
68     Map<T>& pointValues,
69     const CombineOp& cop,
70     const label index,
71     const T& val
74     typename Map<T>::iterator iter = pointValues.find(index);
76     if (iter != pointValues.end())
77     {
78         cop(iter(), val);
79     }
80     else
81     {
82         pointValues.insert(index, val);
83     }
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,
92     const CombineOp& cop,
93     const edge& index,
94     const T& val
97     typename EdgeMap<T>::iterator iter = edgeValues.find(index);
99     if (iter != edgeValues.end())
100     {
101         cop(iter(), val);
102     }
103     else
104     {
105         edgeValues.insert(index, val);
106     }
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))
122     {
123         return;
124     }
126     // Is there any coupled patch with transformation?
127     bool hasTransformation = false;
129     if (Pstream::parRun())
130     {
131         // Send
133         forAll(patches, patchI)
134         {
135             if
136             (
137                 isA<processorPolyPatch>(patches[patchI])
138              && patches[patchI].nPoints() > 0
139             )
140             {
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);
153                 forAll(meshPts, i)
154                 {
155                     typename Map<T>::const_iterator iter =
156                         pointValues.find(meshPts[i]);
158                     if (iter != pointValues.end())
159                     {
160                         if (nbrPts[i] >= 0)
161                         {
162                             patchInfo.insert(nbrPts[i], iter());
163                         }
164                     }
165                 }
167                 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
168                 toNeighb << patchInfo;
169             }
170         }
173         // Receive and combine.
175         forAll(patches, patchI)
176         {
177             if
178             (
179                 isA<processorPolyPatch>(patches[patchI])
180              && patches[patchI].nPoints() > 0
181             )
182             {
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())
191                 {
192                     hasTransformation = true;
193                     transformList(procPatch.forwardT(), nbrPatchInfo);
194                 }
195                 else if (applySeparation && procPatch.separated())
196                 {
197                     hasTransformation = true;
198                     separateList(-procPatch.separation(), nbrPatchInfo);
199                 }
201                 const labelList& meshPts = procPatch.meshPoints();
203                 // Only update those values which come from neighbour
205                 forAllConstIter
206                 (
207                     typename Map<T>,
208                     nbrPatchInfo,
209                     nbrIter
210                 )
211                 {
212                     combine
213                     (
214                         pointValues,
215                         cop,
216                         meshPts[nbrIter.key()],
217                         nbrIter()
218                     );
219                 }
220             }
221         }
222     }
224     // Do the cyclics.
225     forAll(patches, patchI)
226     {
227         if (isA<cyclicPolyPatch>(patches[patchI]))
228         {
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)
241             {
242                 const edge& e = coupledPoints[i];
244                 typename Map<T>::const_iterator point0Fnd =
245                     pointValues.find(meshPts[e[0]]);
247                 if (point0Fnd != pointValues.end())
248                 {
249                     half0Values.insert(i, point0Fnd());
250                 }
252                 typename Map<T>::const_iterator point1Fnd =
253                     pointValues.find(meshPts[e[1]]);
255                 if (point1Fnd != pointValues.end())
256                 {
257                     half1Values.insert(i, point1Fnd());
258                 }
259             }
261             if (!cycPatch.parallel())
262             {
263                 hasTransformation = true;
264                 transformList(cycPatch.reverseT(), half0Values);
265                 transformList(cycPatch.forwardT(), half1Values);
266             }
267             else if (applySeparation && cycPatch.separated())
268             {
269                 hasTransformation = true;
271                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
272                 separateList(v, half0Values);
273                 separateList(-v, half1Values);
274             }
276             forAll(coupledPoints, i)
277             {
278                 const edge& e = coupledPoints[i];
280                 typename Map<T>::const_iterator half1Fnd = half1Values.find(i);
282                 if (half1Fnd != half1Values.end())
283                 {
284                     combine
285                     (
286                         pointValues,
287                         cop,
288                         meshPts[e[0]],
289                         half1Fnd()
290                     );
291                 }
293                 typename Map<T>::const_iterator half0Fnd = half0Values.find(i);
295                 if (half0Fnd != half0Values.end())
296                 {
297                     combine
298                     (
299                         pointValues,
300                         cop,
301                         meshPts[e[1]],
302                         half0Fnd()
303                     );
304                 }
305             }
306         }
307     }
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)
317     {
318         if (hasTransformation)
319         {
320             WarningIn
321             (
322                 "syncTools<class T, class CombineOp>::syncPointMap"
323                 "(const polyMesh&, Map<T>&, const CombineOp&"
324                 ", const bool)"
325             )   << "There are decomposed cyclics in this mesh with"
326                 << " transformations." << endl
327                 << "This is not supported. The result will be incorrect"
328                 << endl;
329         }
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)
341         {
342             label meshPointI = sharedPtLabels[i];
344             typename Map<T>::const_iterator fnd =
345                 pointValues.find(meshPointI);
347             if (fnd != pointValues.end())
348             {
349                 combine
350                 (
351                     sharedPointValues,
352                     cop,
353                     sharedPtAddr[i],    // index
354                     fnd()               // value
355                 );
356             }
357         }
359         // Reduce on master.
361         if (Pstream::parRun())
362         {
363             if (Pstream::master())
364             {
365                 // Receive the edges using shared points from the slave.
366                 for
367                 (
368                     int slave=Pstream::firstSlave();
369                     slave<=Pstream::lastSlave();
370                     slave++
371                 )
372                 {
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)
378                     {
379                         combine
380                         (
381                             sharedPointValues,
382                             cop,
383                             iter.key(), // edge
384                             iter()      // value
385                         );
386                     }
387                 }
389                 // Send back
390                 for
391                 (
392                     int slave=Pstream::firstSlave();
393                     slave<=Pstream::lastSlave();
394                     slave++
395                 )
396                 {
397                     OPstream toSlave(Pstream::blocking, slave);
398                     toSlave << sharedPointValues;
399                 }
400             }
401             else
402             {
403                 // Send to master
404                 {
405                     OPstream toMaster
406                     (
407                         Pstream::blocking,
408                         Pstream::masterNo()
409                     );
410                     toMaster << sharedPointValues;
411                 }
412                 // Receive merged values
413                 {
414                     IPstream fromMaster
415                     (
416                         Pstream::blocking,
417                         Pstream::masterNo()
418                     );
419                     fromMaster >> sharedPointValues;
420                 }
421             }
422         }
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)
431         {
432             sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
433         }
435         forAllConstIter(Map<label>, sharedToMeshPoint, iter)
436         {
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())
442             {
443                 combine
444                 (
445                     pointValues,
446                     cop,
447                     iter(),     // index
448                     sharedFnd() // value
449                 );
450             }
451         }
452     }
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))
468     {
469         return;
470     }
473     // Do synchronisation without constructing globalEdge addressing
474     // (since this constructs mesh edge addressing)
477     // Swap proc patch info
478     // ~~~~~~~~~~~~~~~~~~~~
480     if (Pstream::parRun())
481     {
482         // Send
484         forAll(patches, patchI)
485         {
486             if
487             (
488                 isA<processorPolyPatch>(patches[patchI])
489              && patches[patchI].nEdges() > 0
490             )
491             {
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);
503                 forAll(edges, i)
504                 {
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())
512                     {
513                         const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
515                         if (nbrEdge[0] >= 0 && nbrEdge[1] >= 0)
516                         {
517                             patchInfo.insert(nbrEdge, iter());
518                         }
519                     }
520                 }
522                 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
523                 toNeighb << patchInfo;
524             }
525         }
528         // Receive and combine.
530         forAll(patches, patchI)
531         {
532             if
533             (
534                 isA<processorPolyPatch>(patches[patchI])
535              && patches[patchI].nEdges() > 0
536             )
537             {
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())
548                 {
549                     transformList(procPatch.forwardT(), nbrPatchInfo);
550                 }
551                 else if (applySeparation && procPatch.separated())
552                 {
553                     separateList(-procPatch.separation(), nbrPatchInfo);
554                 }
556                 // Only update those values which come from neighbour
558                 forAllConstIter
559                 (
560                     typename EdgeMap<T>,
561                     nbrPatchInfo,
562                     nbrIter
563                 )
564                 {
565                     const edge& e = nbrIter.key();
566                     const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
568                     combine
569                     (
570                         edgeValues,
571                         cop,
572                         meshEdge,   // edge
573                         nbrIter()   // value
574                     );
575                 }
576             }
577         }
578     }
581     // Swap cyclic info
582     // ~~~~~~~~~~~~~~~~
584     forAll(patches, patchI)
585     {
586         if (isA<cyclicPolyPatch>(patches[patchI]))
587         {
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)
601             {
602                 const edge& twoEdges = coupledEdges[i];
604                 {
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())
612                     {
613                         half0Values.insert(i, iter());
614                     }
615                 }
616                 {
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())
624                     {
625                         half1Values.insert(i, iter());
626                     }
627                 }
628             }
631             // Transform
633             if (!cycPatch.parallel())
634             {
635                 transformList(cycPatch.reverseT(), half0Values);
636                 transformList(cycPatch.forwardT(), half1Values);
637             }
638             else if (applySeparation && cycPatch.separated())
639             {
640                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
641                 separateList(v, half0Values);
642                 separateList(-v, half1Values);
643             }
646             // Extract and combine information
648             forAll(coupledEdges, i)
649             {
650                 const edge& twoEdges = coupledEdges[i];
652                 typename Map<T>::const_iterator half1Fnd =
653                     half1Values.find(i);
655                 if (half1Fnd != half1Values.end())
656                 {
657                     const edge& e0 = edges[twoEdges[0]];
658                     const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
660                     combine
661                     (
662                         edgeValues,
663                         cop,
664                         meshEdge0,  // edge
665                         half1Fnd()  // value
666                     );
667                 }
669                 typename Map<T>::const_iterator half0Fnd =
670                     half0Values.find(i);
671                 if (half0Fnd != half0Values.end())
672                 {
673                     const edge& e1 = edges[twoEdges[1]];
674                     const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
676                     combine
677                     (
678                         edgeValues,
679                         cop,
680                         meshEdge1,  // edge
681                         half0Fnd()  // value
682                     );
683                 }
684             }
685         }
686     }
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)
700     {
701         meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
702     }
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++)
715     {
716         const face& f = mesh.faces()[faceI];
718         forAll(f, fp)
719         {
720             label v0 = f[fp];
721             label v1 = f[f.fcIndex(fp)];
723             Map<label>::const_iterator v0Fnd = meshToShared.find(v0);
725             if (v0Fnd != meshToShared.end())
726             {
727                 Map<label>::const_iterator v1Fnd = meshToShared.find(v1);
729                 if (v1Fnd != meshToShared.end())
730                 {
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())
743                     {
744                         // edge exists in edgeValues. See if already in map
745                         // (since on same processor, e.g. cyclic)
746                         combine
747                         (
748                             sharedEdgeValues,
749                             cop,
750                             sharedEdge, // edge
751                             edgeFnd()   // value
752                         );
753                     }
754                 }
755             }
756         }
757     }
760     // Now sharedEdgeValues will contain per potential sharedEdge the value.
761     // (potential since an edge having two shared points is not nessecary a
762     //  shared edge).
763     // Reduce this on the master.
765     if (Pstream::parRun())
766     {
767         if (Pstream::master())
768         {
769             // Receive the edges using shared points from the slave.
770             for
771             (
772                 int slave=Pstream::firstSlave();
773                 slave<=Pstream::lastSlave();
774                 slave++
775             )
776             {
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)
782                 {
783                     combine
784                     (
785                         sharedEdgeValues,
786                         cop,
787                         iter.key(), // edge
788                         iter()      // value
789                     );
790                 }
791             }
793             // Send back
794             for
795             (
796                 int slave=Pstream::firstSlave();
797                 slave<=Pstream::lastSlave();
798                 slave++
799             )
800             {
802                 OPstream toSlave(Pstream::blocking, slave);
803                 toSlave << sharedEdgeValues;
804             }
805         }
806         else
807         {
808             // Send to master
809             {
810                 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
811                 toMaster << sharedEdgeValues;
812             }
813             // Receive merged values
814             {
815                 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
816                 fromMaster >> sharedEdgeValues;
817             }
818         }
819     }
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)
827     {
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())
836         {
837             combine
838             (
839                 edgeValues,
840                 cop,
841                 meshEdge,       // edge
842                 sharedFnd()     // value
843             );
844         }
845     }
849 template <class T, class CombineOp>
850 void Foam::syncTools::syncPointList
852     const polyMesh& mesh,
853     UList<T>& pointValues,
854     const CombineOp& cop,
855     const T& nullValue,
856     const bool applySeparation
859     if (pointValues.size() != mesh.nPoints())
860     {
861         FatalErrorIn
862         (
863             "syncTools<class T, class CombineOp>::syncPointList"
864             "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
865             ", const bool)"
866         )   << "Number of values " << pointValues.size()
867             << " is not equal to the number of points in the mesh "
868             << mesh.nPoints() << abort(FatalError);
869     }
871     const polyBoundaryMesh& patches = mesh.boundaryMesh();
873     if (!hasCouples(patches))
874     {
875         return;
876     }
878     // Is there any coupled patch with transformation?
879     bool hasTransformation = false;
881     if (Pstream::parRun())
882     {
883         // Send
885         forAll(patches, patchI)
886         {
887             if
888             (
889                 isA<processorPolyPatch>(patches[patchI])
890              && patches[patchI].nPoints() > 0
891             )
892             {
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)
903                 {
904                     label nbrPointI = nbrPts[pointI];
905                     if (nbrPointI >= 0 && nbrPointI < patchInfo.size())
906                     {
907                         patchInfo[nbrPointI] = pointValues[meshPts[pointI]];
908                     }
909                 }
911                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
912                 toNbr << patchInfo;
913             }
914         }
917         // Receive and combine.
919         forAll(patches, patchI)
920         {
921             if
922             (
923                 isA<processorPolyPatch>(patches[patchI])
924              && patches[patchI].nPoints() > 0
925             )
926             {
927                 const processorPolyPatch& procPatch =
928                     refCast<const processorPolyPatch>(patches[patchI]);
929                 checkTransform(procPatch, applySeparation);
931                 List<T> nbrPatchInfo(procPatch.nPoints());
932                 {
933                     // We do not know the number of points on the other side
934                     // so cannot use Pstream::read.
935                     IPstream fromNbr
936                     (
937                         Pstream::blocking,
938                         procPatch.neighbProcNo()
939                     );
940                     fromNbr >> nbrPatchInfo;
941                 }
942                 // Null any value which is not on neighbouring processor
943                 nbrPatchInfo.setSize(procPatch.nPoints(), nullValue);
945                 if (!procPatch.parallel())
946                 {
947                     hasTransformation = true;
948                     transformList(procPatch.forwardT(), nbrPatchInfo);
949                 }
950                 else if (applySeparation && procPatch.separated())
951                 {
952                     hasTransformation = true;
953                     separateList(-procPatch.separation(), nbrPatchInfo);
954                 }
956                 const labelList& meshPts = procPatch.meshPoints();
958                 forAll(meshPts, pointI)
959                 {
960                     label meshPointI = meshPts[pointI];
961                     cop(pointValues[meshPointI], nbrPatchInfo[pointI]);
962                 }
963             }
964         }
965     }
967     // Do the cyclics.
968     forAll(patches, patchI)
969     {
970         if (isA<cyclicPolyPatch>(patches[patchI]))
971         {
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)
984             {
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];
992             }
994             if (!cycPatch.parallel())
995             {
996                 hasTransformation = true;
997                 transformList(cycPatch.reverseT(), half0Values);
998                 transformList(cycPatch.forwardT(), half1Values);
999             }
1000             else if (applySeparation && cycPatch.separated())
1001             {
1002                 hasTransformation = true;
1003                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1004                 separateList(v, half0Values);
1005                 separateList(-v, half1Values);
1006             }
1008             forAll(coupledPoints, i)
1009             {
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]);
1017             }
1018         }
1019     }
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)
1029     {
1030         if (hasTransformation)
1031         {
1032             WarningIn
1033             (
1034                 "syncTools<class T, class CombineOp>::syncPointList"
1035                 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1036                 ", const bool)"
1037             )   << "There are decomposed cyclics in this mesh with"
1038                 << " transformations." << endl
1039                 << "This is not supported. The result will be incorrect"
1040                 << endl;
1041         }
1044         // Values on shared points.
1045         List<T> sharedPts(pd.nGlobalPoints(), nullValue);
1047         forAll(pd.sharedPointLabels(), i)
1048         {
1049             label meshPointI = pd.sharedPointLabels()[i];
1050             // Fill my entries in the shared points
1051             sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
1052         }
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)
1061         {
1062             label meshPointI = pd.sharedPointLabels()[i];
1063             pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
1064         }
1065     }
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,
1076     const T& nullValue,
1077     const bool applySeparation
1080     if (pointValues.size() != meshPoints.size())
1081     {
1082         FatalErrorIn
1083         (
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);
1090     }
1092     if (!hasCouples(mesh.boundaryMesh()))
1093     {
1094         return;
1095     }
1097     List<T> meshValues(mesh.nPoints(), nullValue);
1099     forAll(meshPoints, i)
1100     {
1101         meshValues[meshPoints[i]] = pointValues[i];
1102     }
1104     syncTools::syncPointList
1105     (
1106         mesh,
1107         meshValues,
1108         cop,            // combine op
1109         nullValue,      // null value
1110         applySeparation // separation
1111     );
1113     forAll(meshPoints, i)
1114     {
1115         pointValues[i] = meshValues[meshPoints[i]];
1116     }
1120 template <class T, class CombineOp>
1121 void Foam::syncTools::syncEdgeList
1123     const polyMesh& mesh,
1124     UList<T>& edgeValues,
1125     const CombineOp& cop,
1126     const T& nullValue,
1127     const bool applySeparation
1130     if (edgeValues.size() != mesh.nEdges())
1131     {
1132         FatalErrorIn
1133         (
1134             "syncTools<class T, class CombineOp>::syncEdgeList"
1135             "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1136             ", const bool)"
1137         )   << "Number of values " << edgeValues.size()
1138             << " is not equal to the number of edges in the mesh "
1139             << mesh.nEdges() << abort(FatalError);
1140     }
1142     const polyBoundaryMesh& patches = mesh.boundaryMesh();
1144     if (!hasCouples(patches))
1145     {
1146         return;
1147     }
1149     // Is there any coupled patch with transformation?
1150     bool hasTransformation = false;
1152     if (Pstream::parRun())
1153     {
1154         // Send
1156         forAll(patches, patchI)
1157         {
1158             if
1159             (
1160                 isA<processorPolyPatch>(patches[patchI])
1161              && patches[patchI].nEdges() > 0
1162             )
1163             {
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)
1174                 {
1175                     label nbrEdgeI = neighbEdges[edgeI];
1177                     if (nbrEdgeI >= 0 && nbrEdgeI < patchInfo.size())
1178                     {
1179                         patchInfo[nbrEdgeI] = edgeValues[meshEdges[edgeI]];
1180                     }
1181                 }
1183                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1184                 toNbr << patchInfo;
1185             }
1186         }
1188         // Receive and combine.
1190         forAll(patches, patchI)
1191         {
1192             if
1193             (
1194                 isA<processorPolyPatch>(patches[patchI])
1195              && patches[patchI].nEdges() > 0
1196             )
1197             {
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());
1209                 {
1210                     IPstream fromNeighb
1211                     (
1212                         Pstream::blocking,
1213                         procPatch.neighbProcNo()
1214                     );
1215                     fromNeighb >> nbrPatchInfo;
1216                 }
1217                 // Null any value which is not on neighbouring processor
1218                 nbrPatchInfo.setSize(procPatch.nEdges(), nullValue);
1220                 if (!procPatch.parallel())
1221                 {
1222                     hasTransformation = true;
1223                     transformList(procPatch.forwardT(), nbrPatchInfo);
1224                 }
1225                 else if (applySeparation && procPatch.separated())
1226                 {
1227                     hasTransformation = true;
1228                     separateList(-procPatch.separation(), nbrPatchInfo);
1229                 }
1231                 forAll(meshEdges, edgeI)
1232                 {
1233                     label meshEdgeI = meshEdges[edgeI];
1235                     cop(edgeValues[meshEdgeI], nbrPatchInfo[edgeI]);
1236                 }
1237             }
1238         }
1239     }
1241     // Do the cyclics.
1242     forAll(patches, patchI)
1243     {
1244         if (isA<cyclicPolyPatch>(patches[patchI]))
1245         {
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)
1258             {
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];
1266             }
1268             if (!cycPatch.parallel())
1269             {
1270                 hasTransformation = true;
1271                 transformList(cycPatch.reverseT(), half0Values);
1272                 transformList(cycPatch.forwardT(), half1Values);
1273             }
1274             else if (applySeparation && cycPatch.separated())
1275             {
1276                 hasTransformation = true;
1278                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1279                 separateList(v, half0Values);
1280                 separateList(-v, half1Values);
1281             }
1283             forAll(coupledEdges, i)
1284             {
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]);
1292             }
1293         }
1294     }
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)
1304     {
1305         if (hasTransformation)
1306         {
1307             WarningIn
1308             (
1309                 "syncTools<class T, class CombineOp>::syncEdgeList"
1310                 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
1311                 ", const bool)"
1312             )   << "There are decomposed cyclics in this mesh with"
1313                 << " transformations." << endl
1314                 << "This is not supported. The result will be incorrect"
1315                 << endl;
1316         }
1318         // Values on shared edges.
1319         List<T> sharedPts(pd.nGlobalEdges(), nullValue);
1321         forAll(pd.sharedEdgeLabels(), i)
1322         {
1323             label meshEdgeI = pd.sharedEdgeLabels()[i];
1325             // Fill my entries in the shared edges
1326             sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
1327         }
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)
1336         {
1337             label meshEdgeI = pd.sharedEdgeLabels()[i];
1338             edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
1339         }
1340     }
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)
1356     {
1357         FatalErrorIn
1358         (
1359             "syncTools<class T, class CombineOp>::syncBoundaryFaceList"
1360             "(const polyMesh&, UList<T>&, const CombineOp&"
1361             ", const bool)"
1362         )   << "Number of values " << faceValues.size()
1363             << " is not equal to the number of boundary faces in the mesh "
1364             << nBFaces << abort(FatalError);
1365     }
1367     const polyBoundaryMesh& patches = mesh.boundaryMesh();
1369     if (!hasCouples(patches))
1370     {
1371         return;
1372     }
1375     if (Pstream::parRun())
1376     {
1377         // Send
1379         forAll(patches, patchI)
1380         {
1381             if
1382             (
1383                 isA<processorPolyPatch>(patches[patchI])
1384              && patches[patchI].size() > 0
1385             )
1386             {
1387                 const processorPolyPatch& procPatch =
1388                     refCast<const processorPolyPatch>(patches[patchI]);
1390                 label patchStart = procPatch.start()-mesh.nInternalFaces();
1392                 if (contiguous<T>())
1393                 {
1394                     OPstream::write
1395                     (
1396                         Pstream::blocking,
1397                         procPatch.neighbProcNo(),
1398                         reinterpret_cast<const char*>(&faceValues[patchStart]),
1399                         procPatch.size()*sizeof(T)
1400                     );
1401                 }
1402                 else
1403                 {
1404                     OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1405                     toNbr <<
1406                         SubList<T>(faceValues, procPatch.size(), patchStart);
1407                 }
1408             }
1409         }
1412         // Receive and combine.
1414         forAll(patches, patchI)
1415         {
1416             if
1417             (
1418                 isA<processorPolyPatch>(patches[patchI])
1419              && patches[patchI].size() > 0
1420             )
1421             {
1422                 const processorPolyPatch& procPatch =
1423                     refCast<const processorPolyPatch>(patches[patchI]);
1425                 List<T> nbrPatchInfo(procPatch.size());
1427                 if (contiguous<T>())
1428                 {
1429                     IPstream::read
1430                     (
1431                         Pstream::blocking,
1432                         procPatch.neighbProcNo(),
1433                         reinterpret_cast<char*>(nbrPatchInfo.begin()),
1434                         nbrPatchInfo.byteSize()
1435                     );
1436                 }
1437                 else
1438                 {
1439                     IPstream fromNeighb
1440                     (
1441                         Pstream::blocking,
1442                         procPatch.neighbProcNo()
1443                     );
1444                     fromNeighb >> nbrPatchInfo;
1445                 }
1447                 if (!procPatch.parallel())
1448                 {
1449                     transformList(procPatch.forwardT(), nbrPatchInfo);
1450                 }
1451                 else if (applySeparation && procPatch.separated())
1452                 {
1453                     separateList(-procPatch.separation(), nbrPatchInfo);
1454                 }
1457                 label bFaceI = procPatch.start()-mesh.nInternalFaces();
1459                 forAll(nbrPatchInfo, i)
1460                 {
1461                     cop(faceValues[bFaceI++], nbrPatchInfo[i]);
1462                 }
1463             }
1464         }
1465     }
1467     // Do the cyclics.
1468     forAll(patches, patchI)
1469     {
1470         if (isA<cyclicPolyPatch>(patches[patchI]))
1471         {
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())
1484             {
1485                 transformList(cycPatch.reverseT(), half0Values);
1486                 transformList(cycPatch.forwardT(), half1Values);
1487             }
1488             else if (applySeparation && cycPatch.separated())
1489             {
1490                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
1491                 separateList(v, half0Values);
1492                 separateList(-v, half1Values);
1493             }
1495             label i0 = patchStart;
1496             forAll(half1Values, i)
1497             {
1498                 cop(faceValues[i0++], half1Values[i]);
1499             }
1501             label i1 = half1Start;
1502             forAll(half0Values, i)
1503             {
1504                 cop(faceValues[i1++], half0Values[i]);
1505             }
1506         }
1507     }
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())
1521     {
1522         FatalErrorIn
1523         (
1524             "syncTools<class T, class CombineOp>::syncFaceList"
1525             "(const polyMesh&, UList<T>&, const CombineOp&"
1526             ", const bool)"
1527         )   << "Number of values " << faceValues.size()
1528             << " is not equal to the number of faces in the mesh "
1529             << mesh.nFaces() << abort(FatalError);
1530     }
1532     SubList<T> bndValues
1533     (
1534         faceValues,
1535         mesh.nFaces()-mesh.nInternalFaces(),
1536         mesh.nInternalFaces()
1537     );
1539     syncBoundaryFaceList
1540     (
1541         mesh,
1542         bndValues,
1543         cop,
1544         applySeparation
1545     );
1549 template <class T>
1550 void Foam::syncTools::swapBoundaryFaceList
1552     const polyMesh& mesh,
1553     UList<T>& faceValues,
1554     const bool applySeparation
1557     syncBoundaryFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
1561 template <class T>
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())
1582     {
1583         FatalErrorIn
1584         (
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);
1590     }
1592     const polyBoundaryMesh& patches = mesh.boundaryMesh();
1594     if (!hasCouples(patches))
1595     {
1596         return;
1597     }
1599     // Patch data (proc patches only).
1600     List<List<unsigned int> > patchValues(patches.size());
1602     if (Pstream::parRun())
1603     {
1604         // Send
1606         forAll(patches, patchI)
1607         {
1608             if
1609             (
1610                 isA<processorPolyPatch>(patches[patchI])
1611              && patches[patchI].size() > 0
1612             )
1613             {
1614                 const processorPolyPatch& procPatch =
1615                     refCast<const processorPolyPatch>(patches[patchI]);
1617                 patchValues[patchI].setSize(procPatch.size());
1618                 forAll(procPatch, i)
1619                 {
1620                     patchValues[patchI][i] =
1621                         faceValues.get(procPatch.start()+i);
1622                 }
1624                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1625                 toNbr << patchValues[patchI];
1626             }
1627         }
1630         // Receive and combine.
1632         forAll(patches, patchI)
1633         {
1634             if
1635             (
1636                 isA<processorPolyPatch>(patches[patchI])
1637              && patches[patchI].size() > 0
1638             )
1639             {
1640                 const processorPolyPatch& procPatch =
1641                     refCast<const processorPolyPatch>(patches[patchI]);
1643                 {
1644                     IPstream fromNbr
1645                     (
1646                         Pstream::blocking,
1647                         procPatch.neighbProcNo()
1648                     );
1649                     fromNbr >> patchValues[patchI];
1650                 }
1652                 // Combine (bitwise)
1653                 forAll(procPatch, i)
1654                 {
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);
1660                 }
1661             }
1662         }
1663     }
1665     // Do the cyclics.
1666     forAll(patches, patchI)
1667     {
1668         if (isA<cyclicPolyPatch>(patches[patchI]))
1669         {
1670             const cyclicPolyPatch& cycPatch =
1671                 refCast<const cyclicPolyPatch>(patches[patchI]);
1673             label half = cycPatch.size()/2;
1675             for (label i = 0; i < half; i++)
1676             {
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;
1683                 cop(t, val1);
1684                 faceValues.set(meshFace0, t);
1686                 cop(val1, val0);
1687                 faceValues.set(meshFace1, val1);
1688             }
1689         }
1690     }
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())
1715     {
1716         FatalErrorIn
1717         (
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);
1724     }
1726     const polyBoundaryMesh& patches = mesh.boundaryMesh();
1728     if (!hasCouples(patches))
1729     {
1730         return;
1731     }
1733     // Patch data (proc patches only).
1734     List<List<unsigned int> > patchValues(patches.size());
1736     if (Pstream::parRun())
1737     {
1738         // Send
1740         forAll(patches, patchI)
1741         {
1742             if
1743             (
1744                 isA<processorPolyPatch>(patches[patchI])
1745              && patches[patchI].nPoints() > 0
1746             )
1747             {
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)
1758                 {
1759                     label nbrPointI = nbrPts[pointI];
1760                     if (nbrPointI >= 0 && nbrPointI < procPatch.nPoints())
1761                     {
1762                         patchValues[patchI][nbrPointI] =
1763                             pointValues.get(meshPts[pointI]);
1764                     }
1765                 }
1767                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1768                 toNbr << patchValues[patchI];
1769             }
1770         }
1773         // Receive and combine.
1775         forAll(patches, patchI)
1776         {
1777             if
1778             (
1779                 isA<processorPolyPatch>(patches[patchI])
1780              && patches[patchI].nPoints() > 0
1781             )
1782             {
1783                 const processorPolyPatch& procPatch =
1784                     refCast<const processorPolyPatch>(patches[patchI]);
1786                 {
1787                     // We do not know the number of points on the other side
1788                     // so cannot use Pstream::read.
1789                     IPstream fromNbr
1790                     (
1791                         Pstream::blocking,
1792                         procPatch.neighbProcNo()
1793                     );
1794                     fromNbr >> patchValues[patchI];
1795                 }
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)
1803                 {
1804                     label meshPointI = meshPts[pointI];
1805                     unsigned int pointVal = pointValues.get(meshPointI);
1806                     cop(pointVal, patchValues[patchI][pointI]);
1807                     pointValues.set(meshPointI, pointVal);
1808                 }
1809             }
1810         }
1811     }
1813     // Do the cyclics.
1814     forAll(patches, patchI)
1815     {
1816         if (isA<cyclicPolyPatch>(patches[patchI]))
1817         {
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)
1825             {
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);
1835                 cop(t, val1);
1836                 pointValues.set(point0, t);
1837                 cop(val1, val0);
1838                 pointValues.set(point1, val1);
1839             }
1840         }
1841     }
1843     // Synchronize multiple shared points.
1844     const globalMeshData& pd = mesh.globalData();
1846     if (pd.nGlobalPoints() > 0)
1847     {
1848         // Values on shared points. Use unpacked storage for ease!
1849         List<unsigned int> sharedPts(pd.nGlobalPoints(), nullValue);
1851         forAll(pd.sharedPointLabels(), i)
1852         {
1853             label meshPointI = pd.sharedPointLabels()[i];
1854             // Fill my entries in the shared points
1855             sharedPts[pd.sharedPointAddr()[i]] = pointValues.get(meshPointI);
1856         }
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)
1865         {
1866             label meshPointI = pd.sharedPointLabels()[i];
1867             pointValues.set(meshPointI, sharedPts[pd.sharedPointAddr()[i]]);
1868         }
1869     }
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())
1883     {
1884         FatalErrorIn
1885         (
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);
1892     }
1894     const polyBoundaryMesh& patches = mesh.boundaryMesh();
1896     if (!hasCouples(patches))
1897     {
1898         return;
1899     }
1901     // Patch data (proc patches only).
1902     List<List<unsigned int> > patchValues(patches.size());
1904     if (Pstream::parRun())
1905     {
1906         // Send
1908         forAll(patches, patchI)
1909         {
1910             if
1911             (
1912                 isA<processorPolyPatch>(patches[patchI])
1913              && patches[patchI].nEdges() > 0
1914             )
1915             {
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)
1925                 {
1926                     label nbrEdgeI = neighbEdges[edgeI];
1927                     if (nbrEdgeI >= 0 && nbrEdgeI < procPatch.nEdges())
1928                     {
1929                         patchValues[patchI][nbrEdgeI] =
1930                             edgeValues.get(meshEdges[edgeI]);
1931                     }
1932                 }
1934                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
1935                 toNbr << patchValues[patchI];
1936             }
1937         }
1940         // Receive and combine.
1942         forAll(patches, patchI)
1943         {
1944             if
1945             (
1946                 isA<processorPolyPatch>(patches[patchI])
1947              && patches[patchI].nEdges() > 0
1948             )
1949             {
1950                 const processorPolyPatch& procPatch =
1951                     refCast<const processorPolyPatch>(patches[patchI]);
1953                 {
1954                     IPstream fromNeighb
1955                     (
1956                         Pstream::blocking,
1957                         procPatch.neighbProcNo()
1958                     );
1959                     fromNeighb >> patchValues[patchI];
1960                 }
1962                 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
1964                 const labelList& meshEdges = procPatch.meshEdges();
1966                 forAll(meshEdges, edgeI)
1967                 {
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);
1973                 }
1974             }
1975         }
1976     }
1978     // Do the cyclics.
1979     forAll(patches, patchI)
1980     {
1981         if (isA<cyclicPolyPatch>(patches[patchI]))
1982         {
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)
1990             {
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);
2000                 cop(t, val1);
2001                 edgeValues.set(edge0, t);
2002                 cop(val1, val0);
2003                 edgeValues.set(edge1, val1);
2004             }
2005         }
2006     }
2008     // Synchronize multiple shared edges.
2009     const globalMeshData& pd = mesh.globalData();
2011     if (pd.nGlobalEdges() > 0)
2012     {
2013         // Values on shared edges. Use unpacked storage for ease!
2014         List<unsigned int> sharedPts(pd.nGlobalEdges(), nullValue);
2016         forAll(pd.sharedEdgeLabels(), i)
2017         {
2018             label meshEdgeI = pd.sharedEdgeLabels()[i];
2019             // Fill my entries in the shared edges
2020             sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues.get(meshEdgeI);
2021         }
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)
2030         {
2031             label meshEdgeI = pd.sharedEdgeLabels()[i];
2032             edgeValues.set(meshEdgeI, sharedPts[pd.sharedEdgeAddr()[i]]);
2033         }
2034     }
2038 // ************************ vim: set sw=4 sts=4 et: ************************ //