!> @file parallel_reductions.F90 !> @brief Thin wrappers around MPI_Allreduce for the three reduction kinds !! the 1D Euler solver needs: scalar real max, scalar real sum, and !! scalar logical OR. !! !! Every call goes through MPI_Allreduce so call sites remain correct at any !! rank count. At `-np 1` the operations are identities; bit-identity with !! the pre-MPI serial code is preserved by construction. !! !! We deliberately use separate send/recv buffers rather than =MPI_IN_PLACE=: !! MS-MPI's legacy =mpi= module mishandles =MPI_IN_PLACE= at =-np 1=, returning !! garbage instead of the input value. Two-buffer Allreduce is the textbook !! form and works on every MPI implementation we care about. !! !! See `mpi_runtime.F90` for the rationale behind the `mpi_f08` / legacy !! `mpi` cpp split. module parallel_reductions use precision, only: wp #ifdef CFD_SOLVER_LEGACY_MPI use mpi, only: MPI_Allreduce, MPI_DOUBLE_PRECISION, MPI_LOGICAL, & MPI_MAX, MPI_SUM, MPI_LOR #else use mpi_f08, only: MPI_Allreduce, MPI_DOUBLE_PRECISION, MPI_LOGICAL, & MPI_MAX, MPI_SUM, MPI_LOR #endif use mpi_runtime, only: mpi_world, parallel_fatal implicit none private public :: par_max_real public :: par_sum_real public :: par_lor contains !> Return the maximum of a scalar real(wp) across all ranks. function par_max_real(local) result(global) real(wp), intent(in) :: local real(wp) :: global integer :: ierr call MPI_Allreduce(local, global, 1, MPI_DOUBLE_PRECISION, & MPI_MAX, mpi_world(), ierr) if (ierr /= 0) call parallel_fatal('par_max_real: MPI_Allreduce failed') end function par_max_real !> Return the sum of a scalar real(wp) across all ranks. function par_sum_real(local) result(global) real(wp), intent(in) :: local real(wp) :: global integer :: ierr call MPI_Allreduce(local, global, 1, MPI_DOUBLE_PRECISION, & MPI_SUM, mpi_world(), ierr) if (ierr /= 0) call parallel_fatal('par_sum_real: MPI_Allreduce failed') end function par_sum_real !> Return the logical OR of a scalar logical across all ranks. function par_lor(local) result(global) logical, intent(in) :: local logical :: global integer :: ierr call MPI_Allreduce(local, global, 1, MPI_LOGICAL, & MPI_LOR, mpi_world(), ierr) if (ierr /= 0) call parallel_fatal('par_lor: MPI_Allreduce failed') end function par_lor end module parallel_reductions