12#ifndef MFEM_COMMUNICATION
13#define MFEM_COMMUNICATION
30#define MFEM_MPI_CXX_BOOL MPI_CXX_BOOL
32#define MFEM_MPI_CXX_BOOL MPI_C_BOOL
45 static void Init(
int &argc,
char **&argv,
47 int *provided =
nullptr)
48 {
Init(&argc, &argv, required, provided); }
50 static void Init(
int *argc =
nullptr,
char ***argv =
nullptr,
52 int *provided =
nullptr)
55 if (required == MPI_THREAD_SINGLE)
57 int mpi_err = MPI_Init(argc, argv);
58 MFEM_VERIFY(!mpi_err,
"error in MPI_Init()!");
59 if (provided) { *provided = MPI_THREAD_SINGLE; }
64 int mpi_err = MPI_Init_thread(argc, argv, required, &mpi_provided);
65 MFEM_VERIFY(!mpi_err,
"error in MPI_Init()!");
66 if (provided) { *provided = mpi_provided; }
80 int mpi_is_initialized;
81 int mpi_err = MPI_Initialized(&mpi_is_initialized);
82 return (mpi_err == MPI_SUCCESS) && mpi_is_initialized;
88 int mpi_err = MPI_Finalized(&mpi_is_finalized);
89 return (mpi_err == MPI_SUCCESS) && mpi_is_finalized;
95 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
102 MPI_Comm_size(MPI_COMM_WORLD, &world_size);
111 static Mpi &Singleton()
172 void SetComm(MPI_Comm comm) { MyComm = comm; }
178 int MyRank()
const {
int r; MPI_Comm_rank(MyComm, &r);
return r; }
181 int NRanks()
const {
int s; MPI_Comm_size(MyComm, &s);
return s; }
196 bool IAmMaster(
int g)
const {
return (groupmaster_lproc[g] == 0); }
204 {
return lproc_proc[groupmaster_lproc[g]]; }
217 void Save(std::ostream &
out)
const;
220 void Load(std::istream &in);
233class DeviceGroupCommunicator;
352 int layout,
void (*Op)(
OpData<T>))
const;
363 template <
class T>
void BcastBegin(T *ldata,
int layout)
const;
392 template <
class T>
void BcastEnd(T *ldata,
int layout)
const;
424 template <
class T>
void Bcast(T *ldata,
int layout)
const
435 template <
class T>
void Bcast(T *ldata)
const {
Bcast(ldata, 0); }
460 template <
class T>
void ReduceBegin(
const T *ldata)
const;
477 void (*Op)(OpData<T>) =
nullptr)
const;
496 template <
class T>
void ReduceEnd(T *ldata,
int layout,
497 void (*Op)(OpData<T>))
const;
522 void (*Op)(OpData<T>))
const;
558 template <
class T>
static void Sum(OpData<T>);
560 template <
class T>
static void Min(OpData<T>);
562 template <
class T>
static void Max(OpData<T>);
564 template <
class T>
static void BitOR(OpData<T>);
570 template <
class T>
static void MaxAbs(OpData<T>);
580 void (*Op)(OpData<T>))
const;
616 template <
typename T>
620 template <
typename T>
624 template <
typename T>
628 template <
typename T>
633 template <
typename T>
638 template <
typename T>
643 template <
typename T>
647 template <
typename T>
652 template <
typename T>
658 template <
typename T>
664 template <
typename T>
668 template <
typename T>
673 template <
typename T>
677 template <
typename T>
683 template <
typename T>
688 template <
typename T>
694 template <
typename T>
699 template <
typename T>
704 template <
typename T>
772 MPI_Isend((
void*)
data.data(),
static_cast<int>(
data.length()), MPI_BYTE, rank,
782 MPI_Issend((
void*)
data.data(),
static_cast<int>(
data.length()), MPI_BYTE, rank,
787 template<
typename MapT>
788 static void IsendAll(MapT& rank_msg, MPI_Comm comm)
790 for (
auto it = rank_msg.begin(); it != rank_msg.end(); ++it)
792 it->second.Isend(it->first, comm);
797 template<
typename MapT>
800 for (
auto it = rank_msg.begin(); it != rank_msg.end(); ++it)
802 MPI_Wait(&it->second.send_request, MPI_STATUS_IGNORE);
809 template<
typename MapT>
812 for (
auto it = rank_msg.begin(); it != rank_msg.end(); ++it)
819 if (!sent) {
return false; }
828 static void Probe(
int &rank,
int &size, MPI_Comm comm)
831 MPI_Probe(MPI_ANY_SOURCE, Tag, comm, &status);
832 rank = status.MPI_SOURCE;
833 MPI_Get_count(&status, MPI_BYTE, &size);
839 static bool IProbe(
int &rank,
int &size, MPI_Comm comm)
843 MPI_Iprobe(MPI_ANY_SOURCE, Tag, comm, &flag, &status);
844 if (!flag) {
return false; }
846 rank = status.MPI_SOURCE;
847 MPI_Get_count(&status, MPI_BYTE, &size);
852 void Recv(
int rank,
int size, MPI_Comm comm)
854 MFEM_ASSERT(size >= 0,
"");
857 MPI_Recv((
void*)
data.data(), size, MPI_BYTE, rank, Tag, comm, &status);
860 MPI_Get_count(&status, MPI_BYTE, &count);
861 MFEM_VERIFY(count == size,
"");
871 MPI_Recv((
void*)
data.data(), size, MPI_BYTE, rank, Tag, comm, &status);
876 template<
typename MapT>
877 static void RecvAll(MapT& rank_msg, MPI_Comm comm)
879 int recv_left =
static_cast<int>(rank_msg.size());
880 while (recv_left > 0)
883 Probe(rank, size, comm);
884 MFEM_ASSERT(rank_msg.find(rank) != rank_msg.end(),
"Unexpected message"
885 " (tag " << Tag <<
") from rank " << rank);
887 rank_msg[rank].Recv(rank, size, comm);
900 "WaitAllSent was not called after Isend");
907 "Cannot copy message with a pending send.");
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
int Size() const
Return the logical size of the array.
Auxiliary class used by class GroupCommunicator implementing its device (GPU) code paths for data pas...
Array< buffer_max_type > ext_buf
void RestrictTranspose(const Array< T > &x_tdof, Array< T > &x_ldof) const
Transpose of Restrict(): copy the true-dof data x_tdof into the owned local dofs of x_ldof and set th...
void Restrict(const Array< T > &x_ldof, Array< T > &x_tdof) const
Kernel: copy owned ldofs from x_ldof to ltdofs in x_tdof, i.e. x_tdof[i] = x_ldof[ltdof_ldof[i]].
Array< int > shr_buf_offsets
void BcastEndCopy(const Array< T > &ext_buf_t, Array< T > &x_ldof) const
void CopyTDofsToLDofs(const Array< T > &x_tdof, Array< T > &x_ldof) const
Kernel: copy ltdofs from x_tdof to ldofs in x_ldof, i.e. x_ldof[ltdof_ldof[i]] = x_tdof[i].
void ReduceEndLDofs(Array< T > &x_ldof, Op op) const
Finalize a group reduction into the local-dof data x_ldof, applying the reduction operation op.
void BcastBeginTDofs(Array< T > &x_tdof) const
Begin a group broadcast of the true-dof data x_tdof.
const GroupCommunicator & gc
void ProlongateTranspose(const Array< T > &x_ldof, Array< T > &x_tdof, Op op=Op::Sum) const
Transpose of Prolongate(): reduce the local-dof data x_ldof into the true-dof data x_tdof,...
Array< int > ext_buf_offsets
void ReduceEndAssembleTDofs(const Array< T > &shr_buf_t, Array< T > &x_tdof, Op op) const
Array< buffer_max_type > shr_buf
void BcastBeginCopyTDofs(const Array< T > &x_tdof, Array< T > &shr_buf_t) const
void ReduceEndTDofs(Array< T > &x_tdof, Op op) const
Finalize a group reduction into the true-dof data x_tdof, applying the reduction operation op.
void ReduceBeginLDofs(const Array< T > &x_ldof) const
Begin a group reduction of the local-dof data x_ldof.
void ExchangeSharedToExternal(const Array< T > &shr_buf, Array< T > &ext_buf) const
Op
Reduction operation applied at the receiving dofs.
void BcastBeginLDofs(Array< T > &x_ldof) const
Begin a group broadcast of the local-dof data x_ldof.
void ReduceBeginCopy(const Array< T > &x_ldof, Array< T > &ext_buf_t) const
DeviceGroupCommunicator(const GroupCommunicator &gc_)
Construct a device communicator based on the GroupCommunicator gc_.
void BcastEndLDofs(Array< T > &x_ldof) const
Finalize a group broadcast into the local-dof data x_ldof.
void BcastBeginCopyLDofs(const Array< T > &x_ldof, Array< T > &shr_buf_t) const
Array< MPI_Request > requests
void ExchangeExternalToShared(const Array< T > &ext_buf, Array< T > &shr_buf) const
void Prolongate(const Array< T > &x_tdof, Array< T > &x_ldof) const
Prolongate the true-dof data x_tdof to the local-dof data x_ldof.
void Exchange(const Array< T > &send_buf, const Array< int > &send_offsets, Array< T > &recv_buf, const Array< int > &recv_offsets, int tag) const
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
const Table & GroupLDofTable() const
Read-only access to group-ldof Table.
GroupCommunicator(const GroupTopology >, Mode m=byNeighbor)
Construct a GroupCommunicator object.
DeviceGroupCommunicator * device_gc
void GetNeighborLTDofTable(Table &nbr_ltdof) const
Dofs to be sent (during Bcast) to communication neighbors.
Table & GroupLDofTable()
Fill-in the returned Table reference to initialize the GroupCommunicator then call Finalize().
@ byGroup
Communications are performed one group at a time.
void GetNeighborLDofTable(Table &nbr_ldof) const
Dofs to be received (during Bcast) from communication neighbors.
const T * ReduceGroupFromBuffer(const T *buf, T *ldata, int group, int layout, void(*Op)(OpData< T >)) const
Perform the reduction operation Op to the entries of group group using the values from the buffer buf...
void ReduceMarked(T *ldata, const Array< int > &marker, int layout, void(*Op)(OpData< T >)) const
Finalize reduction operation started with ReduceBegin(), but only apply the reduction to DOFs marked ...
static void MaxAbs(OpData< T >)
void Reduce(Array< T > &ldata, void(*Op)(OpData< T >)) const
Reduce within each group where the master is the root, device version.
void ReduceEnd(T *ldata, int layout, void(*Op)(OpData< T >)) const
Finalize reduction operation started with the host version of ReduceBegin().
const GroupTopology & GetGroupTopology() const
Get a const reference to the associated GroupTopology object.
const GroupTopology & gtopo
void Reduce(T *ldata, void(*Op)(OpData< T >)) const
Reduce within each group where the master is the root, host version.
T * CopyGroupToBuffer(const T *ldata, T *buf, int group, int layout) const
Copy the entries corresponding to the group group from the local array ldata to the buffer buf.
const T * CopyGroupFromBuffer(const T *buf, T *ldata, int group, int layout) const
Copy the entries corresponding to the group group from the buffer buf to the local array ldata.
void BcastEnd(T *ldata, int layout) const
Finalize a broadcast started with the host version of BcastBegin().
void ReduceBegin(const T *ldata) const
Begin reduction operation within each group where the master is the root, host version.
void Create(const Array< int > &ldof_group)
Initialize the communicator from a local-dof to group map. Finalize() is called internally.
~GroupCommunicator()
Destroy a GroupCommunicator object, deallocating internal data structures and buffers.
static void Sum(OpData< T >)
Reduce operation Sum, instantiated for int, double and float.
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
void SetLTDofTable(const Array< int > &ldof_ltdof)
Initialize the internal group_ltdof Table.
static void BitOR(OpData< T >)
Reduce operation bitwise OR, instantiated for int only.
static void Max(OpData< T >)
Reduce operation Max, instantiated for int, double and float.
static void Min(OpData< T >)
Reduce operation Min, instantiated for int, double and float.
void Bcast(Array< T > &ldata) const
Broadcast within each group where the master is the root, device version.
void Bcast(T *ldata) const
Broadcast within each group where the master is the root, host version.
void BcastBegin(T *ldata, int layout) const
Begin a broadcast within each group where the master is the root, host version.
void Reduce(T *ldata, const Array< int > &marker, void(*Op)(OpData< T >)) const
Reduce within each group where the master is the root, but only for marked DOFs.
void Finalize()
Allocate internal buffers after the GroupLDofTable is defined.
void PrintInfo(std::ostream &out=mfem::out) const
Print information about the GroupCommunicator from all MPI ranks.
const DeviceGroupCommunicator & GetDeviceComm() const
Return the device communicator, 'device_gc', constructing it if it was not already constructed.
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
void SetComm(MPI_Comm comm)
Set the MPI communicator to 'comm'.
int NRanks() const
Return the number of MPI ranks within this object's communicator.
bool IAmMaster(int g) const
Return true if I am master for group 'g'.
void Swap(GroupTopology &other)
Swap the internal data with another GroupTopology object.
void Save(std::ostream &out) const
Save the data in a stream.
const int * GetGroup(int g) const
Return a pointer to a list of neighbors for a given group. Neighbor 0 is the local processor.
int MyRank() const
Return the MPI rank within this object's communicator.
int GetGroupSize(int g) const
Get the number of processors in a group.
int GetGroupMaster(int g) const
Return the neighbor index of the group master for a given group. Neighbor 0 is the local processor.
void Load(std::istream &in)
Load the data from a stream.
GroupTopology()
Constructor with the MPI communicator = 0.
GroupTopology(MPI_Comm comm)
Constructor given the MPI communicator 'comm'.
int GetGroupMasterRank(int g) const
Return the rank of the group master for group 'g'.
void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
MPI_Comm GetComm() const
Return the MPI communicator.
void Copy(GroupTopology ©) const
Copy the internal data to the external 'copy'.
int GetNumNeighbors() const
Return the number of neighbors including the local processor.
int NGroups() const
Return the number of groups.
int GetGroupMasterGroup(int g) const
Return the group number in the master for group 'g'.
A simple convenience class based on the Mpi singleton class above. Preserved for backward compatibili...
bool Root() const
Return true if WorldRank() == 0.
int WorldSize() const
Return MPI_COMM_WORLD's size.
MPI_Session(int &argc, char **&argv)
int WorldRank() const
Return MPI_COMM_WORLD's rank.
void CopyConvertPtr(const Memory< U > &base)
A simple singleton class that calls MPI_Init() at construction and MPI_Finalize() at destruction....
static MFEM_EXPORT int default_thread_required
Default level of thread support for MPI_Init_thread.
static bool IsFinalized()
Return true if MPI has been finalized.
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
static void Finalize()
Finalize MPI (if it has been initialized and not yet already finalized).
static void Init(int *argc=nullptr, char ***argv=nullptr, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init().
static bool IsInitialized()
Return true if MPI has been initialized.
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
int Size() const
Returns the number of TYPE I elements.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
MPI_Comm ReorderRanksZCurve(MPI_Comm comm)
@ REBALANCE_DOF_VM
RebalanceDofMessage.
@ NEIGHBOR_REFINEMENT_VM
NeighborRefinementMessage.
@ NEIGHBOR_ROW_VM
NeighborRowMessage.
@ NEIGHBOR_PREFINEMENT_VM
NeighborPRefinementMessage.
@ NEIGHBOR_ELEMENT_RANK_VM
NeighborElementRankMessage.
@ NEIGHBOR_ORDER_VM
NeighborOrderMessage.
@ REBALANCE_VM
RebalanceMessage.
@ NEIGHBOR_DEREFINEMENT_VM
NeighborDerefinementMessage.
MessageTag
General MPI message tags used by MFEM.
@ DEREFINEMENT_MATRIX_CONSTRUCTION_DATA
TypedBufferView(Array< buffer_max_type > &storage_)
Array< buffer_max_type > & storage
Data structure on which we define reduce operations. The data is associated with (and the operation i...
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
static MFEM_EXPORT const MPI_Datatype mpi_type
Helper struct to convert a C++ type to an MPI type.
Variable-length MPI message containing unspecific binary data.
void Issend(int rank, MPI_Comm comm)
Non-blocking synchronous send to processor 'rank'. Returns immediately. Completion (MPI_Wait/Test) me...
static void WaitAllSent(MapT &rank_msg)
Helper to wait for all messages in a map container to be sent.
virtual void Encode(int rank)=0
static bool TestAllSent(MapT &rank_msg)
Return true if all messages in the map container were sent, otherwise return false,...
void Isend(int rank, MPI_Comm comm)
Non-blocking send to processor 'rank'. Returns immediately. Completion (as tested by MPI_Wait/Test) d...
static void IsendAll(MapT &rank_msg, MPI_Comm comm)
Helper to send all messages in a rank-to-message map container.
virtual void Decode(int rank)=0
static void RecvAll(MapT &rank_msg, MPI_Comm comm)
Helper to receive all messages in a rank-to-message map container.
VarMessage(const VarMessage &other)
void Clear()
Clear the message and associated request.
void RecvDrop(int rank, int size, MPI_Comm comm)
Like Recv(), but throw away the message.
static bool IProbe(int &rank, int &size, MPI_Comm comm)
Non-blocking probe for incoming message of this type from any rank. If there is an incoming message,...
void Recv(int rank, int size, MPI_Comm comm)
Post-probe receive from processor 'rank' of message size 'size'.
static void Probe(int &rank, int &size, MPI_Comm comm)
Blocking probe for incoming message of this type from any rank. Returns the rank and message size.