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 debug_oct_m
16 use global_oct_m
18 use mpi_oct_m
20
21 implicit none
22
23 private
24
25 public :: &
27
29 private
30
31 type(mpi_grp_t) :: mpi_grp
32 integer :: nsteps
33 ! !! Each step might imply more than one communication step (e.g. multiple batches per rank).
34 logical :: double_sided_comms
35
36 contains
37 procedure :: start => ring_pattern_start
38 procedure :: get_nsteps => ring_pattern_get_nsteps
39 procedure :: get_rank_from => ring_pattern_get_rank_from
40 procedure :: get_rank_to => ring_pattern_get_rank_to
41 end type ring_pattern_t
42
43contains
44
51 subroutine ring_pattern_start(this, mpi_grp, double_sided_comms)
52 class(ring_pattern_t), intent(inout) :: this
53 type(mpi_grp_t), intent(in) :: mpi_grp
54 logical, intent(in) :: double_sided_comms
55
56 push_sub(ring_pattern_start)
57
58 this%double_sided_comms = double_sided_comms
59 this%mpi_grp = mpi_grp
60
61 if (this%mpi_grp%size <= 0) then
62 this%nsteps = 0
63 pop_sub(ring_pattern_start)
64 return
65 end if
66
67 if (double_sided_comms) then
68 this%nsteps = int((mpi_grp%size+2)/2)-1
69 else
70 this%nsteps = mpi_grp%size-1
71 end if
72
73 if (this%nsteps > 0) then
74 write(message(1), '(a,i0,a)') "Debug: The ring pattern will perform ", this%nsteps, " steps."
75 call messages_info(1, debug_only=.true.)
76 end if
77
78 pop_sub(ring_pattern_start)
79 end subroutine ring_pattern_start
80
82 integer pure function ring_pattern_get_nsteps(this)
83 class(ring_pattern_t), intent(in) :: this
84
85 ring_pattern_get_nsteps = this%nsteps
86 end function ring_pattern_get_nsteps
87
107 integer pure function ring_pattern_get_rank_to(this, istep) result(rank_to)
108 class(ring_pattern_t), intent(in) :: this
109 integer, intent(in) :: istep
110
111 logical :: last_step, even_number_tasks, rank_to_first_half
112
113 rank_to = mod(this%mpi_grp%rank + istep, this%mpi_grp%size)
114
115 if (this%double_sided_comms) then
116 last_step = istep == this%nsteps
117 even_number_tasks = mod(this%mpi_grp%size, 2) == 0
118 rank_to_first_half = rank_to < this%mpi_grp%size/2
119
120 if (last_step .and. even_number_tasks .and. rank_to_first_half) then
121 rank_to = -1
122 end if
123 end if
124 end function ring_pattern_get_rank_to
125
127 integer pure function ring_pattern_get_rank_from(this, istep) result(rank_fr)
128 class(ring_pattern_t), intent(in) :: this
129 integer, intent(in) :: istep
130
131 logical :: last_step, even_number_tasks, rank_first_half
133 rank_fr = modulo(this%mpi_grp%rank - istep, this%mpi_grp%size)
135 if (this%double_sided_comms) then
136 last_step = istep == this%nsteps
137 even_number_tasks = mod(this%mpi_grp%size, 2) == 0
138 rank_first_half = this%mpi_grp%rank < this%mpi_grp%size/2
139 if (last_step .and. even_number_tasks .and. rank_first_half) then
140 rank_fr = -1
141 end if
142 end if
143 end function ring_pattern_get_rank_from
144
145end module ring_pattern_oct_m
147
148!! Local Variables:
149!! mode: f90
150!! coding: utf-8
151!! End:
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
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.
int true(void)