Octopus
ring_pattern.F90
Go to the documentation of this file.
1!! Copyright (C) 2023 N. Tancogne-Dejean
2!!
3!! This Source Code Form is subject to the terms of the Mozilla Public
4!! License, v. 2.0. If a copy of the MPL was not distributed with this
5!! file, You can obtain one at https://mozilla.org/MPL/2.0/.
6!!
7
8#include "global.h"
9
13!
15 use comm_oct_m
16 use debug_oct_m
17 use global_oct_m
19 use mpi_oct_m
21
22 implicit none
23
24 private
25
26 public :: &
28
30 private
31
32 type(mpi_grp_t) :: mpi_grp
33 integer :: nsteps
34 ! Each step might imply more than one communication step (e.g. multiple batches per rank).
35 logical :: double_sided_comms
36
37 contains
38 procedure :: start => ring_pattern_start
39 procedure :: get_nsteps => ring_pattern_get_nsteps
40 procedure :: get_rank_from => ring_pattern_get_rank_from
41 procedure :: get_rank_to => ring_pattern_get_rank_to
42 end type ring_pattern_t
43
44contains
45
52 subroutine ring_pattern_start(this, mpi_grp, double_sided_comms)
53 class(ring_pattern_t), intent(inout) :: this
54 type(mpi_grp_t), intent(in) :: mpi_grp
55 logical, intent(in) :: double_sided_comms
56
57 push_sub(ring_pattern_start)
58
59 this%double_sided_comms = double_sided_comms
60 this%mpi_grp = mpi_grp
61
62 if (double_sided_comms) then
63 this%nsteps = int((mpi_grp%size+2)/2)-1
64 else
65 this%nsteps = mpi_grp%size-1
66 end if
67
68 if (debug%info) then
69 write(message(1), '(a,i4,a)') "Debug: The ring pattern will perform ", this%nsteps, " steps."
70 call messages_info(1)
71 end if
72
73 pop_sub(ring_pattern_start)
74 end subroutine ring_pattern_start
75
77 integer pure function ring_pattern_get_nsteps(this)
78 class(ring_pattern_t), intent(in) :: this
79
80 ring_pattern_get_nsteps = this%nsteps
81 end function ring_pattern_get_nsteps
82
102 integer pure function ring_pattern_get_rank_to(this, istep) result(rank_to)
103 class(ring_pattern_t), intent(in) :: this
104 integer, intent(in) :: istep
105
106 logical :: last_step, even_number_tasks, rank_to_first_half
108 rank_to = mod(this%mpi_grp%rank + istep, this%mpi_grp%size)
109
110 if (this%double_sided_comms) then
111 last_step = istep == this%nsteps
112 even_number_tasks = mod(this%mpi_grp%size, 2) == 0
113 rank_to_first_half = rank_to < this%mpi_grp%size/2
114
115 if (last_step .and. even_number_tasks .and. rank_to_first_half) then
116 rank_to = -1
117 end if
118 end if
119 end function ring_pattern_get_rank_to
120
122 integer pure function ring_pattern_get_rank_from(this, istep) result(rank_fr)
123 class(ring_pattern_t), intent(in) :: this
124 integer, intent(in) :: istep
126 logical :: last_step, even_number_tasks, rank_first_half
127
128 rank_fr = this%mpi_grp%rank - istep
129 if (rank_fr < 0) rank_fr = this%mpi_grp%size + rank_fr
130 rank_fr = mod(rank_fr, this%mpi_grp%size)
132 if (this%double_sided_comms) then
133 last_step = istep == this%nsteps
134 even_number_tasks = mod(this%mpi_grp%size, 2) == 0
135 rank_first_half = this%mpi_grp%rank < this%mpi_grp%size/2
136 if (last_step .and. even_number_tasks .and. rank_first_half) then
137 rank_fr = -1
138 end if
139 end if
140 end function ring_pattern_get_rank_from
141
142end module ring_pattern_oct_m
143
144
145!! Local Variables:
146!! mode: f90
147!! coding: utf-8
148!! End:
type(debug_t), save, public debug
Definition: debug.F90:154
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
This module is an helper to perform ring-pattern communications among all states.
integer pure function ring_pattern_get_nsteps(this)
Returns the total number of steps in the ring.
subroutine ring_pattern_start(this, mpi_grp, double_sided_comms)
Starts the ring pattern scheme.
integer pure function ring_pattern_get_rank_from(this, istep)
Returns the rank from which we receive the information.
integer pure function ring_pattern_get_rank_to(this, istep)
Returns the rank where to send the information.