Program Listing for File field_communicator.hpp
↰ Return to documentation for file (src/pcms/coupler/field_communicator.hpp)
#ifndef FIELD_COMMUNICATOR2_H_
#define FIELD_COMMUNICATOR2_H_
#include "pcms/coupler/field_layout_communicator.h"
#include "pcms/field/field.h"
#include "pcms/field/field_layout.h"
#include "pcms/coupler/field_serializer.h"
#include "pcms/utility/profile.h"
#include "pcms/utility/assert.h"
#include "pcms/utility/inclusive_scan.h"
#include "pcms/utility/arrays.h"
#include <redev.h>
#include <memory>
namespace pcms
{
template <typename T>
class FieldCommunicator
{
public:
FieldCommunicator(const std::string& name,
FieldLayoutCommunicator& layout_comm, Field<T>& field)
: comm_buffer_{}, layout_comm_(layout_comm), field_(field)
{
PCMS_ALWAYS_ASSERT(layout_comm.GetLayout().GetName() ==
field.GetLayout().GetName());
// The exchange plan is per DOF holder; the field payload carries
// num_components values per holder, so the buffer is scaled accordingly.
comm_buffer_.resize(
layout_comm.GetMsgSize() *
static_cast<size_t>(field.GetLayout().GetNumComponents()));
comm_ =
layout_comm_.GetChannel().CreateComm<T>(name, layout_comm.GetMPIComm());
layout_comm_.SetOutMessageLayout<T>(comm_);
}
void Send(redev::Mode mode = redev::Mode::Synchronous)
{
PCMS_FUNCTION_TIMER;
PCMS_ALWAYS_ASSERT(layout_comm_.GetChannel().InSendCommunicationPhase());
auto buffer = make_array_view(comm_buffer_);
serializer_.Serialize(field_, buffer, layout_comm_.GetPermutationArray());
comm_.Send(buffer.data_handle(), mode);
}
void Receive()
{
PCMS_FUNCTION_TIMER;
PCMS_ALWAYS_ASSERT(layout_comm_.GetChannel().InReceiveCommunicationPhase());
// Current implementation requires that Receive is always called in Sync
// mode because we make an immediate call to deserialize after a call to
// receive.
auto data = comm_.Recv(redev::Mode::Synchronous);
serializer_.Deserialize(field_, make_const_array_view(data),
layout_comm_.GetPermutationArray());
}
private:
std::vector<T> comm_buffer_;
redev::BidirectionalComm<T> comm_;
FieldLayoutCommunicator& layout_comm_;
Field<T>& field_;
FieldSerializer<T> serializer_;
};
template <typename T>
using FieldCommunicator2PtrT = std::unique_ptr<FieldCommunicator<T>>;
using FieldCommunicator2Ptr =
std::variant<FieldCommunicator2PtrT<int8_t>, FieldCommunicator2PtrT<int32_t>,
FieldCommunicator2PtrT<int64_t>, FieldCommunicator2PtrT<float>,
FieldCommunicator2PtrT<double>>;
} // namespace pcms
#endif // FIELD_COMMUNICATOR2_H_