mpi.f90 Source File


Files dependent on this one

sourcefile~~mpi.f90~~AfferentGraph sourcefile~mpi.f90 mpi.f90 sourcefile~backend.f90~2 backend.f90 sourcefile~backend.f90~2->sourcefile~mpi.f90 sourcefile~common.f90~2 common.f90 sourcefile~backend.f90~2->sourcefile~common.f90~2 sourcefile~mesh.f90 mesh.f90 sourcefile~backend.f90~2->sourcefile~mesh.f90 sourcefile~sendrecv.f90 sendrecv.f90 sourcefile~backend.f90~2->sourcefile~sendrecv.f90 sourcefile~allocator.f90~2 allocator.f90 sourcefile~backend.f90~2->sourcefile~allocator.f90~2 sourcefile~backend.f90 backend.f90 sourcefile~backend.f90~2->sourcefile~backend.f90 sourcefile~exec_dist.f90 exec_dist.f90 sourcefile~backend.f90~2->sourcefile~exec_dist.f90 sourcefile~exec_thom.f90 exec_thom.f90 sourcefile~backend.f90~2->sourcefile~exec_thom.f90 sourcefile~field.f90 field.f90 sourcefile~backend.f90~2->sourcefile~field.f90 sourcefile~ordering.f90 ordering.f90 sourcefile~backend.f90~2->sourcefile~ordering.f90 sourcefile~poisson_fft.f90~3 poisson_fft.f90 sourcefile~backend.f90~2->sourcefile~poisson_fft.f90~3 sourcefile~tdsops.f90~2 tdsops.f90 sourcefile~backend.f90~2->sourcefile~tdsops.f90~2 sourcefile~backend.f90~3 backend.f90 sourcefile~backend.f90~3->sourcefile~mpi.f90 sourcefile~backend.f90~3->sourcefile~backend.f90~2 sourcefile~backend.f90~3->sourcefile~common.f90~2 sourcefile~backend.f90~3->sourcefile~mesh.f90 sourcefile~allocator.f90 allocator.f90 sourcefile~backend.f90~3->sourcefile~allocator.f90 sourcefile~backend.f90~3->sourcefile~allocator.f90~2 sourcefile~backend.f90~3->sourcefile~field.f90 sourcefile~backend.f90~3->sourcefile~ordering.f90 sourcefile~backend.f90~4 backend.f90 sourcefile~backend.f90~4->sourcefile~mpi.f90 sourcefile~backend.f90~4->sourcefile~common.f90~2 sourcefile~backend.f90~4->sourcefile~mesh.f90 sourcefile~poisson_fft.f90 poisson_fft.f90 sourcefile~backend.f90~4->sourcefile~poisson_fft.f90 sourcefile~sendrecv.f90~2 sendrecv.f90 sourcefile~backend.f90~4->sourcefile~sendrecv.f90~2 sourcefile~backend.f90~4->sourcefile~allocator.f90~2 sourcefile~allocator.f90~3 allocator.f90 sourcefile~backend.f90~4->sourcefile~allocator.f90~3 sourcefile~backend.f90~4->sourcefile~backend.f90 sourcefile~distributed.f90 distributed.f90 sourcefile~backend.f90~4->sourcefile~distributed.f90 sourcefile~exec_dist.f90~2 exec_dist.f90 sourcefile~backend.f90~4->sourcefile~exec_dist.f90~2 sourcefile~exec_thom.f90~2 exec_thom.f90 sourcefile~backend.f90~4->sourcefile~exec_thom.f90~2 sourcefile~backend.f90~4->sourcefile~field.f90 sourcefile~fieldops.f90 fieldops.f90 sourcefile~backend.f90~4->sourcefile~fieldops.f90 sourcefile~reorder.f90 reorder.f90 sourcefile~backend.f90~4->sourcefile~reorder.f90 sourcefile~tdsops.f90 tdsops.f90 sourcefile~backend.f90~4->sourcefile~tdsops.f90 sourcefile~backend.f90~4->sourcefile~tdsops.f90~2 sourcefile~base_case.f90 base_case.f90 sourcefile~base_case.f90->sourcefile~mpi.f90 sourcefile~base_case.f90->sourcefile~common.f90~2 sourcefile~io_manager.f90 io_manager.f90 sourcefile~base_case.f90->sourcefile~io_manager.f90 sourcefile~base_case.f90->sourcefile~mesh.f90 sourcefile~base_case.f90->sourcefile~allocator.f90~2 sourcefile~base_case.f90->sourcefile~backend.f90 sourcefile~config.f90 config.f90 sourcefile~base_case.f90->sourcefile~config.f90 sourcefile~base_case.f90->sourcefile~field.f90 sourcefile~monitoring.f90 monitoring.f90 sourcefile~base_case.f90->sourcefile~monitoring.f90 sourcefile~postprocess.f90 postprocess.f90 sourcefile~base_case.f90->sourcefile~postprocess.f90 sourcefile~solver.f90 solver.f90 sourcefile~base_case.f90->sourcefile~solver.f90 sourcefile~channel.f90 channel.f90 sourcefile~channel.f90->sourcefile~mpi.f90 sourcefile~channel.f90->sourcefile~base_case.f90 sourcefile~channel.f90->sourcefile~common.f90~2 sourcefile~channel.f90->sourcefile~mesh.f90 sourcefile~channel.f90->sourcefile~allocator.f90~2 sourcefile~channel.f90->sourcefile~backend.f90 sourcefile~channel.f90->sourcefile~config.f90 sourcefile~channel.f90->sourcefile~field.f90 sourcefile~channel.f90->sourcefile~solver.f90 sourcefile~checkpoint_manager.f90 checkpoint_manager.f90 sourcefile~checkpoint_manager.f90->sourcefile~mpi.f90 sourcefile~checkpoint_manager.f90->sourcefile~common.f90~2 sourcefile~io.f90 io.f90 sourcefile~checkpoint_manager.f90->sourcefile~io.f90 sourcefile~stats.f90 stats.f90 sourcefile~checkpoint_manager.f90->sourcefile~stats.f90 sourcefile~checkpoint_manager.f90->sourcefile~config.f90 sourcefile~checkpoint_manager.f90->sourcefile~field.f90 sourcefile~io_field_utils.f90 io_field_utils.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_field_utils.f90 sourcefile~io_session.f90 io_session.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_session.f90 sourcefile~checkpoint_manager.f90->sourcefile~solver.f90 sourcefile~checkpoint_state.f90 checkpoint_state.f90 sourcefile~checkpoint_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~common.f90~2->sourcefile~mpi.f90 sourcefile~cylinder.f90 cylinder.f90 sourcefile~cylinder.f90->sourcefile~mpi.f90 sourcefile~cylinder.f90->sourcefile~base_case.f90 sourcefile~cylinder.f90->sourcefile~common.f90~2 sourcefile~cylinder.f90->sourcefile~mesh.f90 sourcefile~cylinder.f90->sourcefile~allocator.f90~2 sourcefile~cylinder.f90->sourcefile~backend.f90 sourcefile~cylinder.f90->sourcefile~config.f90 sourcefile~cylinder.f90->sourcefile~field.f90 sourcefile~cylinder.f90->sourcefile~solver.f90 sourcefile~decomp_2decompfft.f90 decomp_2decompfft.f90 sourcefile~decomp_2decompfft.f90->sourcefile~mpi.f90 sourcefile~mesh_content.f90 mesh_content.f90 sourcefile~decomp_2decompfft.f90->sourcefile~mesh_content.f90 sourcefile~ibm.f90 ibm.f90 sourcefile~ibm.f90->sourcefile~mpi.f90 sourcefile~ibm.f90->sourcefile~common.f90~2 sourcefile~ibm.f90->sourcefile~mesh.f90 sourcefile~ibm.f90->sourcefile~allocator.f90~2 sourcefile~ibm.f90->sourcefile~backend.f90 sourcefile~ibm.f90->sourcefile~field.f90 sourcefile~ibm.f90->sourcefile~io_session.f90 sourcefile~io.f90->sourcefile~mpi.f90 sourcefile~io.f90->sourcefile~common.f90~2 sourcefile~io.f90->sourcefile~backend.f90 sourcefile~io.f90->sourcefile~field.f90 sourcefile~io_base.f90 io_base.f90 sourcefile~io.f90->sourcefile~io_base.f90 sourcefile~io_manager.f90->sourcefile~mpi.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_manager.f90 sourcefile~snapshot_manager.f90 snapshot_manager.f90 sourcefile~io_manager.f90->sourcefile~snapshot_manager.f90 sourcefile~io_manager.f90->sourcefile~stats.f90 sourcefile~io_manager.f90->sourcefile~solver.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~mesh.f90->sourcefile~mpi.f90 sourcefile~mesh.f90->sourcefile~common.f90~2 sourcefile~mesh.f90->sourcefile~field.f90 sourcefile~mesh.f90->sourcefile~mesh_content.f90 sourcefile~decomp_dummy.f90 decomp_dummy.f90 sourcefile~mesh.f90->sourcefile~decomp_dummy.f90 sourcefile~poisson_fft.f90->sourcefile~mpi.f90 sourcefile~poisson_fft.f90->sourcefile~common.f90~2 sourcefile~poisson_fft.f90->sourcefile~mesh.f90 sourcefile~poisson_fft.f90->sourcefile~sendrecv.f90~2 sourcefile~poisson_fft.f90->sourcefile~allocator.f90~3 sourcefile~poisson_fft.f90->sourcefile~field.f90 sourcefile~poisson_fft.f90~2 poisson_fft.f90 sourcefile~poisson_fft.f90->sourcefile~poisson_fft.f90~2 sourcefile~spectral_processing.f90 spectral_processing.f90 sourcefile~poisson_fft.f90->sourcefile~spectral_processing.f90 sourcefile~poisson_fft.f90->sourcefile~tdsops.f90~2 sourcefile~sendrecv.f90->sourcefile~mpi.f90 sourcefile~sendrecv.f90->sourcefile~common.f90~2 sourcefile~sendrecv.f90~2->sourcefile~mpi.f90 sourcefile~sendrecv.f90~2->sourcefile~common.f90~2 sourcefile~snapshot_manager.f90->sourcefile~mpi.f90 sourcefile~snapshot_manager.f90->sourcefile~common.f90~2 sourcefile~snapshot_manager.f90->sourcefile~io.f90 sourcefile~snapshot_manager.f90->sourcefile~config.f90 sourcefile~snapshot_manager.f90->sourcefile~field.f90 sourcefile~snapshot_manager.f90->sourcefile~io_field_utils.f90 sourcefile~snapshot_manager.f90->sourcefile~io_session.f90 sourcefile~snapshot_manager.f90->sourcefile~solver.f90 sourcefile~stats.f90->sourcefile~mpi.f90 sourcefile~stats.f90->sourcefile~common.f90~2 sourcefile~stats.f90->sourcefile~config.f90 sourcefile~stats.f90->sourcefile~field.f90 sourcefile~stats.f90->sourcefile~io_session.f90 sourcefile~stats.f90->sourcefile~solver.f90 sourcefile~xcompact.f90 xcompact.f90 sourcefile~xcompact.f90->sourcefile~mpi.f90 sourcefile~xcompact.f90->sourcefile~backend.f90~2 sourcefile~xcompact.f90->sourcefile~backend.f90~4 sourcefile~xcompact.f90->sourcefile~base_case.f90 sourcefile~xcompact.f90->sourcefile~channel.f90 sourcefile~xcompact.f90->sourcefile~common.f90~2 sourcefile~xcompact.f90->sourcefile~cylinder.f90 sourcefile~xcompact.f90->sourcefile~mesh.f90 sourcefile~xcompact.f90->sourcefile~allocator.f90~2 sourcefile~xcompact.f90->sourcefile~allocator.f90~3 sourcefile~xcompact.f90->sourcefile~backend.f90 sourcefile~xcompact.f90->sourcefile~config.f90 sourcefile~generic.f90 generic.f90 sourcefile~xcompact.f90->sourcefile~generic.f90 sourcefile~tgv.f90 tgv.f90 sourcefile~xcompact.f90->sourcefile~tgv.f90 sourcefile~allocator.f90->sourcefile~common.f90~2 sourcefile~allocator.f90->sourcefile~mesh.f90 sourcefile~allocator.f90->sourcefile~allocator.f90~2 sourcefile~allocator.f90->sourcefile~field.f90 sourcefile~allocator.f90~2->sourcefile~common.f90~2 sourcefile~allocator.f90~2->sourcefile~field.f90 sourcefile~allocator.f90~3->sourcefile~common.f90~2 sourcefile~allocator.f90~3->sourcefile~mesh.f90 sourcefile~allocator.f90~3->sourcefile~allocator.f90~2 sourcefile~allocator.f90~3->sourcefile~field.f90 sourcefile~backend.f90->sourcefile~common.f90~2 sourcefile~backend.f90->sourcefile~mesh.f90 sourcefile~backend.f90->sourcefile~allocator.f90~2 sourcefile~backend.f90->sourcefile~field.f90 sourcefile~backend.f90->sourcefile~poisson_fft.f90~2 sourcefile~backend.f90->sourcefile~tdsops.f90~2 sourcefile~config.f90->sourcefile~common.f90~2 sourcefile~distributed.f90->sourcefile~common.f90~2 sourcefile~distributed.f90~2 distributed.f90 sourcefile~distributed.f90~2->sourcefile~common.f90~2 sourcefile~exec_dist.f90->sourcefile~common.f90~2 sourcefile~exec_dist.f90->sourcefile~sendrecv.f90 sourcefile~exec_dist.f90->sourcefile~distributed.f90~2 sourcefile~exec_dist.f90->sourcefile~tdsops.f90~2 sourcefile~exec_dist.f90~2->sourcefile~common.f90~2 sourcefile~exec_dist.f90~2->sourcefile~sendrecv.f90~2 sourcefile~exec_dist.f90~2->sourcefile~distributed.f90 sourcefile~exec_dist.f90~2->sourcefile~tdsops.f90 sourcefile~exec_thom.f90->sourcefile~common.f90~2 sourcefile~exec_thom.f90->sourcefile~tdsops.f90~2 sourcefile~thomas.f90 thomas.f90 sourcefile~exec_thom.f90->sourcefile~thomas.f90 sourcefile~exec_thom.f90~2->sourcefile~common.f90~2 sourcefile~exec_thom.f90~2->sourcefile~tdsops.f90 sourcefile~thomas.f90~2 thomas.f90 sourcefile~exec_thom.f90~2->sourcefile~thomas.f90~2 sourcefile~field.f90->sourcefile~common.f90~2 sourcefile~fieldops.f90->sourcefile~common.f90~2 sourcefile~generic.f90->sourcefile~base_case.f90 sourcefile~generic.f90->sourcefile~common.f90~2 sourcefile~generic.f90->sourcefile~mesh.f90 sourcefile~generic.f90->sourcefile~allocator.f90~2 sourcefile~generic.f90->sourcefile~backend.f90 sourcefile~generic.f90->sourcefile~field.f90 sourcefile~generic.f90->sourcefile~solver.f90 sourcefile~io.f90~2 io.f90 sourcefile~io.f90~2->sourcefile~common.f90~2 sourcefile~io.f90~2->sourcefile~backend.f90 sourcefile~io.f90~2->sourcefile~field.f90 sourcefile~io.f90~2->sourcefile~io_base.f90 sourcefile~io_base.f90->sourcefile~common.f90~2 sourcefile~io_base.f90->sourcefile~backend.f90 sourcefile~io_base.f90->sourcefile~field.f90 sourcefile~io_field_utils.f90->sourcefile~common.f90~2 sourcefile~io_field_utils.f90->sourcefile~field.f90 sourcefile~io_field_utils.f90->sourcefile~io_base.f90 sourcefile~io_field_utils.f90->sourcefile~solver.f90 sourcefile~io_session.f90->sourcefile~common.f90~2 sourcefile~io_session.f90->sourcefile~io.f90 sourcefile~io_session.f90->sourcefile~backend.f90 sourcefile~io_session.f90->sourcefile~field.f90 sourcefile~io_session.f90->sourcefile~io_base.f90 sourcefile~les.f90 les.f90 sourcefile~les.f90->sourcefile~common.f90~2 sourcefile~les.f90->sourcefile~mesh.f90 sourcefile~les.f90->sourcefile~backend.f90 sourcefile~les.f90->sourcefile~config.f90 sourcefile~les.f90->sourcefile~field.f90 sourcefile~les.f90->sourcefile~tdsops.f90~2 sourcefile~mesh_content.f90->sourcefile~common.f90~2 sourcefile~monitoring.f90->sourcefile~common.f90~2 sourcefile~monitoring.f90->sourcefile~field.f90 sourcefile~scalar_series.f90 scalar_series.f90 sourcefile~monitoring.f90->sourcefile~scalar_series.f90 sourcefile~monitoring.f90->sourcefile~solver.f90 sourcefile~ordering.f90->sourcefile~common.f90~2 sourcefile~poisson_fft.f90~2->sourcefile~common.f90~2 sourcefile~poisson_fft.f90~2->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~2->sourcefile~field.f90 sourcefile~poisson_fft.f90~2->sourcefile~tdsops.f90~2 sourcefile~poisson_fft.f90~3->sourcefile~common.f90~2 sourcefile~poisson_fft.f90~3->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~3->sourcefile~field.f90 sourcefile~poisson_fft.f90~3->sourcefile~poisson_fft.f90~2 sourcefile~spectral_processing.f90~2 spectral_processing.f90 sourcefile~poisson_fft.f90~3->sourcefile~spectral_processing.f90~2 sourcefile~poisson_fft.f90~3->sourcefile~tdsops.f90~2 sourcefile~postprocess.f90->sourcefile~common.f90~2 sourcefile~postprocess.f90->sourcefile~field.f90 sourcefile~postprocess.f90->sourcefile~solver.f90 sourcefile~reorder.f90->sourcefile~common.f90~2 sourcefile~scalar_series.f90->sourcefile~common.f90~2 sourcefile~solver.f90->sourcefile~common.f90~2 sourcefile~solver.f90->sourcefile~ibm.f90 sourcefile~solver.f90->sourcefile~mesh.f90 sourcefile~solver.f90->sourcefile~allocator.f90~2 sourcefile~solver.f90->sourcefile~backend.f90 sourcefile~solver.f90->sourcefile~config.f90 sourcefile~solver.f90->sourcefile~field.f90 sourcefile~solver.f90->sourcefile~les.f90 sourcefile~solver.f90->sourcefile~tdsops.f90~2 sourcefile~time_integrator.f90 time_integrator.f90 sourcefile~solver.f90->sourcefile~time_integrator.f90 sourcefile~vector_calculus.f90 vector_calculus.f90 sourcefile~solver.f90->sourcefile~vector_calculus.f90 sourcefile~spectral_processing.f90->sourcefile~common.f90~2 sourcefile~spectral_processing.f90~2->sourcefile~common.f90~2 sourcefile~tdsops.f90->sourcefile~common.f90~2 sourcefile~tdsops.f90->sourcefile~tdsops.f90~2 sourcefile~tdsops.f90~2->sourcefile~common.f90~2 sourcefile~tgv.f90->sourcefile~base_case.f90 sourcefile~tgv.f90->sourcefile~common.f90~2 sourcefile~tgv.f90->sourcefile~mesh.f90 sourcefile~tgv.f90->sourcefile~allocator.f90~2 sourcefile~tgv.f90->sourcefile~backend.f90 sourcefile~tgv.f90->sourcefile~field.f90 sourcefile~tgv.f90->sourcefile~solver.f90 sourcefile~thomas.f90->sourcefile~common.f90~2 sourcefile~thomas.f90~2->sourcefile~common.f90~2 sourcefile~time_integrator.f90->sourcefile~common.f90~2 sourcefile~time_integrator.f90->sourcefile~allocator.f90~2 sourcefile~time_integrator.f90->sourcefile~backend.f90 sourcefile~time_integrator.f90->sourcefile~field.f90 sourcefile~vector_calculus.f90->sourcefile~common.f90~2 sourcefile~vector_calculus.f90->sourcefile~allocator.f90~2 sourcefile~vector_calculus.f90->sourcefile~backend.f90 sourcefile~vector_calculus.f90->sourcefile~field.f90 sourcefile~vector_calculus.f90->sourcefile~tdsops.f90~2 sourcefile~checkpoint_state.f90->sourcefile~io_session.f90 sourcefile~decomp_dummy.f90->sourcefile~mesh_content.f90

