diff --git a/Documentation/release/dev/mpich4-large-message-support.md b/Documentation/release/dev/mpich4-large-message-support.md
new file mode 100644
index 0000000000000000000000000000000000000000..9831f47a83a298a6e268735ade822f2684c62904
--- /dev/null
+++ b/Documentation/release/dev/mpich4-large-message-support.md
@@ -0,0 +1,5 @@
+## Add mpi large-message support from mpi 4.x to vtkMPICommunicator
+
+Variants of mpi calls allow for message lengths > MAX_INT in mpi 4.x and later.
+vtkMPICommunicator uses these by default when available, and makes versions of
+class methods available with 64bit lengths.
diff --git a/Parallel/MPI/vtkMPICommunicator.cxx b/Parallel/MPI/vtkMPICommunicator.cxx
index 45ee7addb6f879ed1ed723a8e9381e5ce22463cb..051c214f53abccbf096330aaee3d4f6c6ddb2e18 100644
--- a/Parallel/MPI/vtkMPICommunicator.cxx
+++ b/Parallel/MPI/vtkMPICommunicator.cxx
@@ -39,6 +39,12 @@ static inline void vtkMPICommunicatorDebugBarrier(MPI_Comm* handle)
 #endif
 }
 
+#if (MPI_VERSION >= 4)
+// Flag to indicate "_c" versions of communication routines exist, like MPI_Send_c,
+// which use the 64bit type MPI_Count for length parameters.
+// #define VTKMPI_64BIT_LENGTH
+#endif
+
 vtkStandardNewMacro(vtkMPICommunicator);
 
 vtkMPICommunicator* vtkMPICommunicator::WorldCommunicator = nullptr;
@@ -149,6 +155,11 @@ inline MPI_Datatype vtkMPICommunicatorGetMPIType(int vtkType)
       return MPI_LONG_LONG;
     case VTK_UNSIGNED_LONG_LONG:
       return MPI_UNSIGNED_LONG_LONG;
+#elif VTK_SIZEOF_LONG == 8
+    case VTK_LONG_LONG:
+      return MPI_LONG;
+    case VTK_UNSIGNED_LONG_LONG:
+      return MPI_UNSIGNED_LONG;
 #endif
 
     default:
@@ -198,7 +209,7 @@ inline int vtkMPICommunicatorGetVTKType(MPI_Datatype type)
   return VTK_CHAR;
 }
 
