globalIndexTemplates.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) 2013-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2020 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 "globalIndex.H"
30 
31 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
32 
33 template<class Container, class Type>
35 (
36  const labelUList& off,
37  const label comm,
38  const Container& procIDs,
39  const UList<Type>& fld,
40  List<Type>& allFld,
41  const int tag,
42  const Pstream::commsTypes commsType
43 )
44 {
45  if (Pstream::myProcNo(comm) == procIDs[0])
46  {
47  allFld.setSize(off.last());
48 
49  // Assign my local data
50  SubList<Type>(allFld, fld.size(), 0) = fld;
51 
52  if
53  (
54  commsType == Pstream::commsTypes::scheduled
55  || commsType == Pstream::commsTypes::blocking
56  )
57  {
58  for (label i = 1; i < procIDs.size(); ++i)
59  {
60  SubList<Type> procSlot(allFld, off[i+1]-off[i], off[i]);
61 
63  {
65  (
66  commsType,
67  procIDs[i],
68  reinterpret_cast<char*>(procSlot.data()),
69  procSlot.byteSize(),
70  tag,
71  comm
72  );
73  }
74  else
75  {
76  IPstream fromSlave
77  (
78  commsType,
79  procIDs[i],
80  0,
81  tag,
82  comm
83  );
84  fromSlave >> procSlot;
85  }
86  }
87  }
88  else
89  {
90  // nonBlocking
91 
93  {
95  << "nonBlocking not supported for non-contiguous data"
96  << exit(FatalError);
97  }
98 
99  label startOfRequests = Pstream::nRequests();
100 
101  // Set up reads
102  for (label i = 1; i < procIDs.size(); ++i)
103  {
104  SubList<Type> procSlot(allFld, off[i+1]-off[i], off[i]);
105 
107  (
108  commsType,
109  procIDs[i],
110  reinterpret_cast<char*>(procSlot.data()),
111  procSlot.byteSize(),
112  tag,
113  comm
114  );
115  }
116 
117  // Wait for all to finish
118  Pstream::waitRequests(startOfRequests);
119  }
120  }
121  else
122  {
123  if
124  (
125  commsType == Pstream::commsTypes::scheduled
126  || commsType == Pstream::commsTypes::blocking
127  )
128  {
130  {
132  (
133  commsType,
134  procIDs[0],
135  reinterpret_cast<const char*>(fld.cdata()),
136  fld.byteSize(),
137  tag,
138  comm
139  );
140  }
141  else
142  {
143  OPstream toMaster
144  (
145  commsType,
146  procIDs[0],
147  0,
148  tag,
149  comm
150  );
151  toMaster << fld;
152  }
153  }
154  else
155  {
156  // nonBlocking
157 
159  {
161  << "nonBlocking not supported for non-contiguous data"
162  << exit(FatalError);
163  }
164 
165  label startOfRequests = Pstream::nRequests();
166 
167  // Set up write
169  (
170  commsType,
171  procIDs[0],
172  reinterpret_cast<const char*>(fld.cdata()),
173  fld.byteSize(),
174  tag,
175  comm
176  );
177 
178  // Wait for all to finish
179  Pstream::waitRequests(startOfRequests);
180  }
181  }
182 }
183 
184 
185 template<class Type>
187 (
188  const UList<Type>& fld,
189  List<Type>& allFld,
190  const int tag,
191  const Pstream::commsTypes commsType
192 ) const
193 {
194  gather
195  (
196  UPstream::worldComm,
197  UPstream::procID(UPstream::worldComm),
198  fld,
199  allFld,
200  tag,
201  commsType
202  );
203 }
204 
205 
206 template<class Type>
208 (
209  const UList<Type>& fld,
210  List<Type>& allFld,
211  const int tag,
212  const Pstream::commsTypes commsType
213 )
214 {
215  globalIndex(fld.size()).gather(fld, allFld, tag, commsType);
216 }
217 
218 
219 template<class Container, class Type>
221 (
222  const labelUList& off,
223  const label comm,
224  const Container& procIDs,
225  List<Type>& fld,
226  const int tag,
227  const Pstream::commsTypes commsType
228 )
229 {
230  List<Type> allFld;
231 
232  gather(off, comm, procIDs, fld, allFld, tag, commsType);
233 
234  if (Pstream::myProcNo(comm) == procIDs[0])
235  {
236  fld.transfer(allFld);
237  }
238 }
239 
240 
241 template<class Type>
243 (
244  List<Type>& fld,
245  const int tag,
246  const Pstream::commsTypes commsType
247 ) const
248 {
249  List<Type> allFld;
250 
251  gather
252  (
253  UPstream::worldComm,
254  UPstream::procID(UPstream::worldComm),
255  fld,
256  allFld,
257  tag,
258  commsType
259  );
260 
261  if (Pstream::master(UPstream::worldComm))
262  {
263  fld.transfer(allFld);
264  }
265  else
266  {
267  fld.clear();
268  }
269 }
270 
271 
272 template<class Type>
274 (
275  List<Type>& fld,
276  const int tag,
277  const Pstream::commsTypes commsType
278 )
279 {
280  globalIndex(fld.size()).gather(fld, tag, commsType);
281 }
282 
283 
284 template<class Container, class Type>
286 (
287  const labelUList& off,
288  const label comm,
289  const Container& procIDs,
290  const UList<Type>& allFld,
291  UList<Type>& fld,
292  const int tag,
293  const Pstream::commsTypes commsType
294 )
295 {
296  if (Pstream::myProcNo(comm) == procIDs[0])
297  {
298  fld.deepCopy(SubList<Type>(allFld, off[1]-off[0]));
299 
300  if
301  (
302  commsType == Pstream::commsTypes::scheduled
303  || commsType == Pstream::commsTypes::blocking
304  )
305  {
306  for (label i = 1; i < procIDs.size(); ++i)
307  {
308  const SubList<Type> procSlot
309  (
310  allFld,
311  off[i+1]-off[i],
312  off[i]
313  );
314 
316  {
318  (
319  commsType,
320  procIDs[i],
321  reinterpret_cast<const char*>(procSlot.cdata()),
322  procSlot.byteSize(),
323  tag,
324  comm
325  );
326  }
327  else
328  {
329  OPstream toSlave
330  (
331  commsType,
332  procIDs[i],
333  0,
334  tag,
335  comm
336  );
337  toSlave << procSlot;
338  }
339  }
340  }
341  else
342  {
343  // nonBlocking
344 
346  {
348  << "nonBlocking not supported for non-contiguous data"
349  << exit(FatalError);
350  }
351 
352  label startOfRequests = Pstream::nRequests();
353 
354  // Set up writes
355  for (label i = 1; i < procIDs.size(); ++i)
356  {
357  const SubList<Type> procSlot
358  (
359  allFld,
360  off[i+1]-off[i],
361  off[i]
362  );
363 
365  (
366  commsType,
367  procIDs[i],
368  reinterpret_cast<const char*>(procSlot.cdata()),
369  procSlot.byteSize(),
370  tag,
371  comm
372  );
373  }
374 
375  // Wait for all to finish
376  Pstream::waitRequests(startOfRequests);
377  }
378  }
379  else
380  {
381  if
382  (
383  commsType == Pstream::commsTypes::scheduled
384  || commsType == Pstream::commsTypes::blocking
385  )
386  {
388  {
390  (
391  commsType,
392  procIDs[0],
393  reinterpret_cast<char*>(fld.data()),
394  fld.byteSize(),
395  tag,
396  comm
397  );
398  }
399  else
400  {
401  IPstream fromMaster
402  (
403  commsType,
404  procIDs[0],
405  0,
406  tag,
407  comm
408  );
409  fromMaster >> fld;
410  }
411  }
412  else
413  {
414  // nonBlocking
415 
417  {
419  << "nonBlocking not supported for non-contiguous data"
420  << exit(FatalError);
421  }
422 
423  label startOfRequests = Pstream::nRequests();
424 
425  // Set up read
427  (
428  commsType,
429  procIDs[0],
430  reinterpret_cast<char*>(fld.data()),
431  fld.byteSize(),
432  tag,
433  comm
434  );
435 
436  // Wait for all to finish
437  Pstream::waitRequests(startOfRequests);
438  }
439  }
440 }
441 
442 
443 template<class Type>
445 (
446  const UList<Type>& allFld,
447  UList<Type>& fld,
448  const int tag,
449  const Pstream::commsTypes commsType
450 ) const
451 {
452  scatter
453  (
454  offsets_,
455  UPstream::worldComm,
456  UPstream::procID(UPstream::worldComm),
457  allFld,
458  fld,
459  tag,
460  commsType
461  );
462 }
463 
464 
465 template<class Type, class CombineOp>
467 (
468  List<Type>& allFld,
469  const labelUList& globalIds,
470  const CombineOp& cop,
471  const label comm,
472  const int tag
473 ) const
474 {
475  allFld.setSize(globalIds.size());
476  if (globalIds.size())
477  {
478  // Sort according to processor
479  labelList order;
481  DynamicList<label> validBins(Pstream::nProcs());
482  bin
483  (
484  offsets(),
485  globalIds,
486  order,
487  bins,
488  validBins
489  );
490 
491  // Send local indices to individual processors as local index
492  PstreamBuffers sendBufs(Pstream::commsTypes::nonBlocking, tag, comm);
493 
494  for (const auto proci : validBins)
495  {
496  const labelUList& es = bins[proci];
497 
498  labelList localIDs(es.size());
499  forAll(es, i)
500  {
501  localIDs[i] = toLocal(proci, es[i]);
502  }
503 
504  UOPstream os(proci, sendBufs);
505  os << localIDs;
506  }
507  labelList recvSizes;
508  sendBufs.finishedSends(recvSizes);
509 
510 
511  PstreamBuffers returnBufs(Pstream::commsTypes::nonBlocking, tag, comm);
512 
513  forAll(recvSizes, proci)
514  {
515  if (recvSizes[proci])
516  {
517  UIPstream is(proci, sendBufs);
518  labelList localIDs(is);
519 
520  // Collect entries
521  List<Type> fld(localIDs.size());
522  cop(fld, localIDs);
523 
524  UOPstream os(proci, returnBufs);
525  os << fld;
526  }
527  }
528  returnBufs.finishedSends();
529 
530  // Slot back
531  for (const auto proci : validBins)
532  {
533  label start = bins.offsets()[proci];
534  const SubList<label> es
535  (
536  order,
537  bins.offsets()[proci+1]-start, // start
538  start
539  );
540  UIPstream is(proci, returnBufs);
541  List<Type> fld(is);
542 
543  UIndirectList<Type>(allFld, es) = fld;
544  }
545  }
546 }
547 
548 
549 // ************************************************************************* //
Foam::CompactListList::offsets
const List< label > & offsets() const
Return the offset table (= size()+1)
Definition: CompactListListI.H:142
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:57
Foam::DynamicList< label >
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:52
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::CompactListList
A packed storage unstructured matrix of objects of type <T> using an offset table for access.
Definition: polyTopoChange.H:93
globalIndex.H
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:87
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::UList::last
T & last()
Return the last element of the list.
Definition: UListI.H:184
Foam::globalIndex::gatherOp
static void gatherOp(const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const Pstream::commsTypes commsType=Pstream::commsTypes::nonBlocking)
Collect data in processor order on master.
Definition: globalIndexTemplates.C:208
fld
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))
Definition: gmvOutputLagrangian.H:23
Foam::globalIndex::get
void get(List< Type > &allFld, const labelUList &globalIds, const CombineOp &cop, const label comm=Pstream::worldComm, const int tag=UPstream::msgType()) const
Get (potentially remote) data. Elements required given as.
Definition: globalIndexTemplates.C:467
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Definition: PstreamBuffers.C:80
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
Foam::globalIndex::scatter
static void scatter(const labelUList &offsets, const label comm, const Container &procIDs, const UList< Type > &allFld, UList< Type > &fld, const int tag=UPstream::msgType(), const Pstream::commsTypes commsType=Pstream::commsTypes::nonBlocking)
Distribute data in processor order. Requires fld to be sized!
Definition: globalIndexTemplates.C:286
Foam::FatalError
error FatalError
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::UPstream::commsTypes
commsTypes
Types of communications.
Definition: UPstream.H:69
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::List< Type >
Foam::UList< label >
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:35
Foam::UList::size
void size(const label n) noexcept
Override size to be inconsistent with allocated storage.
Definition: UListI.H:360
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:52
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:56
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::is_contiguous
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:75
Foam::globalIndex::gather
static void gather(const labelUList &offsets, const label comm, const Container &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const Pstream::commsTypes commsType=Pstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
Definition: globalIndexTemplates.C:35