syncToolsTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2024 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "syncTools.H"
30 #include "polyMesh.H"
31 #include "processorPolyPatch.H"
32 #include "cyclicPolyPatch.H"
33 #include "globalMeshData.H"
34 #include "transformList.H"
35 
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 
38 template<class T, class CombineOp>
39 void Foam::syncTools::combine
40 (
41  Map<T>& pointValues,
42  const CombineOp& cop,
43  const label index,
44  const T& val
45 )
46 {
47  auto iter = pointValues.find(index);
48 
49  if (iter.good())
50  {
51  cop(iter.val(), val);
52  }
53  else
54  {
55  pointValues.insert(index, val);
56  }
57 }
58 
59 
60 template<class T, class CombineOp>
61 void Foam::syncTools::combine
62 (
63  EdgeMap<T>& edgeValues,
64  const CombineOp& cop,
65  const edge& index,
66  const T& val
67 )
68 {
69  auto iter = edgeValues.find(index);
70 
71  if (iter.good())
72  {
73  cop(iter.val(), val);
74  }
75  else
76  {
77  edgeValues.insert(index, val);
78  }
79 }
80 
81 
82 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
83 
84 template<class T, class CombineOp, class TransformOp>
86 (
87  const polyMesh& mesh,
88  Map<T>& pointValues, // from mesh point label to value
89  const CombineOp& cop,
90  const TransformOp& top
91 )
92 {
94 
95  // Make sure we use unique message tag
96  const int oldTag = UPstream::incrMsgType();
97 
98  // Synchronize multiple shared points.
99  const globalMeshData& pd = mesh.globalData();
100 
101  // Values on shared points. Keyed on global shared index.
102  Map<T> sharedPointValues;
103 
104  if (pd.nGlobalPoints() > 0)
105  {
106  // meshPoint per local index
107  const labelList& sharedPtLabels = pd.sharedPointLabels();
108 
109  // global shared index per local index
110  const labelList& sharedPtAddr = pd.sharedPointAddr();
111 
112  sharedPointValues.reserve(sharedPtAddr.size());
113 
114  // Fill my entries in the shared points
115  forAll(sharedPtLabels, i)
116  {
117  const auto fnd = pointValues.cfind(sharedPtLabels[i]);
118 
119  if (fnd.good())
120  {
121  combine
122  (
123  sharedPointValues,
124  cop,
125  sharedPtAddr[i], // index
126  fnd.val() // value
127  );
128  }
129  }
130  }
131 
132 
133  if (UPstream::parRun())
134  {
135  // Presize according to number of processor patches
136  // (global topology information may not yet be available...)
137  DynamicList<label> neighbProcs(patches.nProcessorPatches());
138  PstreamBuffers pBufs;
139 
140  // Reduce communication by only sending non-zero data,
141  // but with multiply-connected processor/processor
142  // (eg, processorCyclic) also need to send zero information
143  // to keep things synchronised
144 
145  // Initialize for registerSend() bookkeeping
146  pBufs.initRegisterSend();
147 
148 
149  // Sample and send.
150 
151  for (const polyPatch& pp : patches)
152  {
153  const auto* ppp = isA<processorPolyPatch>(pp);
154 
155  if (ppp && pp.nPoints())
156  {
157  const auto& procPatch = *ppp;
158  const label nbrProci = procPatch.neighbProcNo();
159 
160  // Get data per patchPoint in neighbouring point numbers.
161  const labelList& meshPts = procPatch.meshPoints();
162  const labelList& nbrPts = procPatch.neighbPoints();
163 
164  // Extract local values. Create map from nbrPoint to value.
165  // Note: how small initial size?
166  Map<T> patchInfo(meshPts.size() / 20);
167 
168  forAll(meshPts, i)
169  {
170  const auto iter = pointValues.cfind(meshPts[i]);
171 
172  if (iter.good())
173  {
174  patchInfo.insert(nbrPts[i], iter.val());
175  }
176  }
177 
178  // Neighbour connectivity
179  neighbProcs.push_uniq(nbrProci);
180 
181  // Send to neighbour
182  {
183  UOPstream toNbr(nbrProci, pBufs);
184  toNbr << patchInfo;
185 
186  // Record if send is required (data are non-zero)
187  pBufs.registerSend(nbrProci, !patchInfo.empty());
188  }
189  }
190  }
191 
192  // Limit exchange to involved procs.
193  // - automatically discards unnecessary (unregistered) sends
194  pBufs.finishedNeighbourSends(neighbProcs);
195 
196 
197  // Receive and combine.
198  for (const polyPatch& pp : patches)
199  {
200  const auto* ppp = isA<processorPolyPatch>(pp);
201 
202  if (ppp && pp.nPoints())
203  {
204  const auto& procPatch = *ppp;
205  const label nbrProci = procPatch.neighbProcNo();
206 
207  if (!pBufs.recvDataCount(nbrProci))
208  {
209  // Nothing to receive
210  continue;
211  }
212 
213  Map<T> nbrPatchInfo;
214  {
215  UIPstream fromNbr(nbrProci, pBufs);
216  fromNbr >> nbrPatchInfo;
217  }
218 
219  // Transform
220  top(procPatch, nbrPatchInfo);
221 
222  const labelList& meshPts = procPatch.meshPoints();
223 
224  // Only update those values which come from neighbour
225  forAllConstIters(nbrPatchInfo, nbrIter)
226  {
227  combine
228  (
229  pointValues,
230  cop,
231  meshPts[nbrIter.key()],
232  nbrIter.val()
233  );
234  }
235  }
236  }
237  }
238 
239  // Do the cyclics.
240  for (const polyPatch& pp : patches)
241  {
242  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
243 
244  if (cpp && cpp->owner())
245  {
246  // Owner does all.
247 
248  const cyclicPolyPatch& cycPatch = *cpp;
249  const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
250 
251  const edgeList& coupledPoints = cycPatch.coupledPoints();
252  const labelList& meshPtsA = cycPatch.meshPoints();
253  const labelList& meshPtsB = nbrPatch.meshPoints();
254 
255  // Extract local values. Create map from coupled-edge to value.
256  Map<T> half0Values(meshPtsA.size() / 20);
257  Map<T> half1Values(half0Values.size());
258 
259  forAll(coupledPoints, i)
260  {
261  const edge& e = coupledPoints[i];
262 
263  const auto point0Fnd = pointValues.cfind(meshPtsA[e[0]]);
264 
265  if (point0Fnd.good())
266  {
267  half0Values.insert(i, *point0Fnd);
268  }
269 
270  const auto point1Fnd = pointValues.cfind(meshPtsB[e[1]]);
271 
272  if (point1Fnd.good())
273  {
274  half1Values.insert(i, *point1Fnd);
275  }
276  }
277 
278  // Transform to receiving side
279  top(cycPatch, half1Values);
280  top(nbrPatch, half0Values);
281 
282  forAll(coupledPoints, i)
283  {
284  const edge& e = coupledPoints[i];
285 
286  const auto half0Fnd = half0Values.cfind(i);
287 
288  if (half0Fnd.good())
289  {
290  combine
291  (
292  pointValues,
293  cop,
294  meshPtsB[e[1]],
295  *half0Fnd
296  );
297  }
298 
299  const auto half1Fnd = half1Values.cfind(i);
300 
301  if (half1Fnd.good())
302  {
303  combine
304  (
305  pointValues,
306  cop,
307  meshPtsA[e[0]],
308  *half1Fnd
309  );
310  }
311  }
312  }
313  }
314 
315  // Synchronize multiple shared points.
316  if (pd.nGlobalPoints() > 0)
317  {
318  // meshPoint per local index
319  const labelList& sharedPtLabels = pd.sharedPointLabels();
320  // global shared index per local index
321  const labelList& sharedPtAddr = pd.sharedPointAddr();
322 
323  // Reduce on master.
324 
325  if (UPstream::parRun())
326  {
327  if (UPstream::master())
328  {
329  // Receive the edges using shared points from other procs
330  for (const int proci : UPstream::subProcs())
331  {
332  Map<T> nbrValues;
333  IPstream::recv(nbrValues, proci);
334 
335  // Merge neighbouring values with my values
336  forAllConstIters(nbrValues, iter)
337  {
338  combine
339  (
340  sharedPointValues,
341  cop,
342  iter.key(), // edge
343  iter.val() // value
344  );
345  }
346  }
347  }
348  else
349  {
350  // Send to master
351  OPstream::send(sharedPointValues, UPstream::masterNo());
352  }
353 
354  // Broadcast: send merged values to all
355  Pstream::broadcast(sharedPointValues);
356  }
357 
358  // Merge sharedPointValues (keyed on sharedPointAddr) into
359  // pointValues (keyed on mesh points).
360 
361  // Map from global shared index to meshpoint
362  Map<label> sharedToMeshPoint(sharedPtAddr, sharedPtLabels);
363 
364  forAllConstIters(sharedToMeshPoint, iter)
365  {
366  // Do I have a value for my shared point
367  const auto sharedFnd = sharedPointValues.cfind(iter.key());
368 
369  if (sharedFnd.good())
370  {
371  pointValues.set(iter.val(), sharedFnd.val());
372  }
373  }
374  }
375 
376  // Reset tag
377  UPstream::msgType(oldTag);
378 }
379 
380 
381 template<class T, class CombineOp, class TransformOp>
383 (
384  const polyMesh& mesh,
385  EdgeMap<T>& edgeValues,
386  const CombineOp& cop,
387  const TransformOp& top
388 )
389 {
391 
392 
393  // Do synchronisation without constructing globalEdge addressing
394  // (since this constructs mesh edge addressing)
395 
396  // Make sure we use unique message tag
397  const int oldTag = UPstream::incrMsgType();
398 
399  // Swap proc patch info
400  // ~~~~~~~~~~~~~~~~~~~~
401 
402  if (UPstream::parRun())
403  {
404  // Presize according to number of processor patches
405  // (global topology information may not yet be available...)
407  PstreamBuffers pBufs;
408 
409  // Reduce communication by only sending non-zero data,
410  // but with multiply-connected processor/processor
411  // (eg, processorCyclic) also need to send zero information
412  // to keep things synchronised
413 
414  // Initialize for registerSend() bookkeeping
415  pBufs.initRegisterSend();
416 
417 
418  // Sample and send.
419 
420  for (const polyPatch& pp : patches)
421  {
422  const auto* ppp = isA<processorPolyPatch>(pp);
423 
424  if (ppp && pp.nEdges())
425  {
426  const auto& procPatch = *ppp;
427  const label nbrProci = procPatch.neighbProcNo();
428 
429  // Get data per patch edge in neighbouring edge.
430  const edgeList& edges = procPatch.edges();
431  const labelList& meshPts = procPatch.meshPoints();
432  const labelList& nbrPts = procPatch.neighbPoints();
433 
434  EdgeMap<T> patchInfo(edges.size() / 20);
435 
436  for (const edge& e : edges)
437  {
438  const edge meshEdge(meshPts, e);
439 
440  const auto iter = edgeValues.cfind(meshEdge);
441 
442  if (iter.good())
443  {
444  const edge nbrEdge(nbrPts, e);
445  patchInfo.insert(nbrEdge, iter.val());
446  }
447  }
448 
449 
450  // Neighbour connectivity
451  neighbProcs.push_uniq(nbrProci);
452 
453  // Send to neighbour
454  {
455  UOPstream toNbr(nbrProci, pBufs);
456  toNbr << patchInfo;
457 
458  // Record if send is required (data are non-zero)
459  pBufs.registerSend(nbrProci, !patchInfo.empty());
460  }
461  }
462  }
463 
464  // Limit exchange to involved procs
465  // - automatically discards unnecessary (unregistered) sends
466  pBufs.finishedNeighbourSends(neighbProcs);
467 
468 
469  // Receive and combine.
470  for (const polyPatch& pp : patches)
471  {
472  const auto* ppp = isA<processorPolyPatch>(pp);
473 
474  if (ppp && pp.nEdges())
475  {
476  const auto& procPatch = *ppp;
477  const label nbrProci = procPatch.neighbProcNo();
478 
479  if (!pBufs.recvDataCount(nbrProci))
480  {
481  // Nothing to receive
482  continue;
483  }
484 
485  EdgeMap<T> nbrPatchInfo;
486  {
487  UIPstream fromNbr(nbrProci, pBufs);
488  fromNbr >> nbrPatchInfo;
489  }
490 
491  // Apply transform to convert to this side properties.
492  top(procPatch, nbrPatchInfo);
493 
494 
495  // Only update those values which come from neighbour
496  const labelList& meshPts = procPatch.meshPoints();
497 
498  forAllConstIters(nbrPatchInfo, nbrIter)
499  {
500  const edge& e = nbrIter.key();
501  const edge meshEdge(meshPts, e);
502 
503  combine
504  (
505  edgeValues,
506  cop,
507  meshEdge, // edge
508  nbrIter.val() // value
509  );
510  }
511  }
512  }
513  }
514 
515 
516  // Swap cyclic info
517  // ~~~~~~~~~~~~~~~~
518 
519  for (const polyPatch& pp : patches)
520  {
521  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
522 
523  if (cpp && cpp->owner())
524  {
525  // Owner does all.
526 
527  const cyclicPolyPatch& cycPatch = *cpp;
528  const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
529 
530  const edgeList& coupledEdges = cycPatch.coupledEdges();
531 
532  const labelList& meshPtsA = cycPatch.meshPoints();
533  const edgeList& edgesA = cycPatch.edges();
534 
535  const labelList& meshPtsB = nbrPatch.meshPoints();
536  const edgeList& edgesB = nbrPatch.edges();
537 
538  // Extract local values. Create map from edge to value.
539  Map<T> half0Values(edgesA.size() / 20);
540  Map<T> half1Values(half0Values.size());
541 
542  forAll(coupledEdges, edgei)
543  {
544  const edge& twoEdges = coupledEdges[edgei];
545 
546  {
547  const edge& e0 = edgesA[twoEdges[0]];
548  const edge meshEdge0(meshPtsA, e0);
549 
550  const auto iter = edgeValues.cfind(meshEdge0);
551 
552  if (iter.good())
553  {
554  half0Values.insert(edgei, iter.val());
555  }
556  }
557  {
558  const edge& e1 = edgesB[twoEdges[1]];
559  const edge meshEdge1(meshPtsB, e1);
560 
561  const auto iter = edgeValues.cfind(meshEdge1);
562 
563  if (iter.good())
564  {
565  half1Values.insert(edgei, iter.val());
566  }
567  }
568  }
569 
570  // Transform to this side
571  top(cycPatch, half1Values);
572  top(nbrPatch, half0Values);
573 
574 
575  // Extract and combine information
576 
577  forAll(coupledEdges, edgei)
578  {
579  const edge& twoEdges = coupledEdges[edgei];
580 
581  const auto half1Fnd = half1Values.cfind(edgei);
582 
583  if (half1Fnd.good())
584  {
585  const edge& e0 = edgesA[twoEdges[0]];
586  const edge meshEdge0(meshPtsA, e0);
587 
588  combine
589  (
590  edgeValues,
591  cop,
592  meshEdge0, // edge
593  *half1Fnd // value
594  );
595  }
596 
597  const auto half0Fnd = half0Values.cfind(edgei);
598 
599  if (half0Fnd.good())
600  {
601  const edge& e1 = edgesB[twoEdges[1]];
602  const edge meshEdge1(meshPtsB, e1);
603 
604  combine
605  (
606  edgeValues,
607  cop,
608  meshEdge1, // edge
609  *half0Fnd // value
610  );
611  }
612  }
613  }
614  }
615 
616  // Synchronize multiple shared points.
617  // Problem is that we don't want to construct shared edges so basically
618  // we do here like globalMeshData but then using sparse edge representation
619  // (EdgeMap instead of mesh.edges())
620 
621  const globalMeshData& pd = mesh.globalData();
622  const labelList& sharedPtAddr = pd.sharedPointAddr();
623  const labelList& sharedPtLabels = pd.sharedPointLabels();
624 
625  // 1. Create map from meshPoint to globalShared index.
626  Map<label> meshToShared(sharedPtLabels, sharedPtAddr);
627 
628  // Values on shared points. From two sharedPtAddr indices to a value.
629  EdgeMap<T> sharedEdgeValues(meshToShared.size());
630 
631  // From shared edge to mesh edge. Used for merging later on.
632  EdgeMap<edge> potentialSharedEdge(meshToShared.size());
633 
634  // 2. Find any edges using two global shared points. These will always be
635  // on the outside of the mesh. (though might not be on coupled patch
636  // if is single edge and not on coupled face)
637  // Store value (if any) on sharedEdgeValues
638  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
639  {
640  const face& f = mesh.faces()[facei];
641 
642  forAll(f, fp)
643  {
644  const label v0 = f[fp];
645  const label v1 = f[f.fcIndex(fp)];
646 
647  const auto v0Fnd = meshToShared.cfind(v0);
648 
649  if (v0Fnd.good())
650  {
651  const auto v1Fnd = meshToShared.cfind(v1);
652 
653  if (v1Fnd.good())
654  {
655  const edge meshEdge(v0, v1);
656 
657  // edge in shared point labels
658  const edge sharedEdge(*v0Fnd, *v1Fnd);
659 
660  // Store mesh edge as a potential shared edge.
661  potentialSharedEdge.insert(sharedEdge, meshEdge);
662 
663  const auto edgeFnd = edgeValues.cfind(meshEdge);
664 
665  if (edgeFnd.good())
666  {
667  // edge exists in edgeValues. See if already in map
668  // (since on same processor, e.g. cyclic)
669  combine
670  (
671  sharedEdgeValues,
672  cop,
673  sharedEdge, // edge
674  *edgeFnd // value
675  );
676  }
677  }
678  }
679  }
680  }
681 
682 
683  // Now sharedEdgeValues will contain per potential sharedEdge the value.
684  // (potential since an edge having two shared points is not necessary a
685  // shared edge).
686  // Reduce this on the master.
687 
688  if (UPstream::parRun())
689  {
690  if (UPstream::master())
691  {
692  // Receive the edges using shared points from other procs
693  for (const int proci : UPstream::subProcs())
694  {
695  EdgeMap<T> nbrValues;
696  IPstream::recv(nbrValues, proci);
697 
698  // Merge neighbouring values with my values
699  forAllConstIters(nbrValues, iter)
700  {
701  combine
702  (
703  sharedEdgeValues,
704  cop,
705  iter.key(), // edge
706  iter.val() // value
707  );
708  }
709  }
710  }
711  else
712  {
713  // Send to master
714  OPstream::send(sharedEdgeValues, UPstream::masterNo());
715  }
716 
717  // Broadcast: send merged values to all
718  Pstream::broadcast(sharedEdgeValues);
719  }
720 
721 
722  // Merge sharedEdgeValues (keyed on sharedPointAddr) into edgeValues
723  // (keyed on mesh points).
724 
725  // Loop over all my shared edges.
726  forAllConstIters(potentialSharedEdge, iter)
727  {
728  const edge& sharedEdge = iter.key();
729  const edge& meshEdge = iter.val();
730 
731  // Do I have a value for the shared edge?
732  const auto sharedFnd = sharedEdgeValues.cfind(sharedEdge);
733 
734  if (sharedFnd.good())
735  {
736  combine
737  (
738  edgeValues,
739  cop,
740  meshEdge, // edge
741  *sharedFnd // value
742  );
743  }
744  }
745 
746  // Reset tag
747  UPstream::msgType(oldTag);
748 }
749 
750 
751 template<class T, class CombineOp, class TransformOp>
753 (
754  const polyMesh& mesh,
755  List<T>& pointValues,
756  const CombineOp& cop,
757  const T& nullValue,
758  const TransformOp& top
759 )
760 {
761  if (pointValues.size() != mesh.nPoints())
762  {
764  << "Number of values " << pointValues.size()
765  << " != number of points " << mesh.nPoints() << nl
766  << abort(FatalError);
767  }
769  mesh.globalData().syncPointData(pointValues, cop, top);
770 }
771 
772 
773 template<class T, class CombineOp, class TransformOp>
775 (
776  const polyMesh& mesh,
777  const labelUList& meshPoints,
778  List<T>& pointValues,
779  const CombineOp& cop,
780  const T& nullValue,
781  const TransformOp& top
782 )
783 {
784  if (pointValues.size() != meshPoints.size())
785  {
787  << "Number of values " << pointValues.size()
788  << " != number of meshPoints " << meshPoints.size() << nl
789  << abort(FatalError);
790  }
791  const globalMeshData& gd = mesh.globalData();
792  const indirectPrimitivePatch& cpp = gd.coupledPatch();
793  const Map<label>& mpm = cpp.meshPointMap();
794 
795  List<T> cppFld(cpp.nPoints(), nullValue);
796 
797  forAll(meshPoints, i)
798  {
799  const auto iter = mpm.cfind(meshPoints[i]);
800 
801  if (iter.good())
802  {
803  cppFld[iter.val()] = pointValues[i];
804  }
805  }
806 
808  (
809  cppFld,
810  gd.globalPointSlaves(),
811  gd.globalPointTransformedSlaves(),
812  gd.globalPointSlavesMap(),
813  gd.globalTransforms(),
814  cop,
815  top
816  );
817 
818  forAll(meshPoints, i)
819  {
820  const auto iter = mpm.cfind(meshPoints[i]);
821 
822  if (iter.good())
823  {
824  pointValues[i] = cppFld[iter.val()];
825  }
826  }
827 }
828 
829 
830 template<class T, class CombineOp, class TransformOp, class FlipOp>
832 (
833  const polyMesh& mesh,
834  List<T>& edgeValues,
835  const CombineOp& cop,
836  const T& nullValue,
837  const TransformOp& top,
838  const FlipOp& fop
839 )
840 {
841  if (edgeValues.size() != mesh.nEdges())
842  {
844  << "Number of values " << edgeValues.size()
845  << " != number of edges " << mesh.nEdges() << nl
846  << abort(FatalError);
847  }
848 
849  const edgeList& edges = mesh.edges();
850  const globalMeshData& gd = mesh.globalData();
851  const labelList& meshEdges = gd.coupledPatchMeshEdges();
852  const indirectPrimitivePatch& cpp = gd.coupledPatch();
853  const edgeList& cppEdges = cpp.edges();
854  const labelList& mp = cpp.meshPoints();
855  const globalIndexAndTransform& git = gd.globalTransforms();
856  const mapDistribute& edgeMap = gd.globalEdgeSlavesMap();
857  const bitSet& orientation = gd.globalEdgeOrientation();
858 
859  List<T> cppFld(meshEdges.size());
860  forAll(meshEdges, i)
861  {
862  const edge& cppE = cppEdges[i];
863  const label meshEdgei = meshEdges[i];
864  const edge& meshE = edges[meshEdgei];
865 
866  // 1. is cpp edge oriented as mesh edge
867  // 2. is cpp edge oriented same as master edge
868 
869  const int dir = edge::compare(meshE, edge(mp, cppE));
870  if (dir == 0)
871  {
872  FatalErrorInFunction<< "Problem:"
873  << " mesh edge:" << meshE.line(mesh.points())
874  << " coupled edge:" << cppE.line(cpp.localPoints())
875  << exit(FatalError);
876  }
877 
878  const bool sameOrientation = ((dir == 1) == orientation[i]);
879 
880  if (sameOrientation)
881  {
882  cppFld[i] = edgeValues[meshEdgei];
883  }
884  else
885  {
886  cppFld[i] = fop(edgeValues[meshEdgei]);
887  }
888  }
889 
890 
892  (
893  cppFld,
894  gd.globalEdgeSlaves(),
895  gd.globalEdgeTransformedSlaves(),
896  edgeMap,
897  git,
898  cop,
899  top
900  );
901 
902  // Extract back onto mesh
903  forAll(meshEdges, i)
904  {
905  const edge& cppE = cppEdges[i];
906  const label meshEdgei = meshEdges[i];
907  const edge& meshE = edges[meshEdgei];
908 
909  // 1. is cpp edge oriented as mesh edge
910  // 2. is cpp edge oriented same as master edge
911 
912  const int dir = edge::compare(meshE, edge(mp, cppE));
913  const bool sameOrientation = ((dir == 1) == orientation[i]);
914 
915  if (sameOrientation)
916  {
917  edgeValues[meshEdges[i]] = cppFld[i];
918  }
919  else
920  {
921  edgeValues[meshEdges[i]] = fop(cppFld[i]);
922  }
923  }
924 }
925 
926 
927 template<class T, class CombineOp, class TransformOp, class FlipOp>
929 (
930  const polyMesh& mesh,
931  const labelUList& meshEdges,
932  List<T>& edgeValues,
933  const CombineOp& cop,
934  const T& nullValue,
935  const TransformOp& top,
936  const FlipOp& fop
937 )
938 {
939  if (edgeValues.size() != meshEdges.size())
940  {
942  << "Number of values " << edgeValues.size()
943  << " != number of meshEdges " << meshEdges.size() << nl
944  << abort(FatalError);
945  }
946  const edgeList& edges = mesh.edges();
947  const globalMeshData& gd = mesh.globalData();
948  const indirectPrimitivePatch& cpp = gd.coupledPatch();
949  const edgeList& cppEdges = cpp.edges();
950  const labelList& mp = cpp.meshPoints();
951  const Map<label>& mpm = gd.coupledPatchMeshEdgeMap();
952  const bitSet& orientation = gd.globalEdgeOrientation();
953 
954  List<T> cppFld(cpp.nEdges(), nullValue);
955 
956  forAll(meshEdges, i)
957  {
958  const label meshEdgei = meshEdges[i];
959  const auto iter = mpm.cfind(meshEdgei);
960  if (iter.good())
961  {
962  const label cppEdgei = iter.val();
963  const edge& cppE = cppEdges[cppEdgei];
964  const edge& meshE = edges[meshEdgei];
965 
966  // 1. is cpp edge oriented as mesh edge
967  // 2. is cpp edge oriented same as master edge
968 
969  const int dir = edge::compare(meshE, edge(mp, cppE));
970  if (dir == 0)
971  {
972  FatalErrorInFunction<< "Problem:"
973  << " mesh edge:" << meshE.line(mesh.points())
974  << " coupled edge:" << cppE.line(cpp.localPoints())
975  << exit(FatalError);
976  }
977 
978  const bool sameOrientation = ((dir == 1) == orientation[i]);
979 
980  if (sameOrientation)
981  {
982  cppFld[cppEdgei] = edgeValues[i];
983  }
984  else
985  {
986  cppFld[cppEdgei] = fop(edgeValues[i]);
987  }
988  }
989  }
990 
992  (
993  cppFld,
994  gd.globalEdgeSlaves(),
995  gd.globalEdgeTransformedSlaves(),
996  gd.globalEdgeSlavesMap(),
997  gd.globalTransforms(),
998  cop,
999  top
1000  );
1001 
1002  forAll(meshEdges, i)
1003  {
1004  label meshEdgei = meshEdges[i];
1005  const auto iter = mpm.cfind(meshEdgei);
1006  if (iter.good())
1007  {
1008  label cppEdgei = iter.val();
1009  const edge& cppE = cppEdges[cppEdgei];
1010  const edge& meshE = edges[meshEdgei];
1011 
1012  const int dir = edge::compare(meshE, edge(mp, cppE));
1013  const bool sameOrientation = ((dir == 1) == orientation[i]);
1014 
1015  if (sameOrientation)
1016  {
1017  edgeValues[i] = cppFld[cppEdgei];
1018  }
1019  else
1020  {
1021  edgeValues[i] = fop(cppFld[cppEdgei]);
1022  }
1023  }
1024  }
1025 }
1026 
1027 
1028 template<class T, class CombineOp, class TransformOp>
1030 (
1031  const polyMesh& mesh,
1032  UList<T>& faceValues,
1033  const CombineOp& cop,
1034  const TransformOp& top,
1035  const bool parRun
1036 )
1037 {
1038  // Offset (global to local) for start of boundaries
1039  const label boundaryOffset = mesh.nInternalFaces();
1040 
1041  if (faceValues.size() != mesh.nBoundaryFaces())
1042  {
1044  << "Number of values " << faceValues.size()
1045  << " != number of boundary faces " << mesh.nBoundaryFaces() << nl
1046  << abort(FatalError);
1047  }
1048 
1049  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1050 
1051  // Allocate unique tag for all comms
1052  const int oldTag = UPstream::incrMsgType();
1053 
1054  if (parRun && UPstream::parRun())
1055  {
1056  // Avoid mesh.globalData() - possible race condition
1057 
1058  if
1059  (
1060  is_contiguous<T>::value
1062  )
1063  {
1064  const label startRequest = UPstream::nRequests();
1065 
1066  // Receive buffer
1067  List<T> receivedValues(mesh.nBoundaryFaces());
1068 
1069  // Set up reads
1070  for (const polyPatch& pp : patches)
1071  {
1072  const auto* ppp = isA<processorPolyPatch>(pp);
1073 
1074  if (ppp && pp.size())
1075  {
1076  const auto& procPatch = *ppp;
1077 
1078  SubList<T> fld
1079  (
1080  receivedValues,
1081  pp.size(),
1082  pp.start()-boundaryOffset
1083  );
1084 
1086  (
1088  procPatch.neighbProcNo(),
1089  fld.data_bytes(),
1090  fld.size_bytes()
1091  );
1092  }
1093  }
1094 
1095  // Set up writes
1096  for (const polyPatch& pp : patches)
1097  {
1098  const auto* ppp = isA<processorPolyPatch>(pp);
1099 
1100  if (ppp && pp.size())
1101  {
1102  const auto& procPatch = *ppp;
1103 
1104  const SubList<T> fld
1105  (
1106  faceValues,
1107  pp.size(),
1108  pp.start()-boundaryOffset
1109  );
1110 
1112  (
1114  procPatch.neighbProcNo(),
1115  fld.cdata_bytes(),
1116  fld.size_bytes()
1117  );
1118  }
1119  }
1120 
1121  // Wait for all comms to finish
1122  UPstream::waitRequests(startRequest);
1123 
1124  // Combine with existing data
1125  for (const polyPatch& pp : patches)
1126  {
1127  const auto* ppp = isA<processorPolyPatch>(pp);
1128 
1129  if (ppp && pp.size())
1130  {
1131  const auto& procPatch = *ppp;
1132 
1133  SubList<T> recvFld
1134  (
1135  receivedValues,
1136  pp.size(),
1137  pp.start()-boundaryOffset
1138  );
1139  const List<T>& fakeList = recvFld;
1140  top(procPatch, const_cast<List<T>&>(fakeList));
1141 
1142  SubList<T> patchValues
1143  (
1144  faceValues,
1145  pp.size(),
1146  pp.start()-boundaryOffset
1147  );
1148 
1149  forAll(patchValues, i)
1150  {
1151  cop(patchValues[i], recvFld[i]);
1152  }
1153  }
1154  }
1155  }
1156  else
1157  {
1158  DynamicList<label> neighbProcs;
1159  PstreamBuffers pBufs;
1160 
1161  // Send
1162  for (const polyPatch& pp : patches)
1163  {
1164  const auto* ppp = isA<processorPolyPatch>(pp);
1165 
1166  if (ppp && pp.size())
1167  {
1168  const auto& procPatch = *ppp;
1169  const label nbrProci = procPatch.neighbProcNo();
1170 
1171  // Neighbour connectivity
1172  neighbProcs.push_uniq(nbrProci);
1173 
1174  const SubList<T> fld
1175  (
1176  faceValues,
1177  pp.size(),
1178  pp.start()-boundaryOffset
1179  );
1180 
1181  UOPstream toNbr(nbrProci, pBufs);
1182  toNbr << fld;
1183  }
1184  }
1185 
1186  // Limit exchange to involved procs
1187  pBufs.finishedNeighbourSends(neighbProcs);
1188 
1189 
1190  // Receive and combine.
1191  for (const polyPatch& pp : patches)
1192  {
1193  const auto* ppp = isA<processorPolyPatch>(pp);
1194 
1195  if (ppp && pp.size())
1196  {
1197  const auto& procPatch = *ppp;
1198  const label nbrProci = procPatch.neighbProcNo();
1199 
1200  List<T> recvFld;
1201  {
1202  UIPstream fromNbr(nbrProci, pBufs);
1203  fromNbr >> recvFld;
1204  }
1205 
1206  top(procPatch, recvFld);
1207 
1208  SubList<T> patchValues
1209  (
1210  faceValues,
1211  pp.size(),
1212  pp.start()-boundaryOffset
1213  );
1214 
1215  forAll(patchValues, i)
1216  {
1217  cop(patchValues[i], recvFld[i]);
1218  }
1219  }
1220  }
1221  }
1222  }
1223 
1224  // Do the cyclics.
1225  for (const polyPatch& pp : patches)
1226  {
1227  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
1228 
1229  if (cpp && cpp->owner())
1230  {
1231  // Owner does all.
1232 
1233  const cyclicPolyPatch& cycPatch = *cpp;
1234  const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
1235  const label patchSize = cycPatch.size();
1236 
1237  SubList<T> ownPatchValues
1238  (
1239  faceValues,
1240  patchSize,
1241  cycPatch.start()-boundaryOffset
1242  );
1243 
1244  SubList<T> nbrPatchValues
1245  (
1246  faceValues,
1247  patchSize,
1248  nbrPatch.start()-boundaryOffset
1249  );
1250 
1251  // Transform (copy of) data on both sides
1252  List<T> ownVals(ownPatchValues);
1253  top(nbrPatch, ownVals);
1254 
1255  List<T> nbrVals(nbrPatchValues);
1256  top(cycPatch, nbrVals);
1257 
1258  forAll(ownPatchValues, i)
1259  {
1260  cop(ownPatchValues[i], nbrVals[i]);
1261  }
1262 
1263  forAll(nbrPatchValues, i)
1264  {
1265  cop(nbrPatchValues[i], ownVals[i]);
1266  }
1267  }
1268  }
1269 
1270  // Reset tag
1271  UPstream::msgType(oldTag);
1273 
1274 
1275 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1276 
1277 template<unsigned Width, class CombineOp>
1279 (
1280  const polyMesh& mesh,
1281  const bool isBoundaryOnly,
1282  PackedList<Width>& faceValues,
1283  const CombineOp& cop,
1284  const bool parRun
1285 )
1286 {
1287  // Offset (global to local) for start of boundaries
1288  const label boundaryOffset = (isBoundaryOnly ? mesh.nInternalFaces() : 0);
1289 
1290  // Check size
1291  if (faceValues.size() != (mesh.nFaces() - boundaryOffset))
1292  {
1294  << "Number of values " << faceValues.size()
1295  << " != number of "
1296  << (isBoundaryOnly ? "boundary" : "mesh") << " faces "
1297  << (mesh.nFaces() - boundaryOffset) << nl
1298  << abort(FatalError);
1299  }
1300 
1301  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1302 
1303  // Allocate unique tag for all comms
1304  const int oldTag = UPstream::incrMsgType();
1305 
1306  if (parRun && UPstream::parRun())
1307  {
1308  const label startRequest = UPstream::nRequests();
1309 
1310  // Receive buffers
1311  PtrList<PackedList<Width>> recvBufs(patches.size());
1312 
1313  // Set up reads
1314  for (const polyPatch& pp : patches)
1315  {
1316  const auto* ppp = isA<processorPolyPatch>(pp);
1317 
1318  if (ppp && pp.size())
1319  {
1320  const auto& procPatch = *ppp;
1321  const label patchi = pp.index();
1322 
1323  auto& recvbuf = recvBufs.emplace_set(patchi, pp.size());
1324 
1326  (
1328  procPatch.neighbProcNo(),
1329  recvbuf.data_bytes(),
1330  recvbuf.size_bytes()
1331  );
1332  }
1333  }
1334 
1335  // Send buffers
1336  PtrList<PackedList<Width>> sendBufs(patches.size());
1337 
1338  // Set up writes
1339  for (const polyPatch& pp : patches)
1340  {
1341  const auto* ppp = isA<processorPolyPatch>(pp);
1342 
1343  if (ppp && pp.size())
1344  {
1345  const auto& procPatch = *ppp;
1346  const label patchi = pp.index();
1347 
1348  const labelRange range(pp.start()-boundaryOffset, pp.size());
1349 
1350  auto& sendbuf = sendBufs.emplace_set(patchi, faceValues, range);
1351 
1353  (
1355  procPatch.neighbProcNo(),
1356  sendbuf.cdata_bytes(),
1357  sendbuf.size_bytes()
1358  );
1359  }
1360  }
1361 
1362  // Wait for all comms to finish
1363  UPstream::waitRequests(startRequest);
1364 
1365  // Combine with existing data
1366  for (const polyPatch& pp : patches)
1367  {
1368  const auto* ppp = isA<processorPolyPatch>(pp);
1369 
1370  if (ppp && pp.size())
1371  {
1372  const label patchi = pp.index();
1373  const label patchSize = pp.size();
1374 
1375  const auto& recvbuf = recvBufs[patchi];
1376 
1377  // Combine (bitwise)
1378  label bFacei = pp.start()-boundaryOffset;
1379  for (label i = 0; i < patchSize; ++i)
1380  {
1381  unsigned int recvVal = recvbuf[i];
1382  unsigned int faceVal = faceValues[bFacei];
1383 
1384  cop(faceVal, recvVal);
1385  faceValues.set(bFacei, faceVal);
1386 
1387  ++bFacei;
1388  }
1389  }
1390  }
1391  }
1392 
1393 
1394  // Do the cyclics.
1395  for (const polyPatch& pp : patches)
1396  {
1397  const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
1398 
1399  if (cpp && cpp->owner())
1400  {
1401  // Owner does all.
1402 
1403  const cyclicPolyPatch& cycPatch = *cpp;
1404  const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
1405  const label patchSize = cycPatch.size();
1406 
1407  label face0 = cycPatch.start()-boundaryOffset;
1408  label face1 = nbrPatch.start()-boundaryOffset;
1409  for (label i = 0; i < patchSize; ++i)
1410  {
1411  unsigned int val0 = faceValues[face0];
1412  unsigned int val1 = faceValues[face1];
1413 
1414  unsigned int t = val0;
1415  cop(t, val1);
1416  faceValues[face0] = t;
1417 
1418  cop(val1, val0);
1419  faceValues[face1] = val1;
1420 
1421  ++face0;
1422  ++face1;
1423  }
1424  }
1425  }
1426 
1427  // Reset tag
1428  UPstream::msgType(oldTag);
1429 }
1430 
1431 
1432 template<class T>
1434 (
1435  const polyMesh& mesh,
1436  const UList<T>& cellData,
1437  List<T>& neighbourCellData,
1438  const bool parRun
1439 )
1440 {
1441  if (cellData.size() != mesh.nCells())
1442  {
1444  << "Number of cell values " << cellData.size()
1445  << " != number of cells " << mesh.nCells() << nl
1446  << abort(FatalError);
1447  }
1448 
1449  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1450 
1451  neighbourCellData.resize(mesh.nBoundaryFaces());
1452 
1453  for (const polyPatch& pp : patches)
1454  {
1455  const auto& faceCells = pp.faceCells();
1456 
1457  // ie, boundarySlice() = patchInternalList()
1458  SubList<T>
1459  (
1460  neighbourCellData,
1461  faceCells.size(),
1462  pp.offset()
1463  ) = UIndirectList<T>(cellData, faceCells);
1464  }
1466  syncTools::swapBoundaryFaceList(mesh, neighbourCellData, parRun);
1467 }
1468 
1469 
1470 template<unsigned Width, class CombineOp>
1472 (
1473  const polyMesh& mesh,
1474  PackedList<Width>& faceValues,
1475  const CombineOp& cop,
1476  const bool parRun
1477 )
1479  syncFaceList(mesh, false, faceValues, cop, parRun);
1480 }
1481 
1482 
1483 template<unsigned Width, class CombineOp>
1485 (
1486  const polyMesh& mesh,
1487  PackedList<Width>& faceValues,
1488  const CombineOp& cop,
1489  const bool parRun
1490 )
1492  syncFaceList(mesh, true, faceValues, cop, parRun);
1493 }
1494 
1495 
1496 template<unsigned Width>
1498 (
1499  const polyMesh& mesh,
1500  PackedList<Width>& faceValues,
1501  const bool parRun
1502 )
1503 {
1504  syncFaceList
1505  (
1506  mesh,
1507  faceValues,
1509  parRun
1510  );
1511 }
1512 
1513 
1514 template<unsigned Width>
1516 (
1517  const polyMesh& mesh,
1518  PackedList<Width>& faceValues,
1519  const bool parRun
1520 )
1521 {
1522  syncBoundaryFaceList
1523  (
1524  mesh,
1525  faceValues,
1527  parRun
1528  );
1529 }
1530 
1531 
1532 template<unsigned Width, class CombineOp>
1534 (
1535  const polyMesh& mesh,
1536  PackedList<Width>& pointValues,
1537  const CombineOp& cop,
1538  const unsigned int nullValue
1539 )
1540 {
1541  if (pointValues.size() != mesh.nPoints())
1542  {
1544  << "Number of values " << pointValues.size()
1545  << " != number of points " << mesh.nPoints() << nl
1546  << abort(FatalError);
1547  }
1548 
1549  const globalMeshData& gd = mesh.globalData();
1550  const labelList& meshPoints = gd.coupledPatch().meshPoints();
1551 
1552  List<unsigned int> cppFld(gd.globalPointSlavesMap().constructSize());
1553  forAll(meshPoints, i)
1554  {
1555  cppFld[i] = pointValues[meshPoints[i]];
1556  }
1557 
1559  (
1560  cppFld,
1561  gd.globalPointSlaves(),
1562  gd.globalPointTransformedSlaves(),
1563  gd.globalPointSlavesMap(),
1564  cop
1565  );
1566 
1567  // Extract back to mesh
1568  forAll(meshPoints, i)
1569  {
1570  pointValues[meshPoints[i]] = cppFld[i];
1571  }
1572 }
1573 
1574 
1575 template<unsigned Width, class CombineOp>
1577 (
1578  const polyMesh& mesh,
1579  PackedList<Width>& edgeValues,
1580  const CombineOp& cop,
1581  const unsigned int nullValue
1582 )
1583 {
1584  if (edgeValues.size() != mesh.nEdges())
1585  {
1587  << "Number of values " << edgeValues.size()
1588  << " != number of edges " << mesh.nEdges() << nl
1589  << abort(FatalError);
1590  }
1591 
1592  const globalMeshData& gd = mesh.globalData();
1593  const labelList& meshEdges = gd.coupledPatchMeshEdges();
1594 
1595  List<unsigned int> cppFld(gd.globalEdgeSlavesMap().constructSize());
1596  forAll(meshEdges, i)
1597  {
1598  cppFld[i] = edgeValues[meshEdges[i]];
1599  }
1600 
1602  (
1603  cppFld,
1604  gd.globalEdgeSlaves(),
1605  gd.globalEdgeTransformedSlaves(),
1606  gd.globalEdgeSlavesMap(),
1607  cop
1608  );
1609 
1610  // Extract back to mesh
1611  forAll(meshEdges, i)
1612  {
1613  edgeValues[meshEdges[i]] = cppFld[i];
1614  }
1615 }
1616 
1617 
1618 // ************************************************************************* //
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:567
label nPoints() const
Number of points supporting patch faces.
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const bool parRun=UPstream::parRun())
Synchronize values on all mesh faces.
Definition: syncTools.H:465
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
Definition: ops.H:67
static void syncBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const TransformOp &top, const bool parRun=UPstream::parRun())
Synchronize values on boundary faces only.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
static int incrMsgType(int val=1) noexcept
Increment the message tag for standard messages.
Definition: UPstream.H:1274
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
label nPoints() const noexcept
Number of mesh points.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData, const bool parRun=UPstream::parRun())
Extract and swap to obtain neighbour cell values for all boundary faces.
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:524
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1252
label nFaces() const noexcept
Number of mesh faces.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field...
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1561
scalar range
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
label nProcessorPatches() const
The number of processorPolyPatch patches.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static void syncData(List< Type > &elems, const labelListList &slaves, const labelListList &transformedSlaves, const mapDistribute &slavesMap, const globalIndexAndTransform &, const CombineOp &cop, const TransformOp &top)
Helper: synchronise data with transforms.
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
Definition: UListI.H:90
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:62
label nGlobalPoints() const
Return number of globally shared points.
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
Definition: IPstream.H:81
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:105
const_iterator cfind(const label &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:113
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Definition: edge.H:59
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1071
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1311
label nInternalFaces() const noexcept
Number of internal faces.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
bool set(const label i, unsigned int val=~0u)
Set value at index i, default value set is the max_value.
Definition: PackedListI.H:706
errorManip< error > abort(error &err)
Definition: errorManip.H:139
label nEdges() const
Number of mesh edges.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
label nEdges() const
Number of edges in patch.
Map from edge (expressed as its endpoints) to value. Hashing (and ==) on an edge is symmetric...
Definition: edgeHashes.H:56
labelList f(nPoints)
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const volScalarField & T
Spatial transformation functions for list of values and primitive fields.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
label push_uniq(const T &val)
Append an element if not already in the list.
Definition: DynamicListI.H:686
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:397
label nCells() const noexcept
Number of mesh cells.
void reserve(label numEntries)
Reserve space for at least the specified number of elements (not the number of buckets) and regenerat...
Definition: HashTable.C:736
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
const polyBoundaryMesh & patches
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents to given processor.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top, const FlipOp &fop)
Synchronize values on all mesh edges.
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1197
List< label > labelList
A List of labels.
Definition: List.H:62
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points list.
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Definition: OPstreams.C:84
static void syncEdgeMap(const polyMesh &mesh, EdgeMap< T > &edgeValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected edges.
label size() const noexcept
Number of entries.
Definition: PackedList.H:393
static void syncPointMap(const polyMesh &mesh, Map< T > &pointValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected points.
const dimensionedScalar mp
Proton mass.
bool set(const label &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
Definition: HashTableI.H:174
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
static std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
A HashTable to objects of type <T> with a label key.
static int compare(const edge &a, const edge &b)
Compare edges.
Definition: edgeI.H:26
void syncPointData(List< Type > &pointData, const CombineOp &cop, const TransformOp &top) const
Helper to synchronise coupled patch point data.