-inline int vtkMPICommunicatorCheckSize(vtkIdType length)
+inline int vtkMPICommunicatorCheckSize(vtkTypeInt64 length)
 {
   if (length > VTK_INT_MAX)
   {
@@ -213,9 +224,12 @@ inline int vtkMPICommunicatorCheckSize(vtkIdType length)
 }
 
 //------------------------------------------------------------------------------
+// "_c" versions of routines are defined by MPI 4.x, using MPI_Count, a 64-bit integer type, for
+// message length
+// Callers using MPI 3.x must check for overflow with vtkMPICommunicatorCheckSize(length)
 template <class T>
-int vtkMPICommunicatorSendData(const T* data, int length, int sizeoftype, int remoteProcessId,
-  int tag, MPI_Datatype datatype, MPI_Comm* Handle, int useCopy, int useSsend)
+int vtkMPICommunicatorSendData(const T* data, vtkTypeInt64 length, int sizeoftype,
+  int remoteProcessId, int tag, MPI_Datatype datatype, MPI_Comm* Handle, int useCopy, int useSsend)
 {
   if (useCopy)
   {
@@ -225,11 +239,19 @@ int vtkMPICommunicatorSendData(const T* data, int length, int sizeoftype, int re
     memcpy(tmpData, data, length * sizeoftype);
     if (useSsend)
     {
+#ifdef VTKMPI_64BIT_LENGTH
+      retVal = MPI_Ssend_c(tmpData, length, datatype, remoteProcessId, tag, *(Handle));
+    }
+    else
+    {
+      retVal = MPI_Send_c(tmpData, length, datatype, remoteProcessId, tag, *(Handle));
+#else
       retVal = MPI_Ssend(tmpData, length, datatype, remoteProcessId, tag, *(Handle));
     }
     else
     {
       retVal = MPI_Send(tmpData, length, datatype, remoteProcessId, tag, *(Handle));
+#endif
     }
     vtkMPICommunicator::Free(tmpData);
     return retVal;
@@ -238,15 +260,64 @@ int vtkMPICommunicatorSendData(const T* data, int length, int sizeoftype, int re
   {
     if (useSsend)
     {
+#ifdef VTKMPI_64BIT_LENGTH
+      return MPI_Ssend_c(const_cast<T*>(data), length, datatype, remoteProcessId, tag, *(Handle));
+    }
+    else
+    {
+      return MPI_Send_c(const_cast<T*>(data), length, datatype, remoteProcessId, tag, *(Handle));
+#else
       return MPI_Ssend(const_cast<T*>(data), length, datatype, remoteProcessId, tag, *(Handle));
     }
     else
     {
       return MPI_Send(const_cast<T*>(data), length, datatype, remoteProcessId, tag, *(Handle));
+#endif
     }
   }
 }
+
 //------------------------------------------------------------------------------
+int vtkMPICommunicator::ReceiveDataInternal(char* data, vtkTypeInt64 length, int sizeoftype,
+  int remoteProcessId, int tag, vtkMPICommunicatorReceiveDataInfo* info, int useCopy, int& senderId)
+{
+#ifndef VTKMPI_64BIT_LENGTH
+  if (!vtkMPICommunicatorCheckSize(length))
+  {
+    return 0;
+  }
+  return this->ReceiveDataInternal(
+    data, static_cast<int>(length), sizeoftype, remoteProcessId, tag, info, useCopy, senderId);
+#else
+  if (remoteProcessId == vtkMultiProcessController::ANY_SOURCE)
+  {
+    remoteProcessId = MPI_ANY_SOURCE;
+  }
+
+  int retVal;
+
+  if (useCopy)
+  {
+    char* tmpData = vtkMPICommunicator::Allocate(length * sizeoftype);
+    retVal = MPI_Recv_c(
+      tmpData, length, info->DataType, remoteProcessId, tag, *(info->Handle), &(info->Status));
+    memcpy(data, tmpData, length * sizeoftype);
+    vtkMPICommunicator::Free(tmpData);
+  }
+  else
+  {
+    retVal = MPI_Recv_c(
+      data, length, info->DataType, remoteProcessId, tag, *(info->Handle), &(info->Status));
+  }
+
+  if (retVal == MPI_SUCCESS)
+  {
+    senderId = info->Status.MPI_SOURCE;
+  }
+  return retVal;
+#endif
+}
+
 int vtkMPICommunicator::ReceiveDataInternal(char* data, int length, int sizeoftype,
   int remoteProcessId, int tag, vtkMPICommunicatorReceiveDataInfo* info, int useCopy, int& senderId)
 {
@@ -280,15 +351,24 @@ int vtkMPICommunicator::ReceiveDataInternal(char* data, int length, int sizeofty
 
 //------------------------------------------------------------------------------
 template <class T>
-int vtkMPICommunicatorNoBlockSendData(const T* data, int length, int remoteProcessId, int tag,
-  MPI_Datatype datatype, vtkMPICommunicator::Request& req, MPI_Comm* Handle)
+int vtkMPICommunicatorNoBlockSendData(const T* data, vtkTypeInt64 length, int remoteProcessId,
+  int tag, MPI_Datatype datatype, vtkMPICommunicator::Request& req, MPI_Comm* Handle)
 {
-  return MPI_Isend(
+#ifdef VTKMPI_64BIT_LENGTH
+  return MPI_Isend_c(
     const_cast<T*>(data), length, datatype, remoteProcessId, tag, *(Handle), &req.Req->Handle);
+#else
+  if (!vtkMPICommunicatorCheckSize(length))
+  {
+    return 0;
+  }
+  return MPI_Isend(const_cast<T*>(data), static_cast<int>(length), datatype, remoteProcessId, tag,
+    *(Handle), &req.Req->Handle);
+#endif
 }
 //------------------------------------------------------------------------------
 template <class T>
-int vtkMPICommunicatorNoBlockReceiveData(T* data, int length, int remoteProcessId, int tag,
+int vtkMPICommunicatorNoBlockReceiveData(T* data, vtkTypeInt64 length, int remoteProcessId, int tag,
   MPI_Datatype datatype, vtkMPICommunicator::Request& req, MPI_Comm* Handle)
 {
   if (remoteProcessId == vtkMultiProcessController::ANY_SOURCE)
@@ -296,27 +376,50 @@ int vtkMPICommunicatorNoBlockReceiveData(T* data, int length, int remoteProcessI
     remoteProcessId = MPI_ANY_SOURCE;
   }
 
-  return MPI_Irecv(data, length, datatype, remoteProcessId, tag, *(Handle), &req.Req->Handle);
+#ifdef VTKMPI_64BIT_LENGTH
+  return MPI_Irecv_c(data, length, datatype, remoteProcessId, tag, *(Handle), &req.Req->Handle);
+#else
+  if (!vtkMPICommunicatorCheckSize(length))
+  {
+    return 0;
+  }
+  return MPI_Irecv(
+    data, static_cast<int>(length), datatype, remoteProcessId, tag, *(Handle), &req.Req->Handle);
+#endif
 }
 //------------------------------------------------------------------------------
-int vtkMPICommunicatorReduceData(const void* sendBuffer, void* recvBuffer, vtkIdType length,
+int vtkMPICommunicatorReduceData(const void* sendBuffer, void* recvBuffer, vtkTypeInt64 length,
   int type, MPI_Op operation, int destProcessId, MPI_Comm* comm)
 {
-  if (!vtkMPICommunicatorCheckSize(length))
-    return 0;
   MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
-  return MPI_Reduce(
+#ifdef VTKMPI_64BIT_LENGTH
+  return MPI_Reduce_c(
     const_cast<void*>(sendBuffer), recvBuffer, length, mpiType, operation, destProcessId, *comm);
+#else
+  if (!vtkMPICommunicatorCheckSize(length))
+  {
+    return 0;
+  }
+  return MPI_Reduce(const_cast<void*>(sendBuffer), recvBuffer, static_cast<int>(length), mpiType,
+    operation, destProcessId, *comm);
+#endif
 }
 //------------------------------------------------------------------------------
-int vtkMPICommunicatorAllReduceData(const void* sendBuffer, void* recvBuffer, vtkIdType length,
+int vtkMPICommunicatorAllReduceData(const void* sendBuffer, void* recvBuffer, vtkTypeInt64 length,
   int type, MPI_Op operation, MPI_Comm* comm)
 {
+  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+#ifdef VTKMPI_64BIT_LENGTH
+  return MPI_Allreduce_c(
+    const_cast<void*>(sendBuffer), recvBuffer, length, mpiType, operation, *comm);
+#else
   if (!vtkMPICommunicatorCheckSize(length))
+  {
     return 0;
-  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+  }
   return MPI_Allreduce(
-    const_cast<void*>(sendBuffer), recvBuffer, length, mpiType, operation, *comm);
+    const_cast<void*>(sendBuffer), recvBuffer, static_cast<int>(length), mpiType, operation, *comm);
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -343,6 +446,46 @@ int vtkMPICommunicatorIprobe(int source, int tag, int* flag, int* actualSource,
   return retVal;
 }
 
+//------------------------------------------------------------------------------
+int vtkMPICommunicatorIprobe(int source, int tag, int* flag, int* actualSource,
+  MPI_Datatype datatype, vtkTypeInt64* size, MPI_Comm* handle)
+{
+  if (source == vtkMultiProcessController::ANY_SOURCE)
+  {
+    source = MPI_ANY_SOURCE;
+  }
+  MPI_Status status;
+  int retVal = MPI_Iprobe(source, tag, *handle, flag, &status);
+  if (retVal == MPI_SUCCESS && *flag == 1)
+  {
+    if (actualSource)
+    {
+      *actualSource = status.MPI_SOURCE;
+    }
+    if (size)
+    {
+#ifdef VTKMPI_64BIT_LENGTH
+      MPI_Count countSize = 0;
+      retVal = MPI_Get_count_c(&status, datatype, &countSize);
+      if (retVal == MPI_SUCCESS)
+      {
+        *size = countSize;
+      }
+      return retVal;
+#else
+      int intSize = 0;
+      retVal = MPI_Get_count(&status, datatype, &intSize);
+      if (retVal == MPI_SUCCESS)
+      {
+        *size = intSize;
+      }
+      return retVal;
+#endif
+    }
+  }
+  return retVal;
+}
+
 //------------------------------------------------------------------------------
 // Method for converting an MPI operation to a
 // vtkMultiProcessController::Operation.
@@ -777,6 +920,7 @@ int vtkMPICommunicator::SendVoidArray(
       break;
   }
 
+#ifndef VTKMPI_64BIT_LENGTH
   int maxSend = VTK_INT_MAX;
   while (length >= maxSend)
   {
@@ -789,6 +933,7 @@ int vtkMPICommunicator::SendVoidArray(
     byteData += maxSend * sizeOfType;
     length -= maxSend;
   }
+#endif
   return CheckForMPIError(vtkMPICommunicatorSendData(byteData, length, sizeOfType, remoteProcessId,
     tag, mpiType, this->MPIComm->Handle, vtkCommunicator::UseCopy, this->UseSsend));
 }
@@ -816,6 +961,25 @@ int vtkMPICommunicator::ReceiveVoidArray(
       break;
   }
 
+#ifdef VTKMPI_64BIT_LENGTH
+  vtkMPICommunicatorReceiveDataInfo info;
+  info.Handle = this->MPIComm->Handle;
+  info.DataType = mpiType;
+  if (CheckForMPIError(this->ReceiveDataInternal(byteData, maxlength, sizeOfType, remoteProcessId,
+        tag, &info, vtkCommunicator::UseCopy, this->LastSenderId)) != 0)
+  {
+    remoteProcessId = this->LastSenderId;
+
+    MPI_Count words_received = 0;
+    if (CheckForMPIError(MPI_Get_count_c(&info.Status, mpiType, &words_received)) == 0)
+    {
+      // Failed.
+      return 0;
+    }
+    this->Count += words_received;
+    return 1;
+  }
+#else
   // maxReceive is the maximum size of data that can be fetched in a one atomic
   // receive. If when sending the data-length >= maxReceive, then the sender
   // splits it into multiple packets of at most maxReceive size each.  (Note
@@ -849,6 +1013,7 @@ int vtkMPICommunicator::ReceiveVoidArray(
       return 1;
     }
   }
+#endif
   return 0;
 }
 
@@ -900,16 +1065,72 @@ int vtkMPICommunicator::NoBlockSend(
   return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
     data, length, remoteProcessId, tag, MPI_DOUBLE, req, this->MPIComm->Handle));
 }
-#ifdef VTK_USE_64BIT_IDS
 //------------------------------------------------------------------------------
 int vtkMPICommunicator::NoBlockSend(
-  const vtkIdType* data, int length, int remoteProcessId, int tag, Request& req)
+  const vtkTypeInt64* data, int length, int remoteProcessId, int tag, Request& req)
 {
 
   return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(data, length, remoteProcessId, tag,
-    vtkMPICommunicatorGetMPIType(VTK_ID_TYPE), req, this->MPIComm->Handle));
+    vtkMPICommunicatorGetMPIType(VTK_LONG_LONG), req, this->MPIComm->Handle));
+}
+
+// vtkTypeInt64 versions
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const int* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_INT, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const unsigned long* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_UNSIGNED_LONG, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_CHAR, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const unsigned char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_UNSIGNED_CHAR, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const float* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_FLOAT, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const double* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(
+    data, length, remoteProcessId, tag, MPI_DOUBLE, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockSend(
+  const vtkTypeInt64* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockSendData(data, length, remoteProcessId, tag,
+    vtkMPICommunicatorGetMPIType(VTK_LONG_LONG), req, this->MPIComm->Handle));
 }
-#endif
 
 //------------------------------------------------------------------------------
 int vtkMPICommunicator::NoBlockReceive(
@@ -959,16 +1180,72 @@ int vtkMPICommunicator::NoBlockReceive(
   return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
     data, length, remoteProcessId, tag, MPI_DOUBLE, req, this->MPIComm->Handle));
 }
-#ifdef VTK_USE_64BIT_IDS
 //------------------------------------------------------------------------------
 int vtkMPICommunicator::NoBlockReceive(
-  vtkIdType* data, int length, int remoteProcessId, int tag, Request& req)
+  vtkTypeInt64* data, int length, int remoteProcessId, int tag, Request& req)
 {
 
   return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(data, length, remoteProcessId, tag,
-    vtkMPICommunicatorGetMPIType(VTK_ID_TYPE), req, this->MPIComm->Handle));
+    vtkMPICommunicatorGetMPIType(VTK_LONG_LONG), req, this->MPIComm->Handle));
+}
+
+// vtkTypeInt64 versions
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  int* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_INT, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  unsigned long* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_UNSIGNED_LONG, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_CHAR, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  unsigned char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_UNSIGNED_CHAR, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  float* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_FLOAT, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  double* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(
+    data, length, remoteProcessId, tag, MPI_DOUBLE, req, this->MPIComm->Handle));
+}
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::NoBlockReceive(
+  vtkTypeInt64* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req)
+{
+
+  return CheckForMPIError(vtkMPICommunicatorNoBlockReceiveData(data, length, remoteProcessId, tag,
+    vtkMPICommunicatorGetMPIType(VTK_LONG_LONG), req, this->MPIComm->Handle));
 }