Source Code

module m_mpi
!! Single point of contact between x3d2 and MPI.
!!
!! When the build enables MPI (-DMPI, set by the WITH_MPI option, on by
!! default) this module is a thin re-export of the `mpi` module, so `use m_mpi`
!! is exactly `use mpi`.
!!
!! When MPI is disabled the module supplies serial stand-ins for the MPI
!! entities x3d2 uses. A build without MPI is a single rank, so every
!! collective reduces to the identity, ranks are 0 and communicator sizes are
!! 1. Call sites therefore stay free of preprocessor branches: they call
!! MPI_Allreduce, MPI_Comm_rank and friends unconditionally and get the right
!! serial answer. Point-to-point communication is the exception: it is only
!! reachable on more than one rank, so those stubs stop the run instead.
!!
!! Add a stub here rather than an `#ifdef MPI` at a call site when new MPI
!! calls appear. The only guards left in the tree are around communication on
!! device buffers, which cannot be typed generically here.
#ifdef MPI
  use mpi

  implicit none
#else
  use iso_fortran_env, only: int64, real32, real64, stderr => error_unit

  implicit none

  private
  public :: MPI_COMM_WORLD, MPI_COMM_SELF, MPI_COMM_NULL, MPI_SUCCESS
  public :: MPI_SUM, MPI_MAX, MPI_MIN, MPI_LAND
  public :: MPI_INTEGER, MPI_LOGICAL, MPI_REAL, MPI_DOUBLE_PRECISION, &
            MPI_COMPLEX, MPI_DOUBLE_COMPLEX
  public :: MPI_STATUS_SIZE, MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE
  public :: mpi_in_place_t, MPI_IN_PLACE
  public :: MPI_Init, MPI_Finalize, MPI_Initialized, MPI_Abort
  public :: MPI_Comm_rank, MPI_Comm_size, MPI_Barrier, MPI_Wtime
  public :: MPI_Bcast, MPI_Allreduce, MPI_Reduce
  public :: MPI_Isend, MPI_Irecv, MPI_Waitall, MPI_Sendrecv

  !> Handles are opaque in MPI, so the values only have to be distinct.
  integer, parameter :: MPI_COMM_NULL = 0
  integer, parameter :: MPI_COMM_WORLD = 1
  integer, parameter :: MPI_COMM_SELF = 2

  integer, parameter :: MPI_SUCCESS = 0

  integer, parameter :: MPI_SUM = 1
  integer, parameter :: MPI_MAX = 2
  integer, parameter :: MPI_MIN = 3
  integer, parameter :: MPI_LAND = 4

  integer, parameter :: MPI_INTEGER = 1
  integer, parameter :: MPI_LOGICAL = 2
  integer, parameter :: MPI_REAL = 3
  integer, parameter :: MPI_DOUBLE_PRECISION = 4
  integer, parameter :: MPI_COMPLEX = 5
  integer, parameter :: MPI_DOUBLE_COMPLEX = 6

  integer, parameter :: MPI_STATUS_SIZE = 6
  integer, parameter :: MPI_STATUS_IGNORE(MPI_STATUS_SIZE) = 0
  integer, parameter :: MPI_STATUSES_IGNORE(MPI_STATUS_SIZE, 1) = 0

  !> MPI_IN_PLACE is a sentinel, not data. Giving it a type of its own is what
  !> lets the generic MPI_Allreduce below tell an in-place call (a no-op here)
  !> from one with separate send and receive buffers (a copy here).
  type :: mpi_in_place_t
    private
    integer :: sentinel = 0
  end type mpi_in_place_t

  type(mpi_in_place_t), parameter :: MPI_IN_PLACE = mpi_in_place_t(0)

  interface MPI_Allreduce
    module procedure allreduce_in_place
    module procedure allreduce_r32
    module procedure allreduce_r64
    module procedure allreduce_r64_1d
  end interface MPI_Allreduce

  interface MPI_Reduce
    module procedure reduce_r32
    module procedure reduce_r64
  end interface MPI_Reduce

