UPstream.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2025 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 Class
28  Foam::UPstream
29 
30 Description
31  Inter-processor communications stream
32 
33 SourceFiles
34  UPstream.C
35  UPstream.txx
36  UPstreamCommsStruct.C
37 
38 \*---------------------------------------------------------------------------*/
39 
40 #ifndef Foam_UPstream_H
41 #define Foam_UPstream_H
42 
43 #include "wordList.H"
44 #include "labelList.H"
45 #include "DynamicList.H"
46 #include "HashTable.H"
47 #include "Map.H"
48 #include "Enum.H"
49 #include "ListOps.H"
50 
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 
53 namespace Foam
54 {
55 
56 //- Implementation details for UPstream/Pstream/MPI etc.
57 namespace PstreamDetail {}
58 
59 //- Interface handling for UPstream/Pstream/MPI etc.
60 namespace PstreamUtils {}
61 
62 /*---------------------------------------------------------------------------*\
63  Class UPstream Declaration
64 \*---------------------------------------------------------------------------*/
65 
66 class UPstream
67 {
68 public:
69 
70  //- Int ranges are used for MPI ranks (processes)
71  typedef IntRange<int> rangeType;
72 
73  //- Communications types
74  enum class commsTypes : char
75  {
76  buffered,
78  nonBlocking,
79  // Aliases
81  };
82 
83  //- Enumerated names for the communication types
84  static const Enum<commsTypes> commsTypeNames;
85 
86  //- Different MPI-send modes (ignored for commsTypes::buffered)
87  enum class sendModes : char
88  {
90  sync
91  };
92 
93  //- Mapping of some fundamental and aggregate types to MPI data types
94  enum class dataTypes : char
95  {
96  // NOTE: changes here require adjustment in
97  // PstreamGlobals, UPstreamTraits
98 
99  // Fundamental Types [10]:
100  Basic_begin,
102  type_int16,
104  type_int64,
105  type_uint16,
106  type_uint32,
107  type_uint64,
108  type_float,
109  type_double,
111 
115 
116  // User Types [6]:
118  type_3double,
119  type_6float,
120  type_6double,
121  type_9float,
122  type_9double,
123 
124  // Internal markers [1]
125  invalid,
129  };
130 
131  //- Mapping of some MPI op codes.
132  // Currently excluding min/max location until they are needed
133  enum class opCodes : char
134  {
135  // NOTE: changes here require adjustment in
136  // PstreamGlobals, UPstreamTraits
137 
138  Basic_begin,
139 
140  // Reduce or window operations [10]
141  op_min = Basic_begin,
142  op_max,
143  op_sum,
144  op_prod,
146  op_bool_or,
147  op_bool_xor,
148  op_bit_and,
149  op_bit_or,
150  op_bit_xor,
151 
155 
156  // Window-only operations [2]
158  op_no_op,
159 
160  // Internal markers [1]
161  invalid,
165  };
166 
167  //- Some bit masks corresponding to topology controls
168  // These selectively enable topology-aware handling
169  enum class topoControls : int
170  {
171  broadcast = 1,
172  reduce = 2,
173  gather = 4,
174  combine = 16,
175  mapGather = 32,
176  gatherList = 64,
177  };
178 
179 
180  // Public Classes
181 
182  //- Wrapper for OpenFOAM internal communicator index
183  class communicator; // Forward Declaration
185  //- Wrapper for MPI_Comm
186  class Communicator; // Forward Declaration
187 
188  //- Wrapper for MPI_Request
189  class Request; // Forward Declaration
190 
191  //- Wrapper for MPI_Win
192  class Window; // Forward Declaration
193 
194  //- Structure for communicating between processors
195  class commsStruct
196  {
197  // Private Data
198 
199  //- The procID of the processor \em directly above
200  int above_;
201 
202  //- The procIDs of processors \em directly below
203  List<int> below_;
204 
205  //- The procIDs of all processors below myProcNo,
206  //- not just directly below
207  List<int> allBelow_;
208 
209  //- The procIDs of all processors not below myProcNo
210  //- (inverse of allBelow_ without myProcNo)
211  List<int> allNotBelow_;
212 
213 
214  public:
215 
216  // Constructors
217 
218  //- Default construct with above == -1
219  commsStruct() noexcept : above_(-1) {}
221  //- Move construct from components
223  (
224  const int above,
225  List<int>&& below,
228  );
229 
230  //- Copy construct from below, allBelow components
232  (
233  const int numProcs,
234  const int myProcID,
235  const int above,
236  const UList<int>& below,
237  const UList<int>& allBelow
238  );
239 
240 
241  // Member Functions
242 
243  // Access
244 
245  //- The procID of the processor \em directly above
246  int above() const noexcept { return above_; }
247 
248  //- The procIDs of the processors \em directly below
249  const List<int>& below() const noexcept { return below_; }
250 
251  //- The procIDs of \em all processors below
252  //- (so not just directly below)
253  const List<int>& allBelow() const noexcept { return allBelow_; }
255  //- The procIDs of all processors not below myProcNo.
256  //- The inverse set of allBelow without myProcNo.
257  const List<int>& allNotBelow() const noexcept
258  {
259  return allNotBelow_;
260  }
261 
262  //- The number of processors addressed by the structure
263  int nProcs() const noexcept;
264 
265 
266  // Edit
267 
268  //- Reset to default constructed state
269  void reset();
270 
271  //- Reset to linear (flat) communication
272  void reset_linear
273  (
274  const int myProci,
275  const int numProcs
276  );
277 
278  //- Reset to tree selection (linear when very small),
279  //- possibly with communicator-specific adjustments
280  void reset
281  (
282  const int myProci,
283  const int numProcs,
284  const int communicator
285  );
286 
288  // Member / Friend Operators
289 
290  bool operator==(const commsStruct&) const;
291  bool operator!=(const commsStruct&) const;
293  friend Ostream& operator<<(Ostream&, const commsStruct&);
294  };
295 
296  //- Collection of communication structures
297  class commsStructList
298  {
299  // Private Data
300 
301  //- The communicator index
302  int comm_;
303 
304  //- Linear (flat) communication instead of tree communication
305  bool flat_;
306 
307  //- The communication tree
308  List<commsStruct> tree_;
309 
310  public:
311 
312  // Constructors
313 
314  //- Construct empty with invalid communicator
316  :
317  comm_(-1),
318  flat_(false)
319  {}
320 
321  //- Construct empty with given communicator
322  explicit commsStructList(int comm, bool flat=false) noexcept
323  :
324  comm_(comm),
325  flat_(flat)
326  {}
327 
328 
329  // Static Functions
330 
331  //- An empty structure. Used for placeholders etc.
332  static const commsStructList& null();
333 
334 
335  // Member Functions
336 
337  //- True if communicator is non-negative (ie, was assigned)
338  bool good() const noexcept { return (comm_ >= 0); }
339 
340  //- The communicator internal index
341  int comm() const noexcept { return comm_; }
342 
343  //- Linear (flat) communication instead of tree communication
344  bool linear() const noexcept { return flat_; }
345 
346  //- Change communication type (linear vs tree communication).
347  //- Resets existing structure.
348  void linear(bool on);
349 
350  //- Clear the list
351  void clear() { return tree_.clear(); }
352 
353  //- True if the list is empty
354  bool empty() const noexcept { return tree_.empty(); }
355 
356  //- The number of entries
357  label size() const noexcept { return tree_.size(); }
358 
359  //- Reset communicator index, fill tree with empty entries
360  void init(int communicator);
361 
362  //- Reset communicator index, fill tree with empty entries.
363  //- Specify flat vs tree communication.
364  void init(int communicator, bool flat);
365 
366  //- Reset communicator index, clear tree entries
367  void reset(int communicator);
368 
369  //- Reset communicator index, clear tree entries.
370  //- Specify flat vs tree communication.
371  void reset(int communicator, bool flat);
372 
373  //- Get existing or create (demand-driven) entry
374  const UPstream::commsStruct& get(int proci) const;
375 
376  //- Get existing or create (demand-driven) entry
377  const UPstream::commsStruct& operator[](int proci) const
378  {
379  return get(proci);
380  }
381 
382  //- Print un-directed graph in graphviz dot format
383  void printGraph(Ostream& os, int proci = 0) const;
384 
385  //- Write the communication tree
386  Ostream& writeList(Ostream& os) const
387  {
388  return tree_.writeList(os);
389  }
390 
391 
392  // Member / Friend Operators
393 
394  //- Write the communication tree
395  friend Ostream& operator<<
396  (
397  Ostream& os,
398  const commsStructList& rhs
399  )
400  {
401  return rhs.writeList(os);
402  }
403  };
404 
405 
406 private:
407 
408  // Private Data
410  //- Communications type of this stream
411  commsTypes commsType_;
412 
413 
414  // Private Static Data
415 
416  //- By default this is not a parallel run
417  static bool parRun_;
418 
419  //- Have support for threads?
420  static bool haveThreads_;
421 
422  //- Initial MPI_Comm_dup(MPI_COMM_WORLD,...) disabled? (default: false)
423  static bool noInitialCommDup_;
424 
425  //- Standard transfer message type
426  static int msgType_;
427 
428  //- Index to the world-communicator as defined at startup
429  //- (after any multi-world definitions).
430  //- Is unaffected by any later changes to worldComm.
431  static int constWorldComm_;
432 
433  //- Index to the inter-node communicator (between nodes),
434  //- defined based on constWorldComm_
435  static int commInterNode_;
436 
437  //- Index to the intra-host communicator (within a node),
438  //- defined based on constWorldComm_
439  static int commLocalNode_;
441  //- The number of shared/host nodes in the (const) world communicator.
442  static int numNodes_;
443 
444  //- Names of all worlds
445  static wordList allWorlds_;
446 
447  //- Per processor the world index (into allWorlds_)
448  static labelList worldIDs_;
449 
450 
451  // Communicator specific data
452 
453  //- My processor number
454  static DynamicList<int> myProcNo_;
455 
456  //- List of process IDs
457  static DynamicList<List<int>> procIDs_;
458 
459  //- Parent communicator
460  static DynamicList<label> parentComm_;
461 
462  //- Free communicators
463  static DynamicList<label> freeComms_;
464 
465  //- Linear communication schedule
466  static DynamicList<commsStructList> linearCommunication_;
467 
468  //- Multi level communication schedule
469  static DynamicList<commsStructList> treeCommunication_;
470 
471 
472  // Private Member Functions
473 
474  //- Set data for parallel running
475  static void setParRun(const int nProcs, const bool haveThreads);
476 
477  //- Initialise entries for new communicator.
478  //
479  // Resets corresponding entry in myProcNo_, procIDs_,
480  // linearCommunication_, treeCommunication_
481  // \return the communicator index
482  static label getAvailableCommIndex(const label parentIndex);
483 
484  //- Define inter-host/intra-host communicators (uses commConstWorld).
485  // Optionally specify a given number per node.
486  static bool setHostCommunicators(const int numPerNode = 0);
487 
488  //- Define inter-host/intra-host communicators based on
489  //- shared-memory information. Uses comm-world.
490  static bool setSharedMemoryCommunicators();
491 
492  //- Allocate MPI components of communicator with given index.
493  // This represents a "top-down" approach, creating a communicator
494  // based on the procIDs_ groupings.
495  //
496  // Modifies myProcNo_, reads and modifies procIDs_
497  static void allocateCommunicatorComponents
498  (
499  const label parentIndex,
500  const label index
501  );
502 
503  //- Allocate MPI components as duplicate of the parent communicator
504  //
505  // Modifies myProcNo_, procIDs_
506  static void dupCommunicatorComponents
507  (
508  const label parentIndex,
509  const label index
510  );
511 
512  //- Allocate MPI components for the given index by splitting
513  //- the parent communicator on the given \em colour.
514  // This represents a "bottom-up" approach, when the individual ranks
515  // only know which group they should belong to, but don't yet know
516  // which other ranks will be in their group.
517  //
518  // Modifies myProcNo_, procIDs_
519  static void splitCommunicatorComponents
520  (
521  const label parentIndex,
522  const label index,
523  const int colour,
525  const bool two_step = true
526  );
527 
528  //- Free MPI components of communicator.
529  // Does not touch the first two communicators (SELF, WORLD)
530  static void freeCommunicatorComponents(const label index);
531 
532 
533 protected:
534 
535  // Protected Member Functions
536 
537  // Static Functions
538 
539  //- Broadcast buffer contents from rank=0 to all ranks.
540  //- The sizes must match on all processes.
541  // For \b non-parallel : do nothing.
542  //
543  // \note The method uses a \c void pointer and the required data type
544  // (as per MPI). This means it should almost never be called directly
545  // but always via a compile-time checked caller.
546  // \return True on success
547  static bool mpi_broadcast
548  (
549  void* buf,
550  std::streamsize count,
551  const UPstream::dataTypes dataTypeId,
552  const int communicator
553  );
554 
555  //- In-place reduction of \c values with result on rank 0.
556  // Includes internal parallel guard and checks on data types, opcode.
557  //
558  // \note The method uses a \c void pointer and the required data type
559  // (as per MPI). This means it should almost never be called directly
560  // but always via a compile-time checked caller.
561  static void mpi_reduce
562  (
563  void* values,
564  int count,
565  const UPstream::dataTypes dataTypeId,
566  const UPstream::opCodes opCodeId,
567  const int communicator,
569  UPstream::Request* req = nullptr
570  );
571 
572  //- In-place reduction of \c values with same result on all ranks.
573  // Includes internal parallel guard and checks on data types, opcode.
574  //
575  // \note The method uses a \c void pointer and the required data type
576  // (as per MPI). This means it should almost never be called directly
577  // but always via a compile-time checked caller.
578  static void mpi_allreduce
579  (
580  void* values,
581  int count,
582  const UPstream::dataTypes dataTypeId,
583  const UPstream::opCodes opCodeId,
584  const int communicator,
586  UPstream::Request* req = nullptr
587  );
588 
589  //- Send buffer contents of specified data type to given processor.
590  //
591  // \note The method uses a \c void pointer and the required data type
592  // (as per MPI). This means it should almost never be called directly
593  // but always via a compile-time checked caller.
594  // \return True on success (or Fatal)
595  static bool mpi_send
596  (
598  const void* buf,
599  std::streamsize count,
600  const UPstream::dataTypes dataTypeId,
601  const int toProcNo,
602  const int tag, // eg, UPstream::msgType()
603  const int communicator, // eg, UPstream::worldComm
605  UPstream::Request* req = nullptr,
608  );
609 
610  //- Receive buffer contents of specified data type from given processor.
611  //
612  // \note The method uses a \c void pointer and the required data type
613  // (as per MPI). This means it should almost never be called directly
614  // but always via a compile-time checked caller.
615  // The commsType will be ignored if UPstream::Request is specified.
616  //
617  // \return number of elements read. May change in the future
618  static std::streamsize mpi_receive
619  (
621  void* buf,
622  std::streamsize count,
623  const UPstream::dataTypes dataTypeId,
624  const int fromProcNo,
625  const int tag, // eg, UPstream::msgType()
626  const int communicator, // eg, UPstream::worldComm
628  UPstream::Request* req = nullptr
629  );
630 
631  //- Receive identically-sized (contiguous) data from all ranks,
632  //- placing the result on rank 0.
633  // Includes internal parallel guard.
634  // For non-parallel, does not copy any data.
635  // If needed, this must be done by the caller.
636  static void mpi_gather
637  (
639  const void* sendData,
642  void* recvData,
644  int count,
645  const UPstream::dataTypes dataTypeId,
646  const int communicator,
648  UPstream::Request* req = nullptr
649  );
650 
651  //- Send identically-sized (contiguous) data from rank 0
652  //- to all other ranks.
653  // Includes internal parallel guard.
654  static void mpi_scatter
655  (
658  const void* sendData,
660  void* recvData,
662  int count,
663  const UPstream::dataTypes dataTypeId,
664  const int communicator,
666  UPstream::Request* req = nullptr
667  );
668 
669  //- Gather/scatter identically-sized data
670  // Send data from proc slot, receive into all slots
671  static void mpi_allgather
672  (
674  void* allData,
676  int count,
677  const UPstream::dataTypes dataTypeId,
678  const int communicator,
680  UPstream::Request* req = nullptr
681  );
682 
683  //- Receive variable length data from all ranks,
684  //- placing the result on rank 0.
685  //- (caution: known to scale poorly)
686  static void mpi_gatherv
687  (
688  const void* sendData,
689  int sendCount,
690  void* recvData,
691  const UList<int>& recvCounts,
692  const UList<int>& recvOffsets,
693  const UPstream::dataTypes dataTypeId,
694  const int communicator
695  );
696 
697  //- Send variable length data from rank 0 to all ranks.
698  //- (caution: known to scale poorly)
699  static void mpi_scatterv
700  (
701  const void* sendData,
702  const UList<int>& sendCounts,
703  const UList<int>& sendOffsets,
704  void* recvData,
705  int recvCount,
706  const UPstream::dataTypes dataTypeId,
707  const int communicator
708  );
709 
710 public:
711 
712  //- Declare name of the class and its debug switch
713  ClassName("UPstream");
714 
715 
716  // Static Data
717 
718  //- Use of host/node topology-aware routines
719  // 0: disabled
720  // 1: split by hostname [default]
721  // 2: split by shared
722  // >=4: (debug) split with given number per node
723  static int nodeCommsControl_;
724 
725  //- Minimum number of nodes before topology-aware routines are enabled
726  // <= 2 : always
727  // >= 3 : when there are more than N nodes
728  static int nodeCommsMin_;
729 
730  //- Selection of topology-aware routines as a bitmask combination
731  //- of the topoControls enumerations
732  static int topologyControl_;
733 
734  //- Test for selection of given topology-aware routine
736  {
737  return static_cast<bool>(topologyControl_ & int(ctrl));
738  }
739 
740  //- Should compact transfer be used in which floats replace doubles
741  //- reducing the bandwidth requirement at the expense of some loss
742  //- in accuracy
743  static bool floatTransfer;
744 
745  //- Number of processors to change from linear to tree communication
746  static int nProcsSimpleSum;
747 
748  //- Number of processors to change to nonBlocking consensual
749  //- exchange (NBX). Ignored for zero or negative values.
750  static int nProcsNonblockingExchange;
751 
752  //- Number of polling cycles in processor updates
753  static int nPollProcInterfaces;
754 
755  //- Default commsType
757 
758  //- Optional maximum message size (bytes)
759  static int maxCommsSize;
760 
761  //- Tuning parameters for non-blocking exchange (NBX)
762  static int tuning_NBX_;
763 
764  //- MPI buffer-size (bytes)
765  static const int mpiBufferSize;
766 
767 
768  // Standard Communicators
769 
770  //- Communicator for all ranks.
771  //- May differ from commGlobal() if local worlds are in use
772  static label worldComm;
773 
774  //- Debugging: warn for use of any communicator differing from warnComm
775  static label warnComm;
776 
777  //- Communicator for all ranks, irrespective of any local worlds.
778  // This value \em never changes during a simulation.
779  static constexpr int commGlobal() noexcept { return 0; }
780 
781  //- Communicator within the current rank only
782  // This value \em never changes during a simulation.
783  static constexpr int commSelf() noexcept { return 1; }
784 
785  //- Communicator for all ranks (respecting any local worlds).
786  // This value \em never changes after startup. Unlike the commWorld()
787  // which can be temporarily overriden.
788  static int commConstWorld() noexcept { return constWorldComm_; }
789 
790  //- Communicator for all ranks (respecting any local worlds)
791  static label commWorld() noexcept { return worldComm; }
792 
793  //- Set world communicator. Negative values are a no-op.
794  // \returns old world communicator index
795  static label commWorld(const label communicator) noexcept
796  {
797  label old(worldComm);
798  if (communicator >= 0) worldComm = communicator;
799  return old;
800  }
801 
802  //- Alter communicator debugging setting.
803  //- Warns for use of any communicator differing from specified.
804  //- Negative values disable.
805  // \returns the previous warn index
806  static label commWarn(const label communicator) noexcept
807  {
808  label old(warnComm);
809  warnComm = communicator;
810  return old;
811  }
812 
813  //- Number of currently defined communicators
814  static label nComms() noexcept { return parentComm_.size(); }
815 
816  //- Debugging: print the communication tree
817  static void printCommTree(int communicator, bool linear = false);
818 
819 
820  // Host Communicators
821 
822  //- Communicator between nodes/hosts (respects any local worlds)
823  static int commInterNode() noexcept
824  {
825  return (parRun_ ? commInterNode_ : constWorldComm_);
826  }
827 
828  //- Communicator within the node/host (respects any local worlds)
829  static int commLocalNode() noexcept
830  {
831  return (parRun_ ? commLocalNode_ : constWorldComm_);
832  }
833 
834  //- Both inter-node and local-node communicators have been created
835  static bool hasNodeCommunicators() noexcept
836  {
837  return
838  (
839  (commInterNode_ > constWorldComm_)
840  && (commLocalNode_ > constWorldComm_)
841  );
842  }
843 
844  //- True if node topology-aware routines have been enabled,
845  //- it is running in parallel, the starting point is the
846  //- world-communicator and it is not an odd corner case
847  //- (ie, all processes on one node, all processes on different nodes)
848  static bool usingNodeComms(const int communicator);
849 
850 
851  // Constructors
852 
853  //- Construct for given communication type
854  explicit UPstream(const commsTypes commsType) noexcept
855  :
856  commsType_(commsType)
857  {}
858 
859 
860  // Member Functions
861 
862  //- Create new communicator with sub-ranks on the parent communicator
863  static label newCommunicator
864  (
866  const label parent,
867 
869  const labelRange& subRanks,
870 
872  const bool withComponents = true
873  );
874 
875  //- Create new communicator with sub-ranks on the parent communicator
876  static label newCommunicator
877  (
879  const label parent,
880 
882  const labelUList& subRanks,
883 
885  const bool withComponents = true
886  );
887 
888  //- Duplicate the parent communicator
889  //
890  // Always calls dupCommunicatorComponents() internally
891  static label dupCommunicator
892  (
894  const label parent
895  );
896 
897  //- Allocate a new communicator by splitting the parent communicator
898  //- on the given \em colour.
899  // Always calls splitCommunicatorComponents() internally
900  static label splitCommunicator
901  (
903  const label parent,
904 
907  const int colour,
908 
910  const bool two_step = true
911  );
912 
913  //- Free a previously allocated communicator.
914  // Ignores placeholder (negative) communicators.
915  static void freeCommunicator
916  (
917  const label communicator,
918  const bool withComponents = true
919  );
920 
921  //- Return physical processor number (i.e. processor number in
922  //- worldComm) given communicator and processor
923  static int baseProcNo(label comm, int procID);
924 
925  //- Return processor number in communicator (given physical processor
926  //- number) (= reverse of baseProcNo)
927  static label procNo(const label comm, const int baseProcID);
928 
929  //- Return processor number in communicator (given processor number
930  //- and communicator)
931  static label procNo
932  (
933  const label comm,
934  const label currentComm,
935  const int currentProcID
936  );
937 
938  //- Add the valid option this type of communications library
939  //- adds/requires on the command line
940  static void addValidParOptions(HashTable<string>& validParOptions);
941 
942  //- Initialisation function called from main
943  // Spawns sub-processes and initialises inter-communication
944  static bool init(int& argc, char**& argv, const bool needsThread);
945 
946  //- Special purpose initialisation function.
947  // Performs a basic MPI_Init without any other setup.
948  // Only used for applications that need MPI communication when
949  // OpenFOAM is running in a non-parallel mode.
950  // \note Behaves as a no-op if MPI has already been initialized.
951  // Fatal if MPI has already been finalized.
952  static bool initNull();
954  //- Impose a synchronisation barrier (optionally non-blocking)
955  static void barrier
956  (
957  const int communicator,
958  UPstream::Request* req = nullptr
959  );
960 
961  //- Impose a point-to-point synchronisation barrier
962  //- by sending a zero-byte \em "done" message to given rank.
963  // A no-op for non-parallel
964  static void send_done
965  (
967  const int toProcNo,
969  const int communicator,
971  const int tag = UPstream::msgType()+1970
972  );
974  //- Impose a point-to-point synchronisation barrier
975  //- by receiving a zero-byte \em "done" message from given rank
976  // A no-op for non-parallel
977  // \returns the source rank (useful for ANY_SOURCE messages)
978  // or -1 for non-parallel
979  static int wait_done
980  (
982  const int fromProcNo,
984  const int communicator,
986  const int tag = UPstream::msgType()+1970
987  );
988 
989  //- Probe for an incoming message.
990  //
991  // \param commsType Non-blocking or not
992  // \param fromProcNo The source rank (negative == ANY_SOURCE)
993  // \param tag The source message tag
994  // \param communicator The communicator index
995  //
996  // \returns source rank and message size (bytes)
997  // and (-1, 0) on failure
998  static std::pair<int,int64_t> probeMessage
999  (
1001  const int fromProcNo,
1002  const int tag = UPstream::msgType(),
1003  const int communicator = worldComm
1004  );
1005 
1007  // Information
1008 
1009  //- Report the node-communication settings
1010  static void printNodeCommsControl(Ostream& os);
1011 
1012  //- Report the topology routines settings
1013  static void printTopoControl(Ostream& os);
1015 
1016  // Requests (non-blocking comms).
1017  // Pending requests are usually handled as an internal (global) list,
1018  // since this simplifies the overall tracking and provides a convenient
1019  // wrapping to avoid exposing MPI-specific types, but can also handle
1020  // with a wrapped UPstream::Request as well.
1021 
1022  //- Number of outstanding requests (on the internal list of requests)
1023  static label nRequests() noexcept;
1024 
1025  //- Truncate outstanding requests to given length, which is
1026  //- expected to be in the range [0 to nRequests()].
1027  // A no-op for out-of-range values.
1028  static void resetRequests(const label n);
1029 
1030  //- Transfer the (wrapped) MPI request to the internal global list
1031  //- and invalidate the parameter (ignores null requests)
1032  // A no-op for non-parallel
1033  static void addRequest(UPstream::Request& req);
1034 
1035  //- Non-blocking comms: cancel and free outstanding request.
1036  //- Corresponds to MPI_Cancel() + MPI_Request_free()
1037  // A no-op if parRun() == false
1038  // if there are no pending requests,
1039  // or if the index is out-of-range (0 to nRequests)
1040  static void cancelRequest(const label i);
1041 
1042  //- Non-blocking comms: cancel and free outstanding request.
1043  //- Corresponds to MPI_Cancel() + MPI_Request_free()
1044  // A no-op for non-parallel
1045  static void cancelRequest(UPstream::Request& req);
1046 
1047  //- Non-blocking comms: cancel and free outstanding requests.
1048  //- Corresponds to MPI_Cancel() + MPI_Request_free()
1049  // A no-op if parRun() == false or list is empty
1050  static void cancelRequests(UList<UPstream::Request>& requests);
1051 
1052  //- Non-blocking comms: cancel/free outstanding requests
1053  //- (from position onwards) and remove from internal list of requests.
1054  //- Corresponds to MPI_Cancel() + MPI_Request_free()
1055  // A no-op if parRun() == false,
1056  // if the position is out-of-range [0 to nRequests()],
1057  // or the internal list of requests is empty.
1058  //
1059  // \param pos starting position within the internal list of requests
1060  // \param len length of slice to remove (negative = until the end)
1061  static void removeRequests(const label pos, label len = -1);
1062 
1063  //- Non-blocking comms: free outstanding request.
1064  //- Corresponds to MPI_Request_free()
1065  // A no-op if parRun() == false
1066  static void freeRequest(UPstream::Request& req);
1067 
1068  //- Non-blocking comms: free outstanding requests.
1069  //- Corresponds to MPI_Request_free()
1070  // A no-op if parRun() == false or list is empty
1071  static void freeRequests(UList<UPstream::Request>& requests);
1072 
1073  //- Wait until all requests (from position onwards) have finished.
1074  //- Corresponds to MPI_Waitall()
1075  // A no-op if parRun() == false,
1076  // if the position is out-of-range [0 to nRequests()],
1077  // or the internal list of requests is empty.
1078  //
1079  // If checking a trailing portion of the list, it will also trim
1080  // the list of outstanding requests as a side-effect.
1081  // This is a feature (not a bug) to conveniently manange the list.
1082  //
1083  // \param pos starting position within the internal list of requests
1084  // \param len length of slice to check (negative = until the end)
1085  static void waitRequests(const label pos, label len = -1);
1086 
1087  //- Wait until all requests have finished.
1088  //- Corresponds to MPI_Waitall()
1089  // A no-op if parRun() == false, or the list is empty.
1090  static void waitRequests(UList<UPstream::Request>& requests);
1091 
1092  //- Wait until any request (from position onwards) has finished.
1093  //- Corresponds to MPI_Waitany()
1094  // A no-op and returns false if parRun() == false,
1095  // if the position is out-of-range [0 to nRequests()],
1096  // or the internal list of requests is empty.
1097  //
1098  // \returns true if any pending request completed.
1099  // \returns false if all requests have already been handled.
1100  //
1101  // \param pos starting position within the internal list of requests
1102  // \param len length of slice to check (negative = until the end)
1103  static bool waitAnyRequest(const label pos, label len = -1);
1104 
1105  //- Wait until some requests (from position onwards) have finished.
1106  //- Corresponds to MPI_Waitsome()
1107  // A no-op and returns false if parRun() == false,
1108  // if the position is out-of-range [0 to nRequests],
1109  // or the internal list of requests is empty.
1110  //
1111  // \returns true if some pending requests completed.
1112  // \returns false if all requests have already been handled
1113  //
1114  // \param pos starting position within the internal list of requests
1115  // \param len length of slice to check (negative = until the end)
1116  // \param[out] indices the completed request indices relative to the
1117  // starting position. This is an optional parameter that can be
1118  // used to recover the indices or simply to avoid reallocations
1119  // when calling within a loop.
1120  static bool waitSomeRequests
1121  (
1122  const label pos,
1123  label len = -1,
1124  DynamicList<int>* indices = nullptr
1125  );
1126 
1127  //- Wait until some requests have finished.
1128  //- Corresponds to MPI_Waitsome()
1129  // A no-op and returns false if parRun() == false,
1130  // the list is empty,
1131  // or if all the requests have already been handled.
1132  //
1133  // \param requests the requests
1134  // \param[out] indices the completed request indices relative to the
1135  // starting position. This is an optional parameter that can be
1136  // used to recover the indices or simply to avoid reallocations
1137  // when calling within a loop.
1138  static bool waitSomeRequests
1139  (
1140  UList<UPstream::Request>& requests,
1141  DynamicList<int>* indices = nullptr
1142  );
1143 
1144  //- Wait until any request has finished and return its index.
1145  //- Corresponds to MPI_Waitany()
1146  // Returns -1 if parRun() == false, or the list is empty,
1147  // or if all the requests have already been handled
1148  static label waitAnyRequest(UList<UPstream::Request>& requests);
1149 
1150  //- Wait until request i has finished.
1151  //- Corresponds to MPI_Wait()
1152  // A no-op if parRun() == false,
1153  // if there are no pending requests,
1154  // or if the index is out-of-range (0 to nRequests)
1155  static void waitRequest(const label i);
1156 
1157  //- Wait until specified request has finished.
1158  //- Corresponds to MPI_Wait()
1159  // A no-op if parRun() == false or for a null-request
1160  static void waitRequest(UPstream::Request& req);
1161 
1162  //- Non-blocking comms: has request i finished?
1163  //- Corresponds to MPI_Test()
1164  // A no-op and returns true if parRun() == false,
1165  // if there are no pending requests,
1166  // or if the index is out-of-range (0 to nRequests)
1167  static bool finishedRequest(const label i);
1168 
1169  //- Non-blocking comms: has request finished?
1170  //- Corresponds to MPI_Test()
1171  // A no-op and returns true if parRun() == false
1172  // or for a null-request
1173  static bool finishedRequest(UPstream::Request& req);
1174 
1175  //- Non-blocking comms: have all requests (from position onwards)
1176  //- finished?
1177  //- Corresponds to MPI_Testall()
1178  // A no-op and returns true if parRun() == false,
1179  // if there are no pending requests,
1180  // or if the index is out-of-range (0 to nRequests)
1181  // or the addressed range is empty etc.
1182  //
1183  // \param pos starting position within the internal list of requests
1184  // \param len length of slice to check (negative = until the end)
1185  static bool finishedRequests(const label pos, label len = -1);
1186 
1187  //- Non-blocking comms: have all requests finished?
1188  //- Corresponds to MPI_Testall()
1189  // A no-op and returns true if parRun() == false or list is empty
1190  static bool finishedRequests(UList<UPstream::Request>& requests);
1191 
1192  //- Non-blocking comms: have both requests finished?
1193  //- Corresponds to pair of MPI_Test()
1194  // A no-op and returns true if parRun() == false,
1195  // if there are no pending requests,
1196  // or if the indices are out-of-range (0 to nRequests)
1197  // Each finished request parameter is set to -1 (ie, done).
1198  static bool finishedRequestPair(label& req0, label& req1);
1199 
1200  //- Non-blocking comms: wait for both requests to finish.
1201  //- Corresponds to pair of MPI_Wait()
1202  // A no-op if parRun() == false,
1203  // if there are no pending requests,
1204  // or if the indices are out-of-range (0 to nRequests)
1205  // Each finished request parameter is set to -1 (ie, done).
1206  static void waitRequestPair(label& req0, label& req1);
1207 
1208 
1209  // General
1210 
1211  //- Set as parallel run on/off.
1212  // \return the previous value
1213  static bool parRun(const bool on) noexcept
1214  {
1215  bool old(parRun_);
1216  parRun_ = on;
1217  return old;
1218  }
1219 
1220  //- Test if this a parallel run
1221  // Modify access is deprecated
1222  static bool& parRun() noexcept { return parRun_; }
1223 
1224  //- Have support for threads
1225  static bool haveThreads() noexcept { return haveThreads_; }
1226 
1227  //- Relative rank for the master process - is always 0.
1228  static constexpr int masterNo() noexcept { return 0; }
1229 
1230  //- Number of ranks in parallel run (for given communicator).
1231  //- It is 1 for serial run
1232  static label nProcs(const label communicator = worldComm)
1233  {
1234  return procIDs_[communicator].size();
1235  }
1236 
1237  //- Rank of this process in the communicator (starting from masterNo()).
1238  //- Negative if the process is not a rank in the communicator.
1239  static int myProcNo(const label communicator = worldComm)
1240  {
1241  return myProcNo_[communicator];
1242  }
1243 
1244  //- True if process corresponds to the master rank in the communicator
1245  static bool master(const label communicator = worldComm)
1246  {
1247  return myProcNo_[communicator] == masterNo();
1248  }
1249 
1250  //- True if process corresponds to \b any rank (master or sub-rank)
1251  //- in the given communicator
1252  static bool is_rank(const label communicator = worldComm)
1253  {
1254  return myProcNo_[communicator] >= masterNo();
1255  }
1256 
1257  //- True if process corresponds to a sub-rank in the given communicator
1258  static bool is_subrank(const label communicator = worldComm)
1259  {
1260  return myProcNo_[communicator] > masterNo();
1261  }
1262 
1263  //- True if parallel algorithm or exchange is required.
1264  // This is when parRun() == true, the process corresponds to a rank
1265  // in the communicator and there is more than one rank in the
1266  // communicator
1267  static bool is_parallel(const label communicator = worldComm)
1268  {
1269  return
1270  (
1271  parRun_ && is_rank(communicator) && nProcs(communicator) > 1
1272  );
1273  }
1274 
1275  //- The number of shared/host nodes in the (const) world communicator.
1276  static int numNodes() noexcept { return numNodes_; }
1277 
1278  //- The parent communicator
1279  static label parent(int communicator)
1280  {
1281  return parentComm_(communicator);
1282  }
1283 
1284  //- The list of ranks within a given communicator
1285  static List<int>& procID(int communicator)
1286  {
1287  return procIDs_[communicator];
1288  }
1289 
1290 
1291  // Worlds
1292 
1293  //- All worlds
1294  static const wordList& allWorlds() noexcept
1295  {
1296  return allWorlds_;
1297  }
1298 
1299  //- The indices into allWorlds for all processes
1300  static const labelList& worldIDs() noexcept
1301  {
1302  return worldIDs_;
1303  }
1304 
1305  //- My worldID
1306  static label myWorldID()
1307  {
1308  return worldIDs_[myProcNo(UPstream::commGlobal())];
1309  }
1310 
1311  //- My world
1312  static const word& myWorld()
1313  {
1314  return allWorlds_[worldIDs_[myProcNo(UPstream::commGlobal())]];
1315  }
1316 
1317 
1318  // Rank addressing
1319 
1320  //- Range of process indices for all processes
1321  static rangeType allProcs(const label communicator = worldComm)
1322  {
1323  // Proc 0 -> nProcs (int value)
1324  return rangeType(static_cast<int>(nProcs(communicator)));
1325  }
1326 
1327  //- Range of process indices for sub-processes
1328  static rangeType subProcs(const label communicator = worldComm)
1329  {
1330  // Proc 1 -> nProcs (int value)
1331  return rangeType(1, static_cast<int>(nProcs(communicator)-1));
1332  }
1333 
1334  //- Processor offsets corresponding to the inter-node communicator
1335  static const List<int>& interNode_offsets();
1336 
1337  //- The range (start/size) of the commLocalNode ranks in terms of the
1338  //- (const) world communicator processors.
1339  static const rangeType& localNode_parentProcs();
1340 
1341  //- Linear communication schedule (special case) for given communicator
1342  static const commsStructList& linearCommunication(int communicator);
1343 
1344  //- Tree communication schedule (standard case) for given communicator
1345  static const commsStructList& treeCommunication(int communicator);
1346 
1347  //- Communication schedule for all-to-master (proc 0) as
1348  //- linear/tree/none with switching based on UPstream::nProcsSimpleSum,
1349  //- the is_parallel() state and the optional \c linear parameter.
1350  static const commsStructList& whichCommunication
1351  (
1352  const int communicator,
1354  bool linear = false
1355  )
1356  {
1357  const label np
1358  (
1359  parRun_ && is_rank(communicator) // cf. is_parallel()
1360  ? nProcs(communicator)
1361  : label(0)
1362  );
1363 
1364  return
1365  (
1366  np <= 1
1368  : (linear || np < UPstream::nProcsSimpleSum)
1369  ? linearCommunication(communicator)
1370  : treeCommunication(communicator)
1371  );
1372  }
1373 
1374 
1375  //- Message tag of standard messages
1376  static int& msgType() noexcept
1377  {
1378  return msgType_;
1379  }
1380 
1381  //- Set the message tag for standard messages
1382  // \return the previous value
1383  static int msgType(int val) noexcept
1384  {
1385  int old(msgType_);
1386  msgType_ = val;
1387  return old;
1388  }
1389 
1390  //- Increment the message tag for standard messages
1391  // \return the previous value
1392  static int incrMsgType(int val = 1) noexcept
1393  {
1394  int old(msgType_);
1395  msgType_ += val;
1396  return old;
1397  }
1398 
1399  //- Get the communications type of the stream
1400  commsTypes commsType() const noexcept
1401  {
1402  return commsType_;
1403  }
1404 
1405  //- Set the communications type of the stream
1406  // \return the previous value
1408  {
1409  commsTypes old(commsType_);
1410  commsType_ = ct;
1411  return old;
1412  }
1413 
1414 
1415  //- Shutdown (finalize) MPI as required.
1416  // Uses MPI_Abort instead of MPI_Finalize if errNo is non-zero
1417  static void shutdown(int errNo = 0);
1418 
1419  //- Call MPI_Abort with no other checks or cleanup
1420  static void abort(int errNo = 1);
1421 
1422  //- Shutdown (finalize) MPI as required and exit program with errNo.
1423  static void exit(int errNo = 1);
1424 
1425 
1426  #undef Pstream_CommonRoutines
1427  #define Pstream_CommonRoutines(Type) \
1428  \
1429  \
1430  \
1431  static void allToAll \
1432  ( \
1433  \
1434  const UList<Type>& sendData, \
1435  \
1436  UList<Type>& recvData, \
1437  const int communicator = UPstream::worldComm \
1438  ); \
1439  \
1440  \
1441  \
1442  \
1443  \
1444  \
1445  \
1446  \
1447  \
1448  static void allToAllConsensus \
1449  ( \
1450  \
1451  const UList<Type>& sendData, \
1452  \
1453  UList<Type>& recvData, \
1454  \
1455  const int tag, \
1456  const int communicator = UPstream::worldComm \
1457  ); \
1458  \
1459  \
1460  \
1461  \
1462  \
1463  \
1464  static void allToAllConsensus \
1465  ( \
1466  \
1467  const Map<Type>& sendData, \
1468  \
1469  Map<Type>& recvData, \
1470  \
1471  const int tag, \
1472  const int communicator = UPstream::worldComm \
1473  ); \
1474  \
1475  \
1476  \
1477  static Map<Type> allToAllConsensus \
1478  ( \
1479  \
1480  const Map<Type>& sendData, \
1481  \
1482  const int tag, \
1483  const int communicator = UPstream::worldComm \
1484  ) \
1485  { \
1486  Map<Type> recvData; \
1487  allToAllConsensus(sendData, recvData, tag, communicator); \
1488  return recvData; \
1489  }
1490 
1491  Pstream_CommonRoutines(int32_t);
1492  Pstream_CommonRoutines(int64_t);
1493 
1494  #undef Pstream_CommonRoutines
1495 
1496 
1497  // Low-level gather/scatter routines
1498 
1499  //- Receive identically-sized (contiguous) data from all ranks
1500  template<class Type>
1501  static void mpiGather
1502  (
1504  const Type* sendData,
1507  Type* recvData,
1509  int count,
1510  const int communicator = UPstream::worldComm
1511  );
1512 
1513  //- Send identically-sized (contiguous) data to all ranks
1514  template<class Type>
1515  static void mpiScatter
1516  (
1519  const Type* sendData,
1521  Type* recvData,
1523  int count,
1524  const int communicator = UPstream::worldComm
1525  );
1526 
1527  //- Gather/scatter identically-sized data
1528  // Send data from proc slot, receive into all slots
1529  template<class Type>
1530  static void mpiAllGather
1531  (
1533  Type* allData,
1535  int count,
1536  const int communicator = UPstream::worldComm
1537  );
1538 
1539  //- Receive variable length data from all ranks
1540  template<class Type>
1541  static void mpiGatherv
1542  (
1543  const Type* sendData,
1544  int sendCount,
1545  Type* recvData,
1546  const UList<int>& recvCounts,
1547  const UList<int>& recvOffsets,
1548  const int communicator = UPstream::worldComm
1549  );
1550 
1551  //- Send variable length data to all ranks
1552  template<class Type>
1553  static void mpiScatterv
1554  (
1555  const Type* sendData,
1556  const UList<int>& sendCounts,
1557  const UList<int>& sendOffsets,
1558  Type* recvData,
1559  int recvCount,
1560  const int communicator = UPstream::worldComm
1561  );
1562 
1563 
1564  // Gather single, contiguous value(s)
1565 
1566  //- Allgather individual values into list locations.
1567  // The returned list has size nProcs, identical on all ranks.
1568  template<class T>
1569  static List<T> allGatherValues
1570  (
1571  const T& localValue,
1572  const int communicator = UPstream::worldComm
1573  );
1575  //- Gather individual values into list locations.
1576  // On master list length == nProcs, otherwise zero length.
1577  // \n
1578  // For \b non-parallel :
1579  // the returned list length is 1 with localValue.
1580  template<class T>
1581  static List<T> listGatherValues
1582  (
1583  const T& localValue,
1584  const int communicator = UPstream::worldComm
1585  );
1587  //- Scatter individual values from list locations.
1588  // On master input list length == nProcs, ignored on other procs.
1589  // \n
1590  // For \b non-parallel :
1591  // returns the first list element (or default initialized).
1592  template<class T>
1593  static T listScatterValues
1594  (
1595  const UList<T>& allValues,
1597  );
1598 
1599 
1600  // Broadcast Functions
1601 
1602  //- Broadcast buffer contents (contiguous types), from rank=0
1603  //- to all ranks. The sizes must match on all processes.
1604  // For \b non-parallel : do nothing.
1605  // \return True on success
1606  template<class Type>
1607  inline static bool broadcast
1608  (
1609  Type* buffer,
1610  std::streamsize count,
1611  const int communicator
1612  );
1613 
1614 
1615  // Reductions
1616 
1617  //- MPI_Reduce (blocking) for known operators
1618  // For \b non-parallel : do nothing.
1619  template<class T>
1620  static void mpiReduce
1621  (
1622  T values[],
1623  int count,
1624  const UPstream::opCodes opCodeId,
1625  const int communicator
1626  );
1627 
1628  //- MPI_Allreduce (blocking) for known operators
1629  // For \b non-parallel : do nothing.
1630  template<class T>
1631  static void mpiAllReduce
1632  (
1633  T values[],
1634  int count,
1635  const UPstream::opCodes opCodeId,
1636  const int communicator
1637  );
1638 
1639  //- MPI_Iallreduce (non-blocking) for known operators
1640  // For \b non-parallel : do nothing.
1641  template<class T>
1642  static void mpiAllReduce
1643  (
1644  T values[],
1645  int count,
1646  const UPstream::opCodes opCodeId,
1647  const int communicator,
1649  );
1650 
1651 
1652  // Logical reductions
1653 
1654  //- Logical (and) reduction (MPI_AllReduce)
1655  // For \b non-parallel : do nothing
1656  static void reduceAnd
1657  (
1658  bool& value,
1660  );
1661 
1662  //- Logical (or) reduction (MPI_AllReduce)
1663  // For \b non-parallel : do nothing
1664  static void reduceOr
1665  (
1666  bool& value,
1667  const int communicator = worldComm
1668  );
1669 
1670 
1671  // Housekeeping
1673  //- Create new communicator with sub-ranks on the parent communicator
1674  // \deprecated(2025-02)
1675  static label allocateCommunicator
1676  (
1677  const label parent,
1678  const labelRange& subRanks,
1679  const bool withComponents = true
1680  )
1681  {
1682  return newCommunicator(parent, subRanks, withComponents);
1683  }
1684 
1685  //- Create new communicator with sub-ranks on the parent communicator
1686  // \deprecated(2025-02)
1687  static label allocateCommunicator
1688  (
1689  const label parent,
1690  const labelUList& subRanks,
1691  const bool withComponents = true
1692  )
1693  {
1694  return newCommunicator(parent, subRanks, withComponents);
1695  }
1696 
1697  //- Communicator between nodes (respects any local worlds)
1698  FOAM_DEPRECATED_FOR(2025-02, "commInterNode()")
1699  static label commInterHost() noexcept { return commInterNode(); }
1700 
1701  //- Communicator within the node (respects any local worlds)
1702  FOAM_DEPRECATED_FOR(2025-02, "commLocalNode()")
1703  static label commIntraHost() noexcept { return commLocalNode(); }
1704 
1705  //- Wait for all requests to finish.
1706  // \deprecated(2023-01) Probably not what you want.
1707  // Should normally be restricted to a particular starting request.
1708  FOAM_DEPRECATED_FOR(2023-01, "waitRequests(int) method")
1709  static void waitRequests() { waitRequests(0); }
1710 
1711  //- \deprecated(2025-02) prefer mpiGatherv
1712  template<class Type>
1713  FOAM_DEPRECATED_FOR(2025-02, "mpiGatherv()")
1714  static void gather
1715  (
1716  const Type* send,
1717  int count,
1718  Type* recv,
1719  const UList<int>& counts,
1720  const UList<int>& offsets,
1721  const int comm = UPstream::worldComm
1722  )
1723  {
1724  UPstream::mpiGatherv(send, count, recv, counts, offsets, comm);
1725  }
1726 
1727  //- \deprecated(2025-02) prefer mpiScatterv
1728  template<class Type>
1729  FOAM_DEPRECATED_FOR(2025-02, "mpiScatterv()")
1730  static void scatter
1731  (
1732  const Type* send,
1733  const UList<int>& counts,
1734  const UList<int>& offsets,
1735  Type* recv,
1736  int count,
1737  const int comm = UPstream::worldComm
1738  )
1739  {
1740  UPstream::mpiScatterv(send, counts, offsets, recv, count, comm);
1741  }
1742 };
1743 
1744 /*---------------------------------------------------------------------------*\
1745  Class UPstream::communicator Declaration
1746 \*---------------------------------------------------------------------------*/
1747 
1748 //- Wrapper for internally indexed communicator label.
1749 //- Always invokes UPstream::allocateCommunicatorComponents()
1750 //- and UPstream::freeCommunicatorComponents()
1751 class UPstream::communicator
1752 {
1753  // Private Data
1754 
1755  //- The communicator label
1756  label comm_;
1757 
1758 public:
1759 
1760  // Generated Methods
1761 
1762  //- No copy construct
1763  communicator(const communicator&) = delete;
1764 
1765  //- No copy assignment
1766  void operator=(const communicator&) = delete;
1767 
1768 
1769  // Constructors
1770 
1771  //- Default construct (a placeholder communicator)
1772  communicator() noexcept : comm_(-1) {}
1773 
1774  //- Move construct, takes ownership
1775  communicator(communicator&& c) : comm_(c.comm_) { c.comm_ = -1; }
1776 
1777  //- Allocate communicator for contiguous sub-ranks on given parent
1778  communicator
1779  (
1781  const label parentComm,
1783  const labelRange& subRanks
1784  )
1785  :
1786  comm_(UPstream::newCommunicator(parentComm, subRanks))
1787  {}
1788 
1789  //- Allocate communicator for sub-ranks on given parent
1790  communicator
1791  (
1793  const label parentComm,
1795  const labelUList& subRanks
1796  )
1797  :
1798  comm_(UPstream::newCommunicator(parentComm, subRanks))
1799  {}
1800 
1801 
1802  // Destructor
1803 
1804  //- Free allocated communicator
1805  ~communicator() { UPstream::freeCommunicator(comm_); }
1806 
1807 
1808  // Factory Methods
1810  //- Duplicate the given communicator
1811  static communicator duplicate(const label parentComm)
1812  {
1813  communicator c;
1814  c.comm_ = UPstream::dupCommunicator(parentComm);
1815  return c;
1816  }
1817 
1818  //- Factory Method :
1819  //- Split the communicator on the given \em colour.
1820  static communicator split
1821  (
1823  const label parentComm,
1826  const int colour,
1828  const bool two_step = true
1829  )
1830  {
1831  communicator c;
1832  c.comm_ = UPstream::splitCommunicator(parentComm, colour, two_step);
1833  return c;
1834  }
1835 
1836 
1837  // Member Functions
1838 
1839  //- True if communicator is non-negative (ie, was allocated)
1840  bool good() const noexcept { return (comm_ >= 0); }
1841 
1842  //- The communicator label
1843  label comm() const noexcept { return comm_; }
1844 
1845  //- Return non-const reference to this
1846  communicator& constCast() const noexcept
1847  {
1848  return const_cast<communicator&>(*this);
1849  }
1850 
1851  //- Release ownership of the communicator, return old value.
1852  // Leave further management to the caller
1853  label release() noexcept { label c(comm_); comm_ = -1; return c; }
1854 
1855  //- Free allocated communicator
1856  void reset() { UPstream::freeCommunicator(comm_); comm_ = -1; }
1857 
1858  //- Allocate with contiguous sub-ranks of parent communicator
1859  void reset(label parent, const labelRange& subRanks)
1860  {
1862  comm_ = UPstream::newCommunicator(parent, subRanks);
1863  }
1864 
1865  //- Allocate with sub-ranks of parent communicator
1866  void reset(label parent, const labelUList& subRanks)
1867  {
1869  comm_ = UPstream::newCommunicator(parent, subRanks);
1870  }
1871 
1872  //- Take ownership, free managed communicator
1873  void reset(communicator&& c)
1874  {
1875  if (this == &c) return; // No self-assignment
1876  if (comm_ != c.comm_) UPstream::freeCommunicator(comm_);
1877  comm_ = c.comm_;
1878  c.comm_ = -1;
1879  }
1880 
1881  //- Swap communicator labels
1882  void swap(communicator& c) { std::swap(comm_, c.comm_); }
1883 
1884 
1885  // Member Operators
1886 
1887  //- Implicit cast to label - the same as comm()
1888  operator label() const noexcept { return comm_; }
1889 
1890  //- Move assignment, takes ownership
1891  void operator=(communicator&& c) { reset(std::move(c)); }
1892 
1893  //- Test for equality
1894  bool operator==(const communicator& c) const noexcept
1895  {
1896  return (comm_ == c.comm_);
1897  }
1898 
1899  //- Test for inequality
1900  bool operator!=(const communicator& c) const noexcept
1901  {
1902  return (comm_ != c.comm_);
1903  }
1904 };
1905 
1906 
1907 /*---------------------------------------------------------------------------*\
1908  Class UPstream::Communicator Declaration
1909 \*---------------------------------------------------------------------------*/
1910 
1911 //- An opaque wrapper for MPI_Comm with a vendor-independent
1912 //- representation without any \c <mpi.h> header.
1913 // The MPI standard states that MPI_Comm is always an opaque object.
1914 // Generally it is either an integer (eg, mpich) or a pointer (eg, openmpi).
1915 class UPstream::Communicator
1916 {
1917 public:
1918 
1919  // Public Types
1921  //- Storage for MPI_Comm (as integer or pointer)
1922  typedef std::intptr_t value_type;
1923 
1924 
1925 private:
1926 
1927  // Private Data
1928 
1929  //- The MPI_Comm (as wrapped value)
1930  value_type value_;
1931 
1932 public:
1933 
1934  // Generated Methods
1935 
1936  //- Copy construct
1937  Communicator(const Communicator&) noexcept = default;
1938 
1939  //- Move construct
1940  Communicator(Communicator&&) noexcept = default;
1941 
1942  //- Copy assignment
1943  Communicator& operator=(const Communicator&) noexcept = default;
1944 
1945  //- Move assignment
1946  Communicator& operator=(Communicator&&) noexcept = default;
1947 
1948 
1949  // Member Operators
1950 
1951  //- Test for equality
1952  bool operator==(const Communicator& rhs) const noexcept
1953  {
1954  return (value_ == rhs.value_);
1955  }
1956 
1957  //- Test for inequality
1958  bool operator!=(const Communicator& rhs) const noexcept
1959  {
1960  return (value_ != rhs.value_);
1961  }
1962 
1963 
1964  // Constructors
1965 
1966  //- Default construct as MPI_COMM_NULL
1967  Communicator() noexcept;
1968 
1969  //- Construct from MPI_Comm (as pointer type)
1970  explicit Communicator(const void* p) noexcept
1971  :
1972  value_(reinterpret_cast<value_type>(p))
1973  {}
1974 
1975  //- Construct from MPI_Comm (as integer type)
1976  explicit Communicator(value_type val) noexcept
1977  :
1978  value_(val)
1979  {}
1980 
1981 
1982  // Factory Methods
1983 
1984  //- Transcribe internally indexed communicator to wrapped value.
1985  // Example,
1986  // \code
1987  // PstreamUtils::Cast::to_mpi
1988  // (
1989  // UPstream::Communicator::lookup(UPstream::commWorld())
1990  // )
1991  // \endcode
1992  static Communicator lookup(const int comm);
1993 
1994 
1995  // Member Functions
1996 
1997  //- Return raw value
1998  value_type value() const noexcept { return value_; }
1999 
2000  //- Return as pointer value
2001  const void* pointer() const noexcept
2002  {
2003  return reinterpret_cast<const void*>(value_);
2004  }
2005 
2006  //- True if not equal to MPI_COMM_NULL
2007  bool good() const noexcept;
2008 
2009  //- Reset to default constructed value (MPI_COMM_NULL)
2010  void reset() noexcept;
2011 
2012  //- The number of ranks associated with the communicator
2013  int size() const;
2014 };
2015 
2016 
2017 /*---------------------------------------------------------------------------*\
2018  Class UPstream::Request Declaration
2019 \*---------------------------------------------------------------------------*/
2020 
2021 //- An opaque wrapper for MPI_Request with a vendor-independent
2022 //- representation without any \c <mpi.h> header.
2023 // The MPI standard states that MPI_Request is always an opaque object.
2024 // Generally it is either an integer (eg, mpich) or a pointer (eg, openmpi).
2025 class UPstream::Request
2026 {
2027 public:
2028 
2029  // Public Types
2030 
2031  //- Storage for MPI_Request (as integer or pointer)
2032  typedef std::intptr_t value_type;
2033 
2034 
2035 private:
2036 
2037  // Private Data
2038 
2039  //- The MPI_Request (as wrapped value)
2040  value_type value_;
2041 
2042 public:
2043 
2044  // Generated Methods
2045 
2046  //- Copy construct
2047  Request(const Request&) noexcept = default;
2048 
2049  //- Move construct
2050  Request(Request&&) noexcept = default;
2051 
2052  //- Copy assignment
2053  Request& operator=(const Request&) noexcept = default;
2054 
2055  //- Move assignment
2056  Request& operator=(Request&&) noexcept = default;
2057 
2058 
2059  // Member Operators
2060 
2061  //- Test for equality
2062  bool operator==(const Request& rhs) const noexcept
2063  {
2064  return (value_ == rhs.value_);
2065  }
2066 
2067  //- Test for inequality
2068  bool operator!=(const Request& rhs) const noexcept
2069  {
2070  return (value_ != rhs.value_);
2071  }
2072 
2073 
2074  // Constructors
2075 
2076  //- Default construct as MPI_REQUEST_NULL
2077  Request() noexcept;
2078 
2079  //- Construct from MPI_Request (as pointer type)
2080  explicit Request(const void* p) noexcept
2081  :
2082  value_(reinterpret_cast<value_type>(p))
2083  {}
2084 
2085  //- Construct from MPI_Request (as integer type)
2086  explicit Request(value_type val) noexcept
2087  :
2088  value_(val)
2089  {}
2090 
2091 
2092  // Member Functions
2093 
2094  //- Return raw value
2095  value_type value() const noexcept { return value_; }
2096 
2097  //- Return as pointer value
2098  const void* pointer() const noexcept
2099  {
2100  return reinterpret_cast<const void*>(value_);
2101  }
2102 
2103  //- True if not equal to MPI_REQUEST_NULL
2104  bool good() const noexcept;
2105 
2106  //- Reset to default constructed value (MPI_REQUEST_NULL)
2107  void reset() noexcept;
2108 
2109  //- Same as calling UPstream::cancelRequest()
2110  void cancel() { UPstream::cancelRequest(*this); }
2111 
2112  //- Same as calling UPstream::freeRequest()
2113  void free() { UPstream::freeRequest(*this); }
2114 
2115  //- Same as calling UPstream::finishedRequest()
2116  bool finished() { return UPstream::finishedRequest(*this); }
2117 
2118  //- Same as calling UPstream::waitRequest()
2119  void wait() { UPstream::waitRequest(*this); }
2120 };
2121 
2122 
2123 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
2124 
2125 Ostream& operator<<(Ostream&, const UPstream::commsStruct&);
2126 
2127 
2128 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2129 
2130 } // End namespace Foam
2131 
2132 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2133 
2134 // Traits, nested classes etc
2135 #include "UPstreamTraits.H"
2136 #include "UPstreamWindow.H"
2137 
2138 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2139 
2140 #ifdef NoRepository
2141  #include "UPstream.txx"
2142 #endif
2143 
2144 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2145 
2146 #endif
2147 
2148 // ************************************************************************* //
static bool floatTransfer
Should compact transfer be used in which floats replace doubles reducing the bandwidth requirement at...
Definition: UPstream.H:942
static bool mpi_send(const UPstream::commsTypes commsType, const void *buf, std::streamsize count, const UPstream::dataTypes dataTypeId, const int toProcNo, const int tag, const int communicator, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Send buffer contents of specified data type to given processor.
static const word & myWorld()
My world.
Definition: UPstream.H:1707
commsStruct() noexcept
Default construct with above == -1.
Definition: UPstream.H:254
6*float (eg, floatSymmTensor, complex vector)
(internal use) begin marker [user types]
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
int above() const noexcept
The procID of the processor directly above.
Definition: UPstream.H:287
9*double (eg, doubleTensor)
sendModes
Different MPI-send modes (ignored for commsTypes::buffered)
Definition: UPstream.H:94
compatibility name for buffered
(internal use) begin marker [basic/all types]
static void removeRequests(const label pos, label len=-1)
Non-blocking comms: cancel/free outstanding requests (from position onwards) and remove from internal...
static bool usingNodeComms(const int communicator)
True if node topology-aware routines have been enabled, it is running in parallel, the starting point is the world-communicator and it is not an odd corner case (ie, all processes on one node, all processes on different nodes)
Definition: UPstream.C:751
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:89
static const labelList & worldIDs() noexcept
The indices into allWorlds for all processes.
Definition: UPstream.H:1691
static int incrMsgType(int val=1) noexcept
Increment the message tag for standard messages.
Definition: UPstream.H:1809
static void printCommTree(int communicator, bool linear=false)
Debugging: print the communication tree.
Definition: UPstream.C:737
static void mpi_scatterv(const void *sendData, const UList< int > &sendCounts, const UList< int > &sendOffsets, void *recvData, int recvCount, const UPstream::dataTypes dataTypeId, const int communicator)
Send variable length data from rank 0 to all ranks. (caution: known to scale poorly) ...
An opaque wrapper for MPI_Comm with a vendor-independent representation without any <mpi...
Definition: UPstream.H:2451
commsTypes
Communications types.
Definition: UPstream.H:77
static T listScatterValues(const UList< T > &allValues, const int communicator=UPstream::worldComm)
Scatter individual values from list locations.
Bit-wise xor for (unsigned) integral types.
const List< int > & allBelow() const noexcept
The procIDs of all processors below (so not just directly below)
Definition: UPstream.H:298
An opaque wrapper for MPI_Win with a vendor-independent representation and without any <mpi...
static void printNodeCommsControl(Ostream &os)
Report the node-communication settings.
Definition: UPstream.C:56
static void mpi_reduce(void *values, int count, const UPstream::dataTypes dataTypeId, const UPstream::opCodes opCodeId, const int communicator, UPstream::Request *req=nullptr)
In-place reduction of values with result on rank 0.
static void freeCommunicator(const label communicator, const bool withComponents=true)
Free a previously allocated communicator.
Definition: UPstream.C:622
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
3*float (eg, floatVector)
An interval of (signed) integers defined by a start and a size.
Definition: IntRange.H:59
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:1718
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
static const commsStructList & linearCommunication(int communicator)
Linear communication schedule (special case) for given communicator.
Definition: UPstream.C:699
IntRange< int > rangeType
Int ranges are used for MPI ranks (processes)
Definition: UPstream.H:72
static int maxCommsSize
Optional maximum message size (bytes)
Definition: UPstream.H:968
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:697
static label allocateCommunicator(const label parent, const labelRange &subRanks, const bool withComponents=true)
Create new communicator with sub-ranks on the parent communicator.
Definition: UPstream.H:2146
static int nProcsSimpleSum
Number of processors to change from linear to tree communication.
Definition: UPstream.H:947
static void mpi_gather(const void *sendData, void *recvData, int count, const UPstream::dataTypes dataTypeId, const int communicator, UPstream::Request *req=nullptr)
Receive identically-sized (contiguous) data from all ranks, placing the result on rank 0...
static void mpiScatter(const Type *sendData, Type *recvData, int count, const int communicator=UPstream::worldComm)
Send identically-sized (contiguous) data to all ranks.
static label newCommunicator(const label parent, const labelRange &subRanks, const bool withComponents=true)
Create new communicator with sub-ranks on the parent communicator.
Definition: UPstream.C:272
static bool initNull()
Special purpose initialisation function.
Definition: UPstream.C:30
9*float (eg, floatTensor)
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
static void cancelRequest(const label i)
Non-blocking comms: cancel and free outstanding request. Corresponds to MPI_Cancel() + MPI_Request_fr...
#define Pstream_CommonRoutines(Type)
Definition: UPstream.H:1856
static int nodeCommsMin_
Minimum number of nodes before topology-aware routines are enabled.
Definition: UPstream.H:921
static List< T > allGatherValues(const T &localValue, const int communicator=UPstream::worldComm)
Allgather individual values into list locations.
static bool finishedRequest(const label i)
Non-blocking comms: has request i finished? Corresponds to MPI_Test()
static label procNo(const label comm, const int baseProcID)
Return processor number in communicator (given physical processor number) (= reverse of baseProcNo) ...
Definition: UPstream.C:670
static constexpr int commGlobal() noexcept
Communicator for all ranks, irrespective of any local worlds.
Definition: UPstream.H:999
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1787
static int topologyControl_
Selection of topology-aware routines as a bitmask combination of the topoControls enumerations...
Definition: UPstream.H:927
static void freeRequest(UPstream::Request &req)
Non-blocking comms: free outstanding request. Corresponds to MPI_Request_free()
void reset()
Reset to default constructed state.
(internal use) begin marker [reduce/window types]
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1611
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:987
static void freeRequests(UList< UPstream::Request > &requests)
Non-blocking comms: free outstanding requests. Corresponds to MPI_Request_free()
(internal use) end marker [all types]
mapGather (reduction) [manual algorithm]
static const commsStructList & treeCommunication(int communicator)
Tree communication schedule (standard case) for given communicator.
Definition: UPstream.C:718
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:2189
static void mpiGather(const Type *sendData, Type *recvData, int count, const int communicator=UPstream::worldComm)
Receive identically-sized (contiguous) data from all ranks.
static int tuning_NBX_
Tuning parameters for non-blocking exchange (NBX)
Definition: UPstream.H:973
static void shutdown(int errNo=0)
Shutdown (finalize) MPI as required.
Definition: UPstream.C:57
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
static label parent(int communicator)
The parent communicator.
Definition: UPstream.H:1664
ClassName("UPstream")
Declare name of the class and its debug switch.
Various functions to operate on Lists.
opCodes
Mapping of some MPI op codes.
Definition: UPstream.H:145
class FOAM_DEPRECATED_FOR(2017-05, "Foam::Enum") NamedEnum
Definition: NamedEnum.H:65
static void gather(const Type *send, int count, Type *recv, const UList< int > &counts, const UList< int > &offsets, const int comm=UPstream::worldComm)
Definition: UPstream.H:2197
static List< T > listGatherValues(const T &localValue, const int communicator=UPstream::worldComm)
Gather individual values into list locations.
static bool finishedRequestPair(label &req0, label &req1)
Non-blocking comms: have both requests finished? Corresponds to pair of MPI_Test() ...
static int nProcsNonblockingExchange
Number of processors to change to nonBlocking consensual exchange (NBX). Ignored for zero or negative...
Definition: UPstream.H:953
byte, char, unsigned char, ...
reduce/all-reduce [MPI]
static label commWarn(const label communicator) noexcept
Alter communicator debugging setting. Warns for use of any communicator differing from specified...
Definition: UPstream.H:1040
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
6*double (eg, doubleSymmTensor, complex vector)
dimensionedScalar pos(const dimensionedScalar &ds)
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: UListIO.C:75
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
static void send_done(const int toProcNo, const int communicator, const int tag=UPstream::msgType()+1970)
Impose a point-to-point synchronisation barrier by sending a zero-byte "done" message to given rank...
Definition: UPstream.C:111
static void barrier(const int communicator, UPstream::Request *req=nullptr)
Impose a synchronisation barrier (optionally non-blocking)
Definition: UPstream.C:106
static int nPollProcInterfaces
Number of polling cycles in processor updates.
Definition: UPstream.H:958
static int commInterNode() noexcept
Communicator between nodes/hosts (respects any local worlds)
Definition: UPstream.H:1063
static void exit(int errNo=1)
Shutdown (finalize) MPI as required and exit program with errNo.
Definition: UPstream.C:61
static const commsStructList & whichCommunication(const int communicator, bool linear=false)
Communication schedule for all-to-master (proc 0) as linear/tree/none with switching based on UPstrea...
Definition: UPstream.H:1760
static bool is_rank(const label communicator=worldComm)
True if process corresponds to any rank (master or sub-rank) in the given communicator.
Definition: UPstream.H:1628
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
static void printTopoControl(Ostream &os)
Report the topology routines settings.
Definition: UPstream.C:100
static bool init(int &argc, char **&argv, const bool needsThread)
Initialisation function called from main.
Definition: UPstream.C:40
(internal use) end marker [window types]
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
An opaque wrapper for MPI_Request with a vendor-independent representation without any <mpi...
Definition: UPstream.H:2599
static void mpi_scatter(const void *sendData, void *recvData, int count, const UPstream::dataTypes dataTypeId, const int communicator, UPstream::Request *req=nullptr)
Send identically-sized (contiguous) data from rank 0 to all other ranks.
static void mpiGatherv(const Type *sendData, int sendCount, Type *recvData, const UList< int > &recvCounts, const UList< int > &recvOffsets, const int communicator=UPstream::worldComm)
Receive variable length data from all ranks.
static int commConstWorld() noexcept
Communicator for all ranks (respecting any local worlds).
Definition: UPstream.H:1014
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1596
(MPI_Send, MPI_Isend)
static constexpr int commSelf() noexcept
Communicator within the current rank only.
Definition: UPstream.H:1006
static const commsStructList & null()
An empty structure. Used for placeholders etc.
static label commInterHost() noexcept
Communicator between nodes (respects any local worlds)
Definition: UPstream.H:2174
(internal use) end marker [all types]
static bool is_parallel(const label communicator=worldComm)
True if parallel algorithm or exchange is required.
Definition: UPstream.H:1648
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
static std::streamsize mpi_receive(const UPstream::commsTypes commsType, void *buf, std::streamsize count, const UPstream::dataTypes dataTypeId, const int fromProcNo, const int tag, const int communicator, UPstream::Request *req=nullptr)
Receive buffer contents of specified data type from given processor.
Definition: UIPstreamRead.C:27
static label warnComm
Debugging: warn for use of any communicator differing from warnComm.
Definition: UPstream.H:992
Structure for communicating between processors.
Definition: UPstream.H:220
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
static void reduceAnd(bool &value, const int communicator=worldComm)
Logical (and) reduction (MPI_AllReduce)
static bool waitAnyRequest(const label pos, label len=-1)
Wait until any request (from position onwards) has finished. Corresponds to MPI_Waitany() ...
commsTypes commsType() const noexcept
Get the communications type of the stream.
Definition: UPstream.H:1819
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: scalarImpl.H:255
static std::pair< int, int64_t > probeMessage(const UPstream::commsTypes commsType, const int fromProcNo, const int tag=UPstream::msgType(), const int communicator=worldComm)
Probe for an incoming message.
Definition: UPstream.C:132
(MPI_Ssend, MPI_Issend)
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
static void mpiAllGather(Type *allData, int count, const int communicator=UPstream::worldComm)
Gather/scatter identically-sized data.
A set of traits associated with UPstream communication.
static void resetRequests(const label n)
Truncate outstanding requests to given length, which is expected to be in the range [0 to nRequests()...
UPstream(const commsTypes commsType) noexcept
Construct for given communication type.
Definition: UPstream.H:1102
static int commLocalNode() noexcept
Communicator within the node/host (respects any local worlds)
Definition: UPstream.H:1071
const List< int > & below() const noexcept
The procIDs of the processors directly below.
Definition: UPstream.H:292
static bool is_subrank(const label communicator=worldComm)
True if process corresponds to a sub-rank in the given communicator.
Definition: UPstream.H:1636
OBJstream os(runTime.globalPath()/outputName)
Collection of communication structures.
Definition: UPstream.H:354
topoControls
Some bit masks corresponding to topology controls.
Definition: UPstream.H:184
static const List< int > & interNode_offsets()
Processor offsets corresponding to the inter-node communicator.
Definition: UPstream.C:776
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
static void waitRequestPair(label &req0, label &req1)
Non-blocking comms: wait for both requests to finish. Corresponds to pair of MPI_Wait() ...
dataTypes
Mapping of some fundamental and aggregate types to MPI data types.
Definition: UPstream.H:103
static void addRequest(UPstream::Request &req)
Transfer the (wrapped) MPI request to the internal global list and invalidate the parameter (ignores ...
static label commWorld() noexcept
Communicator for all ranks (respecting any local worlds)
Definition: UPstream.H:1019
void reset_linear(const int myProci, const int numProcs)
Reset to linear (flat) communication.
Wrapper for internally indexed communicator label. Always invokes UPstream::allocateCommunicatorCompo...
Definition: UPstream.H:2237
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:32
static void mpiScatterv(const Type *sendData, const UList< int > &sendCounts, const UList< int > &sendOffsets, Type *recvData, int recvCount, const int communicator=UPstream::worldComm)
Send variable length data to all ranks.
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
List< word > wordList
List of word.
Definition: fileName.H:59
static label commIntraHost() noexcept
Communicator within the node (respects any local worlds)
Definition: UPstream.H:2180
(internal use) begin marker [window types]
static int wait_done(const int fromProcNo, const int communicator, const int tag=UPstream::msgType()+1970)
Impose a point-to-point synchronisation barrier by receiving a zero-byte "done" message from given ra...
Definition: UPstream.C:120
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:963
static void cancelRequests(UList< UPstream::Request > &requests)
Non-blocking comms: cancel and free outstanding requests. Corresponds to MPI_Cancel() + MPI_Request_f...
static void mpi_allgather(void *allData, int count, const UPstream::dataTypes dataTypeId, const int communicator, UPstream::Request *req=nullptr)
Gather/scatter identically-sized data.
static void mpi_gatherv(const void *sendData, int sendCount, void *recvData, const UList< int > &recvCounts, const UList< int > &recvOffsets, const UPstream::dataTypes dataTypeId, const int communicator)
Receive variable length data from all ranks, placing the result on rank 0. (caution: known to scale p...
static label dupCommunicator(const label parent)
Duplicate the parent communicator.
Definition: UPstream.C:401
static const rangeType & localNode_parentProcs()
The range (start/size) of the commLocalNode ranks in terms of the (const) world communicator processo...
Definition: UPstream.C:817
static label nComms() noexcept
Number of currently defined communicators.
Definition: UPstream.H:1050
limits reset(1/(limits.max()+VSMALL), 1/(limits.min()+VSMALL))
surface1 clear()
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1619
Bit-wise or for (unsigned) integral types.
static void mpi_allreduce(void *values, int count, const UPstream::dataTypes dataTypeId, const UPstream::opCodes opCodeId, const int communicator, UPstream::Request *req=nullptr)
In-place reduction of values with same result on all ranks.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
static int numNodes() noexcept
The number of shared/host nodes in the (const) world communicator.
Definition: UPstream.H:1659
static List< int > & procID(int communicator)
The list of ranks within a given communicator.
Definition: UPstream.H:1672
label n
(internal use) end marker [reduce types]
bool operator!=(const eddy &a, const eddy &b)
Definition: eddy.H:297
static bool haveThreads() noexcept
Have support for threads.
Definition: UPstream.H:1591
static label splitCommunicator(const label parent, const int colour, const bool two_step=true)
Allocate a new communicator by splitting the parent communicator on the given colour.
Definition: UPstream.C:439
static void abort(int errNo=1)
Call MPI_Abort with no other checks or cleanup.
Definition: UPstream.C:68
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1727
List< label > labelList
A List of labels.
Definition: List.H:61
int nProcs() const noexcept
The number of processors addressed by the structure.
volScalarField & p
tmp< faMatrix< Type > > operator==(const faMatrix< Type > &, const faMatrix< Type > &)
"buffered" : (MPI_Bsend, MPI_Recv)
static const int mpiBufferSize
MPI buffer-size (bytes)
Definition: UPstream.H:978
static const wordList & allWorlds() noexcept
All worlds.
Definition: UPstream.H:1683
static bool mpi_broadcast(void *buf, std::streamsize count, const UPstream::dataTypes dataTypeId, const int communicator)
Broadcast buffer contents from rank=0 to all ranks. The sizes must match on all processes.
const List< int > & allNotBelow() const noexcept
The procIDs of all processors not below myProcNo. The inverse set of allBelow without myProcNo...
Definition: UPstream.H:304
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce)
static void waitRequest(const label i)
Wait until request i has finished. Corresponds to MPI_Wait()
static void mpiReduce(T values[], int count, const UPstream::opCodes opCodeId, const int communicator)
MPI_Reduce (blocking) for known operators.
static bool usingTopoControl(UPstream::topoControls ctrl) noexcept
Test for selection of given topology-aware routine.
Definition: UPstream.H:932
Inter-processor communications stream.
Definition: UPstream.H:65
static bool hasNodeCommunicators() noexcept
Both inter-node and local-node communicators have been created.
Definition: UPstream.H:1079
(internal use) end marker [basic types]
static int baseProcNo(label comm, int procID)
Return physical processor number (i.e. processor number in worldComm) given communicator and processo...
Definition: UPstream.C:657
gatherList [manual algorithm]
static bool broadcast(Type *buffer, std::streamsize count, const int communicator)
Broadcast buffer contents (contiguous types), from rank=0 to all ranks. The sizes must match on all p...
static void addValidParOptions(HashTable< string > &validParOptions)
Add the valid option this type of communications library adds/requires on the command line...
Definition: UPstream.C:26
gather/all-gather [MPI]
Namespace for OpenFOAM.
3*double (eg, doubleVector)
(internal use) end marker [user types]
static int nodeCommsControl_
Use of host/node topology-aware routines.
Definition: UPstream.H:913
static label myWorldID()
My worldID.
Definition: UPstream.H:1699
static void scatter(const Type *send, const UList< int > &counts, const UList< int > &offsets, Type *recv, int count, const int comm=UPstream::worldComm)
Definition: UPstream.H:2215
static bool waitSomeRequests(const label pos, label len=-1, DynamicList< int > *indices=nullptr)
Wait until some requests (from position onwards) have finished. Corresponds to MPI_Waitsome() ...
static bool finishedRequests(const label pos, label len=-1)
Non-blocking comms: have all requests (from position onwards) finished? Corresponds to MPI_Testall() ...
Bit-wise and for (unsigned) integral types.
static void mpiAllReduce(T values[], int count, const UPstream::opCodes opCodeId, const int communicator)
MPI_Allreduce (blocking) for known operators.