-#endif
 
 //------------------------------------------------------------------------------
 vtkMPICommunicator::Request::Request()
@@ -1069,10 +1346,17 @@ void vtkMPICommunicator::Barrier()
 int vtkMPICommunicator::BroadcastVoidArray(void* data, vtkIdType length, int type, int root)
 {
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
+#ifdef VTKMPI_64BIT_LENGTH
+  return CheckForMPIError(
+    MPI_Bcast_c(data, length, vtkMPICommunicatorGetMPIType(type), root, *this->MPIComm->Handle));
+#else
   if (!vtkMPICommunicatorCheckSize(length))
+  {
     return 0;
+  }
   return CheckForMPIError(
     MPI_Bcast(data, length, vtkMPICommunicatorGetMPIType(type), root, *this->MPIComm->Handle));
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1082,11 +1366,18 @@ int vtkMPICommunicator::GatherVoidArray(
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
   int numProc;
   MPI_Comm_size(*this->MPIComm->Handle, &numProc);
+  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+#ifdef VTKMPI_64BIT_LENGTH
+  return CheckForMPIError(MPI_Gather_c(const_cast<void*>(sendBuffer), length, mpiType, recvBuffer,
+    length, mpiType, destProcessId, *this->MPIComm->Handle));
+#else
   if (!vtkMPICommunicatorCheckSize(length * numProc))
+  {
     return 0;
-  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+  }
   return CheckForMPIError(MPI_Gather(const_cast<void*>(sendBuffer), length, mpiType, recvBuffer,
     length, mpiType, destProcessId, *this->MPIComm->Handle));
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1094,8 +1385,12 @@ int vtkMPICommunicator::GatherVVoidArray(const void* sendBuffer, void* recvBuffe
   vtkIdType sendLength, vtkIdType* recvLengths, vtkIdType* offsets, int type, int destProcessId)
 {
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
+#ifndef VTKMPI_64BIT_LENGTH
   if (!vtkMPICommunicatorCheckSize(sendLength))
+  {
     return 0;
+  }
+#endif
   MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
   // We have to jump through several hoops to make sure vtkIdType arrays
   // become int arrays.
@@ -1120,18 +1415,37 @@ int vtkMPICommunicator::GatherVVoidArray(const void* sendBuffer, void* recvBuffe
       return 1;
     }
 #endif // OPEN_MPI
-    std::vector<int> mpiRecvLengths, mpiOffsets;
+#ifdef VTKMPI_64BIT_LENGTH
+    std::vector<MPI_Count> mpiRecvLengths;
+    std::vector<MPI_Aint> mpiOffsets;
+#else
+    std::vector<int> mpiRecvLengths;
+    std::vector<int> mpiOffsets;
+#endif
     mpiRecvLengths.resize(numProc);
     mpiOffsets.resize(numProc);
     for (int i = 0; i < numProc; i++)
     {
+#ifndef VTKMPI_64BIT_LENGTH
       if (!vtkMPICommunicatorCheckSize(recvLengths[i] + offsets[i]))
       {
         return 0;
       }
+#endif
       mpiRecvLengths[i] = recvLengths[i];
       mpiOffsets[i] = offsets[i];
     }
+#ifdef VTKMPI_64BIT_LENGTH
+    return CheckForMPIError(
+      MPI_Gatherv_c(const_cast<void*>(sendBuffer), sendLength, mpiType, recvBuffer,
+        mpiRecvLengths.data(), mpiOffsets.data(), mpiType, destProcessId, *this->MPIComm->Handle));
+  }
+  else
+  {
+    return CheckForMPIError(MPI_Gatherv_c(const_cast<void*>(sendBuffer), sendLength, mpiType,
+      nullptr, nullptr, nullptr, mpiType, destProcessId, *this->MPIComm->Handle));
+  }
+#else
     return CheckForMPIError(
       MPI_Gatherv(const_cast<void*>(sendBuffer), sendLength, mpiType, recvBuffer,
         mpiRecvLengths.data(), mpiOffsets.data(), mpiType, destProcessId, *this->MPIComm->Handle));
@@ -1141,6 +1455,7 @@ int vtkMPICommunicator::GatherVVoidArray(const void* sendBuffer, void* recvBuffe
     return CheckForMPIError(MPI_Gatherv(const_cast<void*>(sendBuffer), sendLength, mpiType, nullptr,
       nullptr, nullptr, mpiType, destProcessId, *this->MPIComm->Handle));
   }
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1148,11 +1463,18 @@ int vtkMPICommunicator::ScatterVoidArray(
   const void* sendBuffer, void* recvBuffer, vtkIdType length, int type, int srcProcessId)
 {
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
+  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+#ifdef VTKMPI_64BIT_LENGTH
+  return CheckForMPIError(MPI_Scatter_c(const_cast<void*>(sendBuffer), length, mpiType, recvBuffer,
+    length, mpiType, srcProcessId, *this->MPIComm->Handle));
+#else
   if (!vtkMPICommunicatorCheckSize(length))
+  {
     return 0;
-  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+  }
   return CheckForMPIError(MPI_Scatter(const_cast<void*>(sendBuffer), length, mpiType, recvBuffer,
     length, mpiType, srcProcessId, *this->MPIComm->Handle));
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1160,8 +1482,12 @@ int vtkMPICommunicator::ScatterVVoidArray(const void* sendBuffer, void* recvBuff
   vtkIdType* sendLengths, vtkIdType* offsets, vtkIdType recvLength, int type, int srcProcessId)
 {
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
+#ifndef VTKMPI_64BIT_LENGTH
   if (!vtkMPICommunicatorCheckSize(recvLength))
+  {
     return 0;
+  }
+#endif
   MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
   // We have to jump through several hoops to make sure vtkIdType arrays
   // become int arrays.
@@ -1186,18 +1512,38 @@ int vtkMPICommunicator::ScatterVVoidArray(const void* sendBuffer, void* recvBuff
       return 1;
     }
 #endif // OPEN_MPI
-    std::vector<int> mpiSendLengths, mpiOffsets;
+
+#ifdef VTKMPI_64BIT_LENGTH
+    std::vector<MPI_Count> mpiSendLengths;
+    std::vector<MPI_Aint> mpiOffsets;
+#else
+    std::vector<int> mpiSendLengths;
+    std::vector<int> mpiOffsets;
+#endif
     mpiSendLengths.resize(numProc);
     mpiOffsets.resize(numProc);
     for (int i = 0; i < numProc; i++)
     {
+#ifndef VTKMPI_64BIT_LENGTH
       if (!vtkMPICommunicatorCheckSize(sendLengths[i] + offsets[i]))
       {
         return 0;
       }
+#endif
       mpiSendLengths[i] = sendLengths[i];
       mpiOffsets[i] = offsets[i];
     }
+#ifdef VTKMPI_64BIT_LENGTH
+    return CheckForMPIError(
+      MPI_Scatterv_c(const_cast<void*>(sendBuffer), mpiSendLengths.data(), mpiOffsets.data(),
+        mpiType, recvBuffer, recvLength, mpiType, srcProcessId, *this->MPIComm->Handle));
+  }
+  else
+  {
+    return CheckForMPIError(MPI_Scatterv_c(nullptr, nullptr, nullptr, mpiType, recvBuffer,
+      recvLength, mpiType, srcProcessId, *this->MPIComm->Handle));
+  }
+#else
     return CheckForMPIError(
       MPI_Scatterv(const_cast<void*>(sendBuffer), mpiSendLengths.data(), mpiOffsets.data(), mpiType,
         recvBuffer, recvLength, mpiType, srcProcessId, *this->MPIComm->Handle));
@@ -1207,6 +1553,7 @@ int vtkMPICommunicator::ScatterVVoidArray(const void* sendBuffer, void* recvBuff
     return CheckForMPIError(MPI_Scatterv(nullptr, nullptr, nullptr, mpiType, recvBuffer, recvLength,
       mpiType, srcProcessId, *this->MPIComm->Handle));
   }
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1216,11 +1563,18 @@ int vtkMPICommunicator::AllGatherVoidArray(
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
   int numProc;
   MPI_Comm_size(*this->MPIComm->Handle, &numProc);
+  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+#ifdef VTKMPI_64BIT_LENGTH
+  return CheckForMPIError(MPI_Allgather_c(const_cast<void*>(sendBuffer), length, mpiType,
+    recvBuffer, length, mpiType, *this->MPIComm->Handle));
+#else
   if (!vtkMPICommunicatorCheckSize(length * numProc))
+  {
     return 0;
-  MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
+  }
   return CheckForMPIError(MPI_Allgather(const_cast<void*>(sendBuffer), length, mpiType, recvBuffer,
     length, mpiType, *this->MPIComm->Handle));
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1228,8 +1582,12 @@ int vtkMPICommunicator::AllGatherVVoidArray(const void* sendBuffer, void* recvBu
   vtkIdType sendLength, vtkIdType* recvLengths, vtkIdType* offsets, int type)
 {
   vtkMPICommunicatorDebugBarrier(this->MPIComm->Handle);
+#ifndef VTKMPI_64BIT_LENGTH
   if (!vtkMPICommunicatorCheckSize(sendLength))
+  {
     return 0;
+  }
+#endif
   MPI_Datatype mpiType = vtkMPICommunicatorGetMPIType(type);
   // We have to jump through several hoops to make sure vtkIdType arrays
   // become int arrays.
@@ -1265,20 +1623,33 @@ int vtkMPICommunicator::AllGatherVVoidArray(const void* sendBuffer, void* recvBu
     }
   }
 #endif // OPEN_MPI
-  std::vector<int> mpiRecvLengths, mpiOffsets;
+#ifdef VTKMPI_64BIT_LENGTH
+  std::vector<MPI_Count> mpiRecvLengths;
+  std::vector<MPI_Aint> mpiOffsets;
+#else
+  std::vector<int> mpiRecvLengths;
+  std::vector<int> mpiOffsets;
+#endif
   mpiRecvLengths.resize(numProc);
   mpiOffsets.resize(numProc);
   for (int i = 0; i < numProc; i++)
   {
+#ifndef VTKMPI_64BIT_LENGTH
     if (!vtkMPICommunicatorCheckSize(recvLengths[i] + offsets[i]))
     {
       return 0;
     }
+#endif
     mpiRecvLengths[i] = recvLengths[i];
     mpiOffsets[i] = offsets[i];
   }
+#ifdef VTKMPI_64BIT_LENGTH
+  return CheckForMPIError(MPI_Allgatherv_c(const_cast<void*>(sendBuffer), sendLength, mpiType,
+    recvBuffer, mpiRecvLengths.data(), mpiOffsets.data(), mpiType, *this->MPIComm->Handle));
+#else
   return CheckForMPIError(MPI_Allgatherv(const_cast<void*>(sendBuffer), sendLength, mpiType,
     recvBuffer, mpiRecvLengths.data(), mpiOffsets.data(), mpiType, *this->MPIComm->Handle));
+#endif
 }
 
 //------------------------------------------------------------------------------
@@ -1536,7 +1907,7 @@ int vtkMPICommunicator::TestSome(int count, Request requests[], int& NCompleted,
 int vtkMPICommunicator::Iprobe(int source, int tag, int* flag, int* actualSource)
 {
   return CheckForMPIError(vtkMPICommunicatorIprobe(
-    source, tag, flag, actualSource, MPI_INT, nullptr, this->MPIComm->Handle));
+    source, tag, flag, actualSource, MPI_INT, (vtkIdType*)nullptr, this->MPIComm->Handle));
 }
 
 //------------------------------------------------------------------------------
@@ -1578,4 +1949,44 @@ int vtkMPICommunicator::Iprobe(
   return CheckForMPIError(vtkMPICommunicatorIprobe(
     source, tag, flag, actualSource, MPI_DOUBLE, size, this->MPIComm->Handle));
 }
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::Iprobe(
+  int source, int tag, int* flag, int* actualSource, int* vtkNotUsed(type), vtkTypeInt64* size)
+{
+  return CheckForMPIError(vtkMPICommunicatorIprobe(
+    source, tag, flag, actualSource, MPI_INT, size, this->MPIComm->Handle));
+}
+
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::Iprobe(int source, int tag, int* flag, int* actualSource,
+  unsigned long* vtkNotUsed(type), vtkTypeInt64* size)
+{
+  return CheckForMPIError(vtkMPICommunicatorIprobe(
+    source, tag, flag, actualSource, MPI_UNSIGNED_LONG, size, this->MPIComm->Handle));
+}
+
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::Iprobe(int source, int tag, int* flag, int* actualSource,
+  const char* vtkNotUsed(type), vtkTypeInt64* size)
+{
+  return CheckForMPIError(vtkMPICommunicatorIprobe(
+    source, tag, flag, actualSource, MPI_CHAR, size, this->MPIComm->Handle));
+}
+
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::Iprobe(
+  int source, int tag, int* flag, int* actualSource, float* vtkNotUsed(type), vtkTypeInt64* size)
+{
+  return CheckForMPIError(vtkMPICommunicatorIprobe(
+    source, tag, flag, actualSource, MPI_FLOAT, size, this->MPIComm->Handle));
+}
+
+//------------------------------------------------------------------------------
+int vtkMPICommunicator::Iprobe(
+  int source, int tag, int* flag, int* actualSource, double* vtkNotUsed(type), vtkTypeInt64* size)
+{
+  return CheckForMPIError(vtkMPICommunicatorIprobe(
+    source, tag, flag, actualSource, MPI_DOUBLE, size, this->MPIComm->Handle));
+}
+
 VTK_ABI_NAMESPACE_END
diff --git a/Parallel/MPI/vtkMPICommunicator.h b/Parallel/MPI/vtkMPICommunicator.h
index 83dda50c88cd99fc2767c9bdb4ef63c301bfdb4f..eab6ae3883195b11899a0ec1b24a58ef51bfe3da 100644
--- a/Parallel/MPI/vtkMPICommunicator.h
+++ b/Parallel/MPI/vtkMPICommunicator.h
@@ -119,9 +119,21 @@ public:
     const unsigned char* data, int length, int remoteProcessId, int tag, Request& req);
   int NoBlockSend(const float* data, int length, int remoteProcessId, int tag, Request& req);
   int NoBlockSend(const double* data, int length, int remoteProcessId, int tag, Request& req);
-#ifdef VTK_USE_64BIT_IDS
-  int NoBlockSend(const vtkIdType* data, int length, int remoteProcessId, int tag, Request& req);
-#endif
+  int NoBlockSend(const vtkTypeInt64* data, int length, int remoteProcessId, int tag, Request& req);
+
+  int NoBlockSend(const int* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const unsigned long* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const unsigned char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const float* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const double* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockSend(
+    const vtkTypeInt64* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
   ///@}
 
   ///@{
@@ -138,9 +150,18 @@ public:
   int NoBlockReceive(unsigned char* data, int length, int remoteProcessId, int tag, Request& req);
   int NoBlockReceive(float* data, int length, int remoteProcessId, int tag, Request& req);
   int NoBlockReceive(double* data, int length, int remoteProcessId, int tag, Request& req);
-#ifdef VTK_USE_64BIT_IDS
-  int NoBlockReceive(vtkIdType* data, int length, int remoteProcessId, int tag, Request& req);
-#endif
+  int NoBlockReceive(vtkTypeInt64* data, int length, int remoteProcessId, int tag, Request& req);
+
+  int NoBlockReceive(int* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(
+    unsigned long* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(
+    unsigned char* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(float* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(double* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
+  int NoBlockReceive(
+    vtkTypeInt64* data, vtkTypeInt64 length, int remoteProcessId, int tag, Request& req);
   ///@}
 
   ///@{
@@ -189,6 +210,14 @@ public:
   int Iprobe(int source, int tag, int* flag, int* actualSource, const char* type, int* size);
   int Iprobe(int source, int tag, int* flag, int* actualSource, float* type, int* size);
   int Iprobe(int source, int tag, int* flag, int* actualSource, double* type, int* size);
+
+  int Iprobe(int source, int tag, int* flag, int* actualSource, int* type, vtkTypeInt64* size);
+  int Iprobe(
+    int source, int tag, int* flag, int* actualSource, unsigned long* type, vtkTypeInt64* size);
+  int Iprobe(
+    int source, int tag, int* flag, int* actualSource, const char* type, vtkTypeInt64* size);
+  int Iprobe(int source, int tag, int* flag, int* actualSource, float* type, vtkTypeInt64* size);
+  int Iprobe(int source, int tag, int* flag, int* actualSource, double* type, vtkTypeInt64* size);
   ///@}
 
   /**
@@ -299,11 +328,16 @@ protected:
    */
   void Duplicate(vtkMPICommunicator* source);
 
+  ///@{
   /**
    * Implementation for receive data.
    */
   virtual int ReceiveDataInternal(char* data, int length, int sizeoftype, int remoteProcessId,
     int tag, vtkMPICommunicatorReceiveDataInfo* info, int useCopy, int& senderId);
+  virtual int ReceiveDataInternal(char* data, vtkTypeInt64 length, int sizeoftype,
+    int remoteProcessId, int tag, vtkMPICommunicatorReceiveDataInfo* info, int useCopy,
+    int& senderId);
+  ///@}
 
   vtkMPICommunicatorOpaqueComm* MPIComm;