Skip to content

File mpisendreceive.h

File List > code_source > templat > include > TempLat > parallel > mpi > comm > exchange > mpisendreceive.h

Go to the documentation of this file

#ifndef TEMPLAT_PARALLEL_MPI_COMM_EXCHANGE_MPISENDRECEIVE_H
#define TEMPLAT_PARALLEL_MPI_COMM_EXCHANGE_MPISENDRECEIVE_H

/* This file is part of TempLat, available at https://cosmolattice.github.io/templat .
   Copyright 2021-2026 The TempLat authors, see AUTHORS.md.
   Released under the MIT license, see LICENSE.md. */

// File info: Main contributor(s): Wessel Valkenburg, Year: 2019

#include "TempLat/util/exception.h"
#include "TempLat/parallel/mpi/comm/mpicommreference.h"

namespace TempLat
{

  MakeException(MPISendReceiveException);

  class MPISendReceive
  {
  public:
    // Put public methods here. These should change very little over time.
    MPISendReceive(MPICommReference comm) : mpiComm(comm) {}

    template <typename T> void send(std::vector<T> *theVec, int toRank, int tag)
    {
      /* Vectors have a dynamic size. So we must perform two
       * information exchanges: the size and the data.
       */

      size_t theSize = theVec->size();

      send(&theSize, toRank, tag, 1);

      send(theVec->data(), toRank, tag + 1, theSize);
    }

    template <typename T> void receive(std::vector<T> *theVec, int fromRank, int tag)
    {
      /* Vectors have a dynamic size. So we must perform two
       * information exchanges: the size and the data.
       */

      size_t theSize = 0;

      receive(&theSize, fromRank, tag, 1);

      theVec->resize(theSize);

      receive(theVec->data(), fromRank, tag + 1, theSize);
    }

    template <typename T, size_t N> void send(std::array<T, N> *theArr, int toRank, int tag)
    {
      send(theArr->data(), toRank, tag, N);
    }

    template <typename T, size_t N> void receive(std::array<T, N> *theArr, int fromRank, int tag)
    {
      receive(theArr->data(), fromRank, tag, N);
    }

    /* these should work with built in types */
    template <typename T> void send(T *value, int toRank, int tag, int size = 1)
    {
#ifdef HAVE_MPI
      int result = 0;
      result = MPI_Send(value, size, MPITypeSelect<T>(), toRank, tag, mpiComm);
      if (0 != result) {
        throw MPISendReceiveException("MPI_Send failed. Error code:", result);
      }
#endif
    }

    template <typename T> void receive(T *value, int fromRank, int tag, int size = 1)
    {
#ifdef HAVE_MPI
      int result = 0;
      MPI_Status status;
      status.MPI_ERROR = 0;
      result = MPI_Recv(value, size, MPITypeSelect<T>(), fromRank, tag, mpiComm, &status);
      if (0 != result || 0 != status.MPI_ERROR) {
        throw MPISendReceiveException("MPI_Send failed. Error codes:", result, status.MPI_ERROR);
      }
#endif
    }

  private:
    /* Put all member variables and private methods here. These may change arbitrarily. */
    MPICommReference mpiComm;
  };
} // namespace TempLat

#endif