contains

  subroutine MPI_Init(ierror)
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
  end subroutine MPI_Init

  subroutine MPI_Finalize(ierror)
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
  end subroutine MPI_Finalize

  subroutine MPI_Initialized(flag, ierror)
    !! Reported as initialised whether or not MPI_Init has been called. There
    !! is no MPI environment to bring up here, so callers asking whether it is
    !! safe to proceed always have their answer, and a library handed a
    !! communicator never has to wait for one.
    logical, intent(out) :: flag
    integer, intent(out) :: ierror

    flag = .true.
    ierror = MPI_SUCCESS
  end subroutine MPI_Initialized

  subroutine MPI_Abort(comm, errorcode, ierror)
    integer, intent(in) :: comm, errorcode
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
    write (stderr, '(a,i0)') 'MPI_Abort with error code ', errorcode
    flush (stderr)
    error stop 'aborted'
  end subroutine MPI_Abort

  subroutine MPI_Comm_rank(comm, rank, ierror)
    integer, intent(in) :: comm
    integer, intent(out) :: rank, ierror

    rank = 0
    ierror = MPI_SUCCESS
  end subroutine MPI_Comm_rank

  subroutine MPI_Comm_size(comm, size, ierror)
    integer, intent(in) :: comm
    integer, intent(out) :: size, ierror

    size = 1
    ierror = MPI_SUCCESS
  end subroutine MPI_Comm_size

  subroutine MPI_Barrier(comm, ierror)
    integer, intent(in) :: comm
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
  end subroutine MPI_Barrier

  function MPI_Wtime() result(t)
    !! Elapsed wall-clock seconds, from an arbitrary origin as MPI defines it.
    real(real64) :: t

    integer(int64) :: ticks, ticks_per_second

    call system_clock(ticks, ticks_per_second)
    t = real(ticks, real64)/real(ticks_per_second, real64)
  end function MPI_Wtime

  subroutine MPI_Bcast(buffer, count, datatype, root, comm, ierror)
    !! The only rank is the root, so its buffer is already the broadcast value.
    type(*), dimension(..), intent(inout) :: buffer
    integer, intent(in) :: count, datatype, root, comm
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
  end subroutine MPI_Bcast

  subroutine allreduce_in_place(sendbuf, recvbuf, count, datatype, op, comm, &
                                ierror)
    !! Reducing one rank's contribution in place leaves the buffer as it is,
    !! whatever its type, shape or the operation asked for.
    type(mpi_in_place_t), intent(in) :: sendbuf
    type(*), dimension(..), intent(inout) :: recvbuf
    integer, intent(in) :: count, datatype, op, comm
    integer, intent(out) :: ierror

    ierror = MPI_SUCCESS
  end subroutine allreduce_in_place

  subroutine allreduce_r32(sendbuf, recvbuf, count, datatype, op, comm, ierror)
    real(real32), intent(in) :: sendbuf
    real(real32), intent(out) :: recvbuf
    integer, intent(in) :: count, datatype, op, comm
    integer, intent(out) :: ierror

    recvbuf = sendbuf
    ierror = MPI_SUCCESS
  end subroutine allreduce_r32

  subroutine allreduce_r64(sendbuf, recvbuf, count, datatype, op, comm, ierror)
    real(real64), intent(in) :: sendbuf
    real(real64), intent(out) :: recvbuf
    integer, intent(in) :: count, datatype, op, comm
    integer, intent(out) :: ierror

    recvbuf = sendbuf
    ierror = MPI_SUCCESS
  end subroutine allreduce_r64

  subroutine allreduce_r64_1d(sendbuf, recvbuf, count, datatype, op, comm, &
                              ierror)
    real(real64), intent(in) :: sendbuf(:)
    real(real64), intent(out) :: recvbuf(:)
    integer, intent(in) :: count, datatype, op, comm
    integer, intent(out) :: ierror

    recvbuf(1:count) = sendbuf(1:count)
    ierror = MPI_SUCCESS
  end subroutine allreduce_r64_1d

  subroutine reduce_r32(sendbuf, recvbuf, count, datatype, op, root, comm, &
                        ierror)
    real(real32), intent(in) :: sendbuf
    real(real32), intent(out) :: recvbuf
    integer, intent(in) :: count, datatype, op, root, comm
    integer, intent(out) :: ierror

    recvbuf = sendbuf
    ierror = MPI_SUCCESS
  end subroutine reduce_r32

  subroutine reduce_r64(sendbuf, recvbuf, count, datatype, op, root, comm, &
                        ierror)
    real(real64), intent(in) :: sendbuf
    real(real64), intent(out) :: recvbuf
    integer, intent(in) :: count, datatype, op, root, comm
    integer, intent(out) :: ierror

    recvbuf = sendbuf
    ierror = MPI_SUCCESS
  end subroutine reduce_r64

  ! Point-to-point communication has no serial meaning: a single rank has no
  ! partner to exchange with. Call sites reach these only after branching on a
  ! rank count above one, so the stubs exist to satisfy the compiler and stop
  ! the run if that branching is ever wrong.
  subroutine MPI_Isend(buf, count, datatype, dest, tag, comm, request, ierror)
    type(*), dimension(..), intent(in) :: buf
    integer, intent(in) :: count, datatype, dest, tag, comm
    integer, intent(out) :: request, ierror

    error stop 'MPI_Isend called, but this build was configured without MPI'
  end subroutine MPI_Isend

  subroutine MPI_Irecv(buf, count, datatype, source, tag, comm, request, &
                       ierror)
    type(*), dimension(..), intent(inout) :: buf
    integer, intent(in) :: count, datatype, source, tag, comm
    integer, intent(out) :: request, ierror

    error stop 'MPI_Irecv called, but this build was configured without MPI'
  end subroutine MPI_Irecv

  subroutine MPI_Waitall(count, array_of_requests, array_of_statuses, ierror)
    integer, intent(in) :: count
    integer, intent(inout) :: array_of_requests(*)
    integer, intent(in) :: array_of_statuses(*)
    integer, intent(out) :: ierror

    error stop 'MPI_Waitall called, but this build was configured without MPI'
  end subroutine MPI_Waitall

  subroutine MPI_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag, &
                          recvbuf, recvcount, recvtype, source, recvtag, &
                          comm, status, ierror)
    !! Reachable only where a call site has already branched on a rank count
    !! above one, as the exchanges in the CUDA Poisson solver do. It exists so
    !! that callers can name it in a `use m_mpi, only:` list that has to
    !! compile in both builds.
    type(*), dimension(..), intent(in) :: sendbuf
    type(*), dimension(..), intent(inout) :: recvbuf
    integer, intent(in) :: sendcount, sendtype, dest, sendtag
    integer, intent(in) :: recvcount, recvtype, source, recvtag, comm
    integer, intent(in) :: status(*)
    integer, intent(out) :: ierror

    error stop 'MPI_Sendrecv called, but this build was configured without MPI'
  end subroutine MPI_Sendrecv
#endif
end module m_mpi