module comm_handler_m !! Handles MPI topology and communicators use MPI implicit none integer, private, parameter :: ndims = 2 !! Number of MPI parallelized dimensions (planes and species) integer, private, parameter :: dimcnt_planes = 1 !! Location of planes dimension integer, private, parameter :: dimcnt_species = 2 !! Location of species dimension type, public :: comm_handler_t !! MPI topology and communicators integer, private :: comm_cart !! MPI communicator for complete topology integer, private :: ncart !! Number of total MPI processes of topology integer, private :: rank !! Number of the rank the code is running on integer, private :: comm_planes !! MPI communicator over planes integer, private :: nplanes !! Number of planes integer, private :: plane !! Number of the plane code is running on integer, private :: comm_species !! MPI communicator over species integer, private :: nspecies !! Number of species integer, private :: species !! Number of the species code is running on contains procedure, public :: init procedure, public :: get_comm_cart procedure, public :: get_ncart procedure, public :: get_rank procedure, public :: get_comm_planes procedure, public :: get_nplanes procedure, public :: get_plane procedure, public :: get_comm_species procedure, public :: get_nspecies procedure, public :: get_species procedure, public :: say_hello final :: destructor end type contains subroutine init(self, comm_old, nplanes, nspecies) !! Initialises MPI topology and communicators class(comm_handler_t), intent(inout) :: self !! Instance of type integer, intent(in) :: comm_old !! Communicator topology is created on integer, intent(in) :: nplanes !! Number of poloidal planes integer, intent(in) :: nspecies !! Number of species integer :: ierr integer, dimension(ndims) :: dims logical, dimension(ndims) :: periods, activated_dims logical :: reorder dims(dimcnt_planes) = nplanes dims(dimcnt_species) = nspecies periods(dimcnt_planes) = .true. periods(dimcnt_species) = .false. reorder = .false. ! Create cartesian communicators call MPI_cart_create(comm_old, ndims, dims, periods, reorder, self%comm_cart, ierr) if (ierr /= 0) then write(*,*)'error(comm_handler%init), MPI_CART_CREATE', ierr error stop endif call MPI_comm_size(self%comm_cart, self%ncart, ierr) call MPI_comm_rank(self%comm_cart, self%rank, ierr) ! Create planes communicator activated_dims = .false. activated_dims(dimcnt_planes) = .true. call MPI_cart_sub(self%comm_cart, activated_dims, self%comm_planes, ierr) if (ierr /= 0) then write(*,*)'error(comm_handler%init), MPI_cart_sub planes', ierr error stop endif call MPI_comm_size(self%comm_planes, self%nplanes, ierr) call MPI_comm_rank(self%comm_planes, self%plane, ierr) ! Create species communicator activated_dims = .false. activated_dims(dimcnt_species) = .true. call MPI_cart_sub(self%comm_cart, activated_dims, self%comm_species, ierr) if (ierr /= 0) then write(*,*)'error(comm_handler%init), MPI_cart_sub species', ierr error stop endif call MPI_comm_size(self%comm_species, self%nspecies, ierr) call MPI_comm_rank(self%comm_species, self%species, ierr) end subroutine integer pure function get_comm_cart(self) class(comm_handler_t), intent(in) :: self get_comm_cart = self%comm_cart end function integer pure function get_ncart(self) class(comm_handler_t), intent(in) :: self get_ncart = self%ncart end function integer pure function get_rank(self) class(comm_handler_t), intent(in) :: self get_rank = self%rank end function integer pure function get_comm_planes(self) class(comm_handler_t), intent(in) :: self get_comm_planes = self%comm_planes end function integer pure function get_nplanes(self) class(comm_handler_t), intent(in) :: self get_nplanes = self%nplanes end function integer pure function get_plane(self) class(comm_handler_t), intent(in) :: self get_plane = self%plane end function integer pure function get_comm_species(self) class(comm_handler_t), intent(in) :: self get_comm_species = self%comm_species end function integer pure function get_nspecies(self) class(comm_handler_t), intent(in) :: self get_nspecies = self%nspecies end function integer pure function get_species(self) class(comm_handler_t), intent(in) :: self get_species = self%species end function subroutine say_hello(self) class(comm_handler_t), intent(in) :: self write(*,101)self%get_rank(),self%get_ncart(),self%get_plane(),self%get_nplanes(), & self%get_species(),self%get_nspecies() 101 FORMAT('Rank = ',I5,' of ',I5,5X,'; Plane = ',I5,' of ',I5,5X,'; Species = ',I5,' of ',I5) end subroutine subroutine destructor(self) type(comm_handler_t), intent(inout) :: self integer :: ierr call MPI_comm_free(self%comm_cart, ierr) call MPI_comm_free(self%comm_planes, ierr) call MPI_comm_free(self%comm_species, ierr) end subroutine end module