mapDistributeTemplates.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 | Copyright (C) 2011-2012 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "Pstream.H"
27 #include "PstreamBuffers.H"
30 #include "transformField.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 // Distribute list.
35 template<class T>
37 (
38  const Pstream::commsTypes commsType,
39  const List<labelPair>& schedule,
40  const label constructSize,
41  const labelListList& subMap,
42  const labelListList& constructMap,
43  List<T>& field,
44  const int tag
45 )
46 {
47  if (!Pstream::parRun())
48  {
49  // Do only me to me.
50 
51  const labelList& mySubMap = subMap[Pstream::myProcNo()];
52 
53  List<T> subField(mySubMap.size());
54  forAll(mySubMap, i)
55  {
56  subField[i] = field[mySubMap[i]];
57  }
58 
59  // Receive sub field from myself (subField)
60  const labelList& map = constructMap[Pstream::myProcNo()];
61 
62  field.setSize(constructSize);
63 
64  forAll(map, i)
65  {
66  field[map[i]] = subField[i];
67  }
68  return;
69  }
70 
71  if (commsType == Pstream::blocking)
72  {
73  // Since buffered sending can reuse the field to collect the
74  // received data.
75 
76  // Send sub field to neighbour
77  for (label domain = 0; domain < Pstream::nProcs(); domain++)
78  {
79  const labelList& map = subMap[domain];
80 
81  if (domain != Pstream::myProcNo() && map.size())
82  {
83  OPstream toNbr(Pstream::blocking, domain, 0, tag);
84  toNbr << UIndirectList<T>(field, map);
85  }
86  }
87 
88  // Subset myself
89  const labelList& mySubMap = subMap[Pstream::myProcNo()];
90 
91  List<T> subField(mySubMap.size());
92  forAll(mySubMap, i)
93  {
94  subField[i] = field[mySubMap[i]];
95  }
96 
97  // Receive sub field from myself (subField)
98  const labelList& map = constructMap[Pstream::myProcNo()];
99 
100  field.setSize(constructSize);
101 
102  forAll(map, i)
103  {
104  field[map[i]] = subField[i];
105  }
106 
107  // Receive sub field from neighbour
108  for (label domain = 0; domain < Pstream::nProcs(); domain++)
109  {
110  const labelList& map = constructMap[domain];
111 
112  if (domain != Pstream::myProcNo() && map.size())
113  {
114  IPstream fromNbr(Pstream::blocking, domain, 0, tag);
115  List<T> subField(fromNbr);
116 
117  checkReceivedSize(domain, map.size(), subField.size());
118 
119  forAll(map, i)
120  {
121  field[map[i]] = subField[i];
122  }
123  }
124  }
125  }
126  else if (commsType == Pstream::scheduled)
127  {
128  // Need to make sure I don't overwrite field with received data
129  // since the data might need to be sent to another processor. So
130  // allocate a new field for the results.
131  List<T> newField(constructSize);
132 
133  // Subset myself
134  UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
135 
136  // Receive sub field from myself (subField)
137  const labelList& map = constructMap[Pstream::myProcNo()];
138 
139  forAll(map, i)
140  {
141  newField[map[i]] = subField[i];
142  }
143 
144  // Schedule will already have pruned 0-sized comms
145  forAll(schedule, i)
146  {
147  const labelPair& twoProcs = schedule[i];
148  // twoProcs is a swap pair of processors. The first one is the
149  // one that needs to send first and then receive.
150 
151  label sendProc = twoProcs[0];
152  label recvProc = twoProcs[1];
153 
154  if (Pstream::myProcNo() == sendProc)
155  {
156  // I am send first, receive next
157  {
158  OPstream toNbr(Pstream::scheduled, recvProc, 0, tag);
159  toNbr << UIndirectList<T>(field, subMap[recvProc]);
160  }
161  {
162  IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag);
163  List<T> subField(fromNbr);
164 
165  const labelList& map = constructMap[recvProc];
166 
167  checkReceivedSize(recvProc, map.size(), subField.size());
168 
169  forAll(map, i)
170  {
171  newField[map[i]] = subField[i];
172  }
173  }
174  }
175  else
176  {
177  // I am receive first, send next
178  {
179  IPstream fromNbr(Pstream::scheduled, sendProc, 0, tag);
180  List<T> subField(fromNbr);
181 
182  const labelList& map = constructMap[sendProc];
183 
184  checkReceivedSize(sendProc, map.size(), subField.size());
185 
186  forAll(map, i)
187  {
188  newField[map[i]] = subField[i];
189  }
190  }
191  {
192  OPstream toNbr(Pstream::scheduled, sendProc, 0, tag);
193  toNbr << UIndirectList<T>(field, subMap[sendProc]);
194  }
195  }
196  }
197  field.transfer(newField);
198  }
199  else if (commsType == Pstream::nonBlocking)
200  {
201  label nOutstanding = Pstream::nRequests();
202 
203  if (!contiguous<T>())
204  {
205  PstreamBuffers pBufs(Pstream::nonBlocking, tag);
206 
207  // Stream data into buffer
208  for (label domain = 0; domain < Pstream::nProcs(); domain++)
209  {
210  const labelList& map = subMap[domain];
211 
212  if (domain != Pstream::myProcNo() && map.size())
213  {
214  // Put data into send buffer
215  UOPstream toDomain(domain, pBufs);
216  toDomain << UIndirectList<T>(field, map);
217  }
218  }
219 
220  // Start receiving. Do not block.
221  pBufs.finishedSends(false);
222 
223  {
224  // Set up 'send' to myself
225  const labelList& mySubMap = subMap[Pstream::myProcNo()];
226  List<T> mySubField(mySubMap.size());
227  forAll(mySubMap, i)
228  {
229  mySubField[i] = field[mySubMap[i]];
230  }
231  // Combine bits. Note that can reuse field storage
232  field.setSize(constructSize);
233  // Receive sub field from myself
234  {
235  const labelList& map = constructMap[Pstream::myProcNo()];
236 
237  forAll(map, i)
238  {
239  field[map[i]] = mySubField[i];
240  }
241  }
242  }
243 
244  // Block ourselves, waiting only for the current comms
245  Pstream::waitRequests(nOutstanding);
246 
247  // Consume
248  for (label domain = 0; domain < Pstream::nProcs(); domain++)
249  {
250  const labelList& map = constructMap[domain];
251 
252  if (domain != Pstream::myProcNo() && map.size())
253  {
254  UIPstream str(domain, pBufs);
255  List<T> recvField(str);
256 
257  checkReceivedSize(domain, map.size(), recvField.size());
258 
259  forAll(map, i)
260  {
261  field[map[i]] = recvField[i];
262  }
263  }
264  }
265  }
266  else
267  {
268  // Set up sends to neighbours
269 
270  List<List<T > > sendFields(Pstream::nProcs());
271 
272  for (label domain = 0; domain < Pstream::nProcs(); domain++)
273  {
274  const labelList& map = subMap[domain];
275 
276  if (domain != Pstream::myProcNo() && map.size())
277  {
278  List<T>& subField = sendFields[domain];
279  subField.setSize(map.size());
280  forAll(map, i)
281  {
282  subField[i] = field[map[i]];
283  }
284 
286  (
287  Pstream::nonBlocking,
288  domain,
289  reinterpret_cast<const char*>(subField.begin()),
290  subField.byteSize(),
291  tag
292  );
293  }
294  }
295 
296  // Set up receives from neighbours
297 
298  List<List<T > > recvFields(Pstream::nProcs());
299 
300  for (label domain = 0; domain < Pstream::nProcs(); domain++)
301  {
302  const labelList& map = constructMap[domain];
303 
304  if (domain != Pstream::myProcNo() && map.size())
305  {
306  recvFields[domain].setSize(map.size());
308  (
309  Pstream::nonBlocking,
310  domain,
311  reinterpret_cast<char*>(recvFields[domain].begin()),
312  recvFields[domain].byteSize(),
313  tag
314  );
315  }
316  }
317 
318 
319  // Set up 'send' to myself
320 
321  {
322  const labelList& map = subMap[Pstream::myProcNo()];
323 
324  List<T>& subField = sendFields[Pstream::myProcNo()];
325  subField.setSize(map.size());
326  forAll(map, i)
327  {
328  subField[i] = field[map[i]];
329  }
330  }
331 
332 
333  // Combine bits. Note that can reuse field storage
334 
335  field.setSize(constructSize);
336 
337 
338  // Receive sub field from myself (sendFields[Pstream::myProcNo()])
339  {
340  const labelList& map = constructMap[Pstream::myProcNo()];
341  const List<T>& subField = sendFields[Pstream::myProcNo()];
342 
343  forAll(map, i)
344  {
345  field[map[i]] = subField[i];
346  }
347  }
348 
349 
350  // Wait for all to finish
351 
352  Pstream::waitRequests(nOutstanding);
353 
354 
355  // Collect neighbour fields
356 
357  for (label domain = 0; domain < Pstream::nProcs(); domain++)
358  {
359  const labelList& map = constructMap[domain];
360 
361  if (domain != Pstream::myProcNo() && map.size())
362  {
363  const List<T>& subField = recvFields[domain];
364 
365  checkReceivedSize(domain, map.size(), subField.size());
366 
367  forAll(map, i)
368  {
369  field[map[i]] = subField[i];
370  }
371  }
372  }
373  }
374  }
375  else
376  {
377  FatalErrorIn("mapDistribute::distribute(..)")
378  << "Unknown communication schedule " << commsType
379  << abort(FatalError);
380  }
381 }
382 
383 
384 // Distribute list.
385 template<class T, class CombineOp>
387 (
388  const Pstream::commsTypes commsType,
389  const List<labelPair>& schedule,
390  const label constructSize,
391  const labelListList& subMap,
392  const labelListList& constructMap,
393  List<T>& field,
394  const CombineOp& cop,
395  const T& nullValue,
396  const int tag
397 )
398 {
399  if (!Pstream::parRun())
400  {
401  // Do only me to me.
402 
403  const labelList& mySubMap = subMap[Pstream::myProcNo()];
404 
405  List<T> subField(mySubMap.size());
406  forAll(mySubMap, i)
407  {
408  subField[i] = field[mySubMap[i]];
409  }
410 
411  // Receive sub field from myself (subField)
412  const labelList& map = constructMap[Pstream::myProcNo()];
413 
414  field.setSize(constructSize);
415  field = nullValue;
416 
417  forAll(map, i)
418  {
419  cop(field[map[i]], subField[i]);
420  }
421  return;
422  }
423 
424  if (commsType == Pstream::blocking)
425  {
426  // Since buffered sending can reuse the field to collect the
427  // received data.
428 
429  // Send sub field to neighbour
430  for (label domain = 0; domain < Pstream::nProcs(); domain++)
431  {
432  const labelList& map = subMap[domain];
433 
434  if (domain != Pstream::myProcNo() && map.size())
435  {
436  OPstream toNbr(Pstream::blocking, domain, 0, tag);
437  toNbr << UIndirectList<T>(field, map);
438  }
439  }
440 
441  // Subset myself
442  const labelList& mySubMap = subMap[Pstream::myProcNo()];
443 
444  List<T> subField(mySubMap.size());
445  forAll(mySubMap, i)
446  {
447  subField[i] = field[mySubMap[i]];
448  }
449 
450  // Receive sub field from myself (subField)
451  const labelList& map = constructMap[Pstream::myProcNo()];
452 
453  field.setSize(constructSize);
454  field = nullValue;
455 
456  forAll(map, i)
457  {
458  cop(field[map[i]], subField[i]);
459  }
460 
461  // Receive sub field from neighbour
462  for (label domain = 0; domain < Pstream::nProcs(); domain++)
463  {
464  const labelList& map = constructMap[domain];
465 
466  if (domain != Pstream::myProcNo() && map.size())
467  {
468  IPstream fromNbr(Pstream::blocking, domain, 0, tag);
469  List<T> subField(fromNbr);
470 
471  checkReceivedSize(domain, map.size(), subField.size());
472 
473  forAll(map, i)
474  {
475  cop(field[map[i]], subField[i]);
476  }
477  }
478  }
479  }
480  else if (commsType == Pstream::scheduled)
481  {
482  // Need to make sure I don't overwrite field with received data
483  // since the data might need to be sent to another processor. So
484  // allocate a new field for the results.
485  List<T> newField(constructSize, nullValue);
486 
487  // Subset myself
488  UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
489 
490  // Receive sub field from myself (subField)
491  const labelList& map = constructMap[Pstream::myProcNo()];
492 
493  forAll(map, i)
494  {
495  cop(newField[map[i]], subField[i]);
496  }
497 
498  // Schedule will already have pruned 0-sized comms
499  forAll(schedule, i)
500  {
501  const labelPair& twoProcs = schedule[i];
502  // twoProcs is a swap pair of processors. The first one is the
503  // one that needs to send first and then receive.
504 
505  label sendProc = twoProcs[0];
506  label recvProc = twoProcs[1];
507 
508  if (Pstream::myProcNo() == sendProc)
509  {
510  // I am send first, receive next
511  {
512  OPstream toNbr(Pstream::scheduled, recvProc, 0, tag);
513  toNbr << UIndirectList<T>(field, subMap[recvProc]);
514  }
515  {
516  IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag);
517  List<T> subField(fromNbr);
518  const labelList& map = constructMap[recvProc];
519 
520  checkReceivedSize(recvProc, map.size(), subField.size());
521 
522  forAll(map, i)
523  {
524  cop(newField[map[i]], subField[i]);
525  }
526  }
527  }
528  else
529  {
530  // I am receive first, send next
531  {
532  IPstream fromNbr(Pstream::scheduled, sendProc, 0, tag);
533  List<T> subField(fromNbr);
534  const labelList& map = constructMap[sendProc];
535 
536  checkReceivedSize(sendProc, map.size(), subField.size());
537 
538  forAll(map, i)
539  {
540  cop(newField[map[i]], subField[i]);
541  }
542  }
543  {
544  OPstream toNbr(Pstream::scheduled, sendProc, 0, tag);
545  toNbr << UIndirectList<T>(field, subMap[sendProc]);
546  }
547  }
548  }
549  field.transfer(newField);
550  }
551  else if (commsType == Pstream::nonBlocking)
552  {
553  label nOutstanding = Pstream::nRequests();
554 
555  if (!contiguous<T>())
556  {
557  PstreamBuffers pBufs(Pstream::nonBlocking, tag);
558 
559  // Stream data into buffer
560  for (label domain = 0; domain < Pstream::nProcs(); domain++)
561  {
562  const labelList& map = subMap[domain];
563 
564  if (domain != Pstream::myProcNo() && map.size())
565  {
566  // Put data into send buffer
567  UOPstream toDomain(domain, pBufs);
568  toDomain << UIndirectList<T>(field, map);
569  }
570  }
571 
572  // Start receiving. Do not block.
573  pBufs.finishedSends(false);
574 
575  {
576  // Set up 'send' to myself
577  List<T> mySubField(field, subMap[Pstream::myProcNo()]);
578  // Combine bits. Note that can reuse field storage
579  field.setSize(constructSize);
580  field = nullValue;
581  // Receive sub field from myself
582  {
583  const labelList& map = constructMap[Pstream::myProcNo()];
584 
585  forAll(map, i)
586  {
587  cop(field[map[i]], mySubField[i]);
588  }
589  }
590  }
591 
592  // Block ourselves, waiting only for the current comms
593  Pstream::waitRequests(nOutstanding);
594 
595  // Consume
596  for (label domain = 0; domain < Pstream::nProcs(); domain++)
597  {
598  const labelList& map = constructMap[domain];
599 
600  if (domain != Pstream::myProcNo() && map.size())
601  {
602  UIPstream str(domain, pBufs);
603  List<T> recvField(str);
604 
605  checkReceivedSize(domain, map.size(), recvField.size());
606 
607  forAll(map, i)
608  {
609  cop(field[map[i]], recvField[i]);
610  }
611  }
612  }
613  }
614  else
615  {
616  // Set up sends to neighbours
617 
618  List<List<T > > sendFields(Pstream::nProcs());
619 
620  for (label domain = 0; domain < Pstream::nProcs(); domain++)
621  {
622  const labelList& map = subMap[domain];
623 
624  if (domain != Pstream::myProcNo() && map.size())
625  {
626  List<T>& subField = sendFields[domain];
627  subField.setSize(map.size());
628  forAll(map, i)
629  {
630  subField[i] = field[map[i]];
631  }
632 
634  (
635  Pstream::nonBlocking,
636  domain,
637  reinterpret_cast<const char*>(subField.begin()),
638  subField.size()*sizeof(T),
639  tag
640  );
641  }
642  }
643 
644  // Set up receives from neighbours
645 
646  List<List<T > > recvFields(Pstream::nProcs());
647 
648  for (label domain = 0; domain < Pstream::nProcs(); domain++)
649  {
650  const labelList& map = constructMap[domain];
651 
652  if (domain != Pstream::myProcNo() && map.size())
653  {
654  recvFields[domain].setSize(map.size());
656  (
657  Pstream::nonBlocking,
658  domain,
659  reinterpret_cast<char*>(recvFields[domain].begin()),
660  recvFields[domain].size()*sizeof(T),
661  tag
662  );
663  }
664  }
665 
666  // Set up 'send' to myself
667 
668  {
669  const labelList& map = subMap[Pstream::myProcNo()];
670 
671  List<T>& subField = sendFields[Pstream::myProcNo()];
672  subField.setSize(map.size());
673  forAll(map, i)
674  {
675  subField[i] = field[map[i]];
676  }
677  }
678 
679 
680  // Combine bits. Note that can reuse field storage
681 
682  field.setSize(constructSize);
683  field = nullValue;
684 
685  // Receive sub field from myself (subField)
686  {
687  const labelList& map = constructMap[Pstream::myProcNo()];
688  const List<T>& subField = sendFields[Pstream::myProcNo()];
689 
690  forAll(map, i)
691  {
692  cop(field[map[i]], subField[i]);
693  }
694  }
695 
696 
697  // Wait for all to finish
698 
699  Pstream::waitRequests(nOutstanding);
700 
701 
702  // Collect neighbour fields
703 
704  for (label domain = 0; domain < Pstream::nProcs(); domain++)
705  {
706  const labelList& map = constructMap[domain];
707 
708  if (domain != Pstream::myProcNo() && map.size())
709  {
710  const List<T>& subField = recvFields[domain];
711 
712  checkReceivedSize(domain, map.size(), subField.size());
713 
714  forAll(map, i)
715  {
716  cop(field[map[i]], subField[i]);
717  }
718  }
719  }
720  }
721  }
722  else
723  {
724  FatalErrorIn("mapDistribute::distribute(..)")
725  << "Unknown communication schedule " << commsType
726  << abort(FatalError);
727  }
728 }
729 
730 
731 template<class T>
733 const
734 {
735  // Stream data into buffer
736  for (label domain = 0; domain < Pstream::nProcs(); domain++)
737  {
738  const labelList& map = subMap_[domain];
739 
740  if (map.size())
741  {
742  // Put data into send buffer
743  UOPstream toDomain(domain, pBufs);
744  toDomain << UIndirectList<T>(field, map);
745  }
746  }
747 
748  // Start sending and receiving but do not block.
749  pBufs.finishedSends(false);
750 }
751 
752 
753 template<class T>
755 {
756  // Consume
757  field.setSize(constructSize_);
758 
759  for (label domain = 0; domain < Pstream::nProcs(); domain++)
760  {
761  const labelList& map = constructMap_[domain];
762 
763  if (map.size())
764  {
765  UIPstream str(domain, pBufs);
766  List<T> recvField(str);
767 
768  if (recvField.size() != map.size())
769  {
771  (
772  "template<class T>\n"
773  "void mapDistribute::receive\n"
774  "(\n"
775  " PstreamBuffers&,\n"
776  " List<T>&\n"
777  ")\n"
778  ) << "Expected from processor " << domain
779  << " " << map.size() << " but received "
780  << recvField.size() << " elements."
781  << abort(FatalError);
782  }
783 
784  forAll(map, i)
785  {
786  field[map[i]] = recvField[i];
787  }
788  }
789  }
790 }
791 
792 
793 // In case of no transform: copy elements
794 template<class T>
795 void Foam::mapDistribute::applyDummyTransforms(List<T>& field) const
796 {
797  forAll(transformElements_, trafoI)
798  {
799  const labelList& elems = transformElements_[trafoI];
800 
801  label n = transformStart_[trafoI];
802 
803  forAll(elems, i)
804  {
805  field[n++] = field[elems[i]];
806  }
807  }
808 }
809 
810 
811 // In case of no transform: copy elements
812 template<class T>
813 void Foam::mapDistribute::applyDummyInverseTransforms(List<T>& field) const
814 {
815  forAll(transformElements_, trafoI)
816  {
817  const labelList& elems = transformElements_[trafoI];
818  label n = transformStart_[trafoI];
819 
820  forAll(elems, i)
821  {
822  field[elems[i]] = field[n++];
823  }
824  }
825 }
826 
827 
828 // Calculate transformed elements.
829 template<class T, class TransformOp> //, class CombineOp>
830 void Foam::mapDistribute::applyTransforms
831 (
832  const globalIndexAndTransform& globalTransforms,
833  List<T>& field,
834  const TransformOp& top
835 ) const
836 {
837  const List<vectorTensorTransform>& totalTransform =
838  globalTransforms.transformPermutations();
839 
840  forAll(totalTransform, trafoI)
841  {
842  const vectorTensorTransform& vt = totalTransform[trafoI];
843  const labelList& elems = transformElements_[trafoI];
844  label n = transformStart_[trafoI];
845 
846  // Could be optimised to avoid memory allocations
847  List<T> transformFld(UIndirectList<T>(field, elems));
848  top(vt, true, transformFld);
849 
850  forAll(transformFld, i)
851  {
852  //cop(field[n++], transformFld[i]);
853  field[n++] = transformFld[i];
854  }
855  }
856 }
857 
858 
859 // Calculate transformed elements.
860 template<class T, class TransformOp> //, class CombineOp>
861 void Foam::mapDistribute::applyInverseTransforms
862 (
863  const globalIndexAndTransform& globalTransforms,
864  List<T>& field,
865  const TransformOp& top
866 ) const
867 {
868  const List<vectorTensorTransform>& totalTransform =
869  globalTransforms.transformPermutations();
870 
871  forAll(totalTransform, trafoI)
872  {
873  const vectorTensorTransform& vt = totalTransform[trafoI];
874  const labelList& elems = transformElements_[trafoI];
875  label n = transformStart_[trafoI];
876 
877  // Could be optimised to avoid memory allocations
878  List<T> transformFld(SubList<T>(field, elems.size(), n));
879  top(vt, false, transformFld);
880 
881  forAll(transformFld, i)
882  {
883  //cop(field[elems[i]], transformFld[i]);
884  field[elems[i]] = transformFld[i];
885  }
886  }
887 }
888 
889 
890 //- Distribute data using default commsType.
891 template<class T>
893 (
894  DynamicList<T>& fld,
895  const bool dummyTransform,
896  const int tag
897 ) const
898 {
899  fld.shrink();
900 
901  List<T>& fldList = static_cast<List<T>& >(fld);
902 
903  distribute(fldList, dummyTransform, tag);
904 
905  fld.setCapacity(fldList.size());
906 }
907 
908 
909 //- Distribute data using default commsType.
910 template<class T>
912 (
913  List<T>& fld,
914  const bool dummyTransform,
915  const int tag
916 ) const
917 {
919  {
920  distribute
921  (
923  List<labelPair>(),
924  constructSize_,
925  subMap_,
926  constructMap_,
927  fld,
928  tag
929  );
930  }
932  {
933  distribute
934  (
936  schedule(),
937  constructSize_,
938  subMap_,
939  constructMap_,
940  fld,
941  tag
942  );
943  }
944  else
945  {
946  distribute
947  (
949  List<labelPair>(),
950  constructSize_,
951  subMap_,
952  constructMap_,
953  fld,
954  tag
955  );
956  }
957 
958  //- Fill in transformed slots with copies
959  if (dummyTransform)
960  {
961  applyDummyTransforms(fld);
962  }
963 }
964 
965 
966 //- Reverse distribute data using default commsType.
967 template<class T>
969 (
970  const label constructSize,
971  List<T>& fld,
972  const bool dummyTransform,
973  const int tag
974 ) const
975 {
976  if (dummyTransform)
977  {
978  applyDummyInverseTransforms(fld);
979  }
980 
982  {
983  distribute
984  (
986  List<labelPair>(),
987  constructSize,
988  constructMap_,
989  subMap_,
990  fld,
991  tag
992  );
993  }
995  {
996  distribute
997  (
999  schedule(),
1000  constructSize,
1001  constructMap_,
1002  subMap_,
1003  fld,
1004  tag
1005  );
1006  }
1007  else
1008  {
1009  distribute
1010  (
1012  List<labelPair>(),
1013  constructSize,
1014  constructMap_,
1015  subMap_,
1016  fld,
1017  tag
1018  );
1019  }
1020 }
1021 
1022 
1023 //- Reverse distribute data using default commsType.
1024 // Since constructSize might be larger than supplied size supply
1025 // a nullValue
1026 template<class T>
1029  const label constructSize,
1030  const T& nullValue,
1031  List<T>& fld,
1032  const bool dummyTransform,
1033  const int tag
1034 ) const
1035 {
1036  if (dummyTransform)
1037  {
1038  applyDummyInverseTransforms(fld);
1039  }
1040 
1042  {
1043  distribute
1044  (
1046  List<labelPair>(),
1047  constructSize,
1048  constructMap_,
1049  subMap_,
1050  fld,
1051  eqOp<T>(),
1052  nullValue,
1053  tag
1054  );
1055  }
1057  {
1058  distribute
1059  (
1061  schedule(),
1062  constructSize,
1063  constructMap_,
1064  subMap_,
1065  fld,
1066  eqOp<T>(),
1067  nullValue,
1068  tag
1069  );
1070  }
1071  else
1072  {
1073  distribute
1074  (
1076  List<labelPair>(),
1077  constructSize,
1078  constructMap_,
1079  subMap_,
1080  fld,
1081  eqOp<T>(),
1082  nullValue,
1083  tag
1084  );
1085  }
1086 }
1087 
1088 
1089 //- Distribute data using default commsType.
1090 template<class T, class TransformOp>
1093  const globalIndexAndTransform& git,
1094  List<T>& fld,
1095  const TransformOp& top,
1096  const int tag
1097 ) const
1098 {
1099  // Distribute. Leave out dummy transforms since we're doing them ourselves
1100  distribute(fld, false, tag);
1101  // Do transforms
1102  applyTransforms(git, fld, top);
1103 }
1104 
1105 
1106 template<class T, class TransformOp>
1109  const globalIndexAndTransform& git,
1110  const label constructSize,
1111  List<T>& fld,
1112  const TransformOp& top,
1113  const int tag
1114 ) const
1115 {
1116  // Fill slots with reverse-transformed data. Note that it also copies
1117  // back into the non-remote part of fld even though these values are not
1118  // used.
1119  applyInverseTransforms(git, fld, top);
1120 
1121  // And send back (the remote slots). Disable dummy transformations.
1122  reverseDistribute(constructSize, fld, false, tag);
1123 }
1124 
1125 
1126 template<class T, class TransformOp>
1129  const globalIndexAndTransform& git,
1130  const label constructSize,
1131  const T& nullValue,
1132  List<T>& fld,
1133  const TransformOp& top,
1134  const int tag
1135 ) const
1136 {
1137  // Fill slots with reverse-transformed data Note that it also copies
1138  // back into the non-remote part of fld even though these values are not
1139  // used.
1140  applyInverseTransforms(git, fld, top); //, eqOp<T>());
1141 
1142  // And send back (the remote slots) Disable dummy transformations.
1143  reverseDistribute(constructSize, nullValue, fld, false, tag);
1144 }
1145 
1146 
1147 // ************************************************************************* //
void receive(PstreamBuffers &, List< T > &) const
Do all receives using PstreamBuffers.
void send(PstreamBuffers &, const List< T > &) const
Do all sends using PstreamBuffers.
Determination and storage of the possible independent transforms introduced by coupledPolyPatches, as well as all of the possible permutations of these transforms generated by the presence of multiple coupledPolyPatches, i.e. more than one cyclic boundary.
std::streamsize byteSize() const
Return the binary size in number of characters of the UList.
Definition: UList.C:92
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:109
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
static void distribute(const Pstream::commsTypes commsType, const List< labelPair > &schedule, const label constructSize, const labelListList &subMap, const labelListList &constructMap, List< T > &, const int tag=UPstream::msgType())
Distribute data. Note:schedule only used for Pstream::scheduled.
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const List< vectorTensorTransform > & transformPermutations() const
Return access to the permuted transforms.
Definition: ops.H:70
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
Output inter-processor communications stream.
Definition: OPstream.H:50
const volScalarField & T
Definition: createFields.H:25
runTime write()
void reverseDistribute(const label constructSize, List< T > &, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType.
label n
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:216
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
void setSize(const label)
Reset size of List.
Definition: List.C:318
A List with indirect addressing.
Definition: fvMatrix.H:106
commsTypes
Types of communications.
Definition: UPstream.H:64
#define forAll(list, i)
Definition: UList.H:421
Spatial transformation functions for primitive fields.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
errorManip< error > abort(error &err)
Definition: errorManip.H:131
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().x()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().y()<< ' ';}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().z()<< ' ';}gmvFile<< nl;forAll(lagrangianScalarNames, i){const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject( name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE ))
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
Vector-tensor class used to perform translations and rotations in 3D space.
const List< labelPair > & schedule() const
Return a schedule. Demand driven. See above.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
error FatalError
Input inter-processor communications stream.
Definition: IPstream.H:50
bool read(const char *, int32_t &)
Definition: int32IO.C:87
A List obtained as a section of another List.
Definition: SubList.H:53
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:255
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Combination-Reduction operation for a parallel run. The information from all nodes is collected on th...