FreeFOAM The Cross-Platform CFD Toolkit
Pstream.H
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) 1991-2010 OpenCFD Ltd.
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 Class
25  Foam::Pstream
26 
27 Description
28  Inter-processor communications stream
29 
30 SourceFiles
31  Pstream.C
32  PstreamsPrint.C
33  PstreamCommsStruct.C
34  gatherScatter.C
35  combineGatherScatter.C
36  gatherScatterList.C
37 
38 \*---------------------------------------------------------------------------*/
39 
40 #ifndef Pstream_H
41 #define Pstream_H
42 
43 #include "PstreamImpl.H"
44 #include <OpenFOAM/labelList.H>
45 #include <OpenFOAM/DynamicList.H>
46 #include <OpenFOAM/HashTable.H>
47 #include <OpenFOAM/string.H>
48 #include <OpenFOAM/NamedEnum.H>
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
52 namespace Foam
53 {
54 
55 /*---------------------------------------------------------------------------*\
56  Class Pstream Declaration
57 \*---------------------------------------------------------------------------*/
58 
59 class Pstream
60 : public helper_::PstreamBase
61 {
62 
63 public:
64 
65  //- Types of communications
67 
69 
70  //- Structure for communicating between processors
72  {
73  // Private data
74 
75  //- procID of above processor
76  label above_;
77 
78  //- procIDs of processors directly below me
79  labelList below_;
80 
81  //- procIDs of all processors below (so not just directly below)
82  labelList allBelow_;
83 
84  //- procIDs of all processors not below. (inverse set of allBelow_
85  // and minus myProcNo)
86  labelList allNotBelow_;
87 
88 
89  public:
90 
91  // Constructors
92 
93  //- Construct null
94  commsStruct();
95 
96  //- Construct from components
98  (
99  const label,
100  const labelList&,
101  const labelList&,
102  const labelList&
103  );
104 
105  //- Construct from components; construct allNotBelow_
107  (
108  const label nProcs,
109  const label myProcID,
110  const label,
111  const labelList&,
112  const labelList&
113  );
114 
115 
116  // Member Functions
117 
118  // Access
119 
120  label above() const
121  {
122  return above_;
123  }
124 
125  const labelList& below() const
126  {
127  return below_;
128  }
129 
130  const labelList& allBelow() const
131  {
132  return allBelow_;
133  }
134 
135  const labelList& allNotBelow() const
136  {
137  return allNotBelow_;
138  }
139 
140 
141  // Member operators
142 
143  bool operator==(const commsStruct&) const;
144 
145  bool operator!=(const commsStruct&) const;
146 
147 
148  // Ostream Operator
149 
150  friend Ostream& operator<<(Ostream&, const commsStruct&);
151  };
152 
153 
154 private:
155 
156  // Private data
157 
158  static int myProcNo_;
159  static bool parRun_;
160 
161  static List<int> procIDs_;
162  static const int msgType_;
163 
164  static List<commsStruct> linearCommunication_;
165  static List<commsStruct> treeCommunication_;
166 
167  static autoPtr<PstreamImpl> impl_;
168 
169 
170  // Private member functions
171 
172  //- Calculate linear communication schedule
173  static void calcLinearComm(const label nProcs);
174 
175  //- Calculate tree communication schedule
176  static void calcTreeComm(const label nProcs);
177 
178  //- Helper function for tree communication schedule determination
179  // Collects all processorIDs below a processor
180  static void collectReceives
181  (
182  const label procID,
183  const List<DynamicList<label> >& receives,
184  DynamicList<label>& allReceives
185  );
186 
187  //- Initialize all communication schedules. Callback from
188  // PstreamImpl::init()
189  static void initCommunicationSchedule();
190 
191  //- Fetches the PstreamImpl instance if necessary
192  static autoPtr<PstreamImpl>& impl()
193  {
194  if(!impl_.valid())
195  {
196  impl_ = PstreamImpl::New();
197  }
198  return impl_;
199  }
200 
201 
202 protected:
203 
204  // Protected data
205 
206  //- Communications type of this stream
208 
209  //- Transfer buffer
211 
212  //- Current buffer read/write location
214 
215 
216  // Protected member functions
217 
218  //- Increase the size of the transfer buffer
219  inline void enlargeBuffer(size_t count);
220 
221 
222 public:
223 
224  // Declare name of the class and its debug switch
225  ClassName("Pstream");
226 
227 
228  // Static data
229 
230  //- Should compact transfer be used in which floats replace doubles
231  // reducing the bandwidth requirement at the expense of some loss
232  // in accuracy
233  static bool floatTransfer;
234 
235  //- Number of processors at which the sum algorithm changes from linear
236  // to tree
237  static int nProcsSimpleSum;
238 
239  //- Default commsType
241 
242 
243  // Constructors
244 
245  //- Construct given optional buffer size
246  Pstream
247  (
248  const commsTypes commsType,
249  const label bufSize = 0
250  )
251  :
252  commsType_(commsType),
253  bufPosition_(0)
254  {
255  if (bufSize)
256  {
257  buf_.setSize(bufSize + 2*sizeof(scalar) + 1);
258  }
259  }
260 
261 
262  // Member functions
263 
264  //- Add the valid option this type of communications library
265  // adds/requires on the command line
266  static void addValidParOptions(HashTable<string>& validParOptions)
267  {
268  impl()->addValidParOptions(validParOptions);
269  }
270 
271  //- Initialisation function called from main
272  // Spawns slave processes and initialises inter-communication
273  static bool init(int& argc, char**& argv)
274  {
275  return impl()->init(argc, argv, myProcNo_, procIDs_, parRun_);
276  }
277 
278  //- Is this a parallel run?
279  static bool parRun()
280  {
281  return parRun_;
282  }
283 
284  //- Number of processes in parallel run
285  static label nProcs()
286  {
287  return procIDs_.size();
288  }
289 
290  //- Am I the master process
291  static bool master()
292  {
293  return myProcNo_ == 0;
294  }
295 
296  //- Process index of the master
297  static int masterNo()
298  {
299  return 0;
300  }
301 
302  //- Number of this process (starting from masterNo() = 0)
303  static int myProcNo()
304  {
305  return myProcNo_;
306  }
307 
308  //- Process IDs
309  static const List<int>& procIDs()
310  {
311  return procIDs_;
312  }
313 
314  //- Process ID of given process index
315  static int procID(int procNo)
316  {
317  return procIDs_[procNo];
318  }
319 
320  //- Process index of first slave
321  static int firstSlave()
322  {
323  return 1;
324  }
325 
326  //- Process index of last slave
327  static int lastSlave()
328  {
329  return nProcs() - 1;
330  }
331 
332  //- Communication schedule for linear all-to-master (proc 0)
334  {
335  return linearCommunication_;
336  }
337 
338  //- Communication schedule for tree all-to-master (proc 0)
340  {
341  return treeCommunication_;
342  }
343 
344  //- Message tag of standard messages
345  static int msgType()
346  {
347  return msgType_;
348  }
349 
350  //- Get the communications type of the stream
352  {
353  return commsType_;
354  }
355 
356  //- Set the communications type of the stream
358  {
359  commsTypes oldCommsType = commsType_;
360  commsType_ = ct;
361  return oldCommsType;
362  }
363 
364  //- Exit program
365  static void exit(int errnum = 1)
366  {
367  impl()->exit(errnum);
368  }
369 
370  //- Abort program
371  static void abort()
372  {
373  impl()->abort();
374  }
375 
376 
377  // Gather and scatter
378 
379  //- Gather data. Apply bop to combine Value
380  // from different processors
381  template <class T, class BinaryOp>
382  static void gather
383  (
384  const List<commsStruct>& comms,
385  T& Value,
386  const BinaryOp& bop
387  );
388 
389  //- Like above but switches between linear/tree communication
390  template <class T, class BinaryOp>
391  static void gather(T& Value, const BinaryOp& bop);
392 
393  //- Scatter data. Distribute without modification. Reverse of gather
394  template <class T>
395  static void scatter(const List<commsStruct>& comms, T& Value);
396 
397  //- Like above but switches between linear/tree communication
398  template <class T>
399  static void scatter(T& Value);
400 
401 
402  // Combine variants. Inplace combine values from processors.
403  // (Uses construct from Istream instead of <<)
404 
405  template <class T, class CombineOp>
406  static void combineGather
407  (
408  const List<commsStruct>& comms,
409  T& Value,
410  const CombineOp& cop
411  );
412 
413  //- Like above but switches between linear/tree communication
414  template <class T, class CombineOp>
415  static void combineGather(T& Value, const CombineOp& cop);
416 
417  //- Scatter data. Reverse of combineGather
418  template <class T>
419  static void combineScatter
420  (
421  const List<commsStruct>& comms,
422  T& Value
423  );
424 
425  //- Like above but switches between linear/tree communication
426  template <class T>
427  static void combineScatter(T& Value);
428 
429  // Combine variants working on whole List at a time.
430 
431  template <class T, class CombineOp>
432  static void listCombineGather
433  (
434  const List<commsStruct>& comms,
435  List<T>& Value,
436  const CombineOp& cop
437  );
438 
439  //- Like above but switches between linear/tree communication
440  template <class T, class CombineOp>
441  static void listCombineGather(List<T>& Value, const CombineOp& cop);
442 
443  //- Scatter data. Reverse of combineGather
444  template <class T>
445  static void listCombineScatter
446  (
447  const List<commsStruct>& comms,
448  List<T>& Value
449  );
450 
451  //- Like above but switches between linear/tree communication
452  template <class T>
453  static void listCombineScatter(List<T>& Value);
454 
455  // Combine variants working on whole map at a time. Container needs to
456  // have iterators and find() defined.
457 
458  template <class Container, class CombineOp>
459  static void mapCombineGather
460  (
461  const List<commsStruct>& comms,
462  Container& Values,
463  const CombineOp& cop
464  );
465 
466  //- Like above but switches between linear/tree communication
467  template <class Container, class CombineOp>
468  static void mapCombineGather
469  (
470  Container& Values,
471  const CombineOp& cop
472  );
473 
474  //- Scatter data. Reverse of combineGather
475  template <class Container>
476  static void mapCombineScatter
477  (
478  const List<commsStruct>& comms,
479  Container& Values
480  );
481 
482  //- Like above but switches between linear/tree communication
483  template <class Container>
484  static void mapCombineScatter(Container& Values);
485 
486 
487 
488  // Gather/scatter keeping the individual processor data separate.
489  // Values is a List of size Pstream::nProcs() where
490  // Values[Pstream::myProcNo()] is the data for the current processor.
491 
492  //- Gather data but keep individual values separate
493  template <class T>
494  static void gatherList
495  (
496  const List<commsStruct>& comms,
497  List<T>& Values
498  );
499 
500  //- Like above but switches between linear/tree communication
501  template <class T>
502  static void gatherList(List<T>& Values);
503 
504  //- Scatter data. Reverse of gatherList
505  template <class T>
506  static void scatterList
507  (
508  const List<commsStruct>& comms,
509  List<T>& Values
510  );
511 
512  //- Like above but switches between linear/tree communication
513  template <class T>
514  static void scatterList(List<T>& Values);
515 
516  // Friends
517 
518  friend void ::Foam::reduce(scalar& Value, const sumOp<scalar>& bop);
519  friend void ::Foam::PstreamImpl::initCommunicationSchedule();
520 
521 };
522 
523 
524 inline void Pstream::enlargeBuffer(size_t count)
525 {
526  buf_.setSize(max(int(buf_.size() + count), 2*buf_.size()));
527 }
528 
529 
531 
532 
533 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
534 
535 } // End namespace Foam
536 
537 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
538 
539 #ifdef NoRepository
540 # include <OpenFOAM/gatherScatter.C>
543 #endif
544 
545 
546 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
547 
548 #endif
549 
550 // ************************ vim: set sw=4 sts=4 et: ************************ //