comm_handler_m.f90 Source File


Contents

Source Code


Source Code

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