Octopus
distributed.F90
Go to the documentation of this file.
1!! Copyright (C) 2008-2016 X. Andrade
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use debug_oct_m
23 use global_oct_m
25 use mpi_oct_m
28
29 implicit none
30
31 private
32
33 public :: &
39
42 type distributed_t
43 integer :: start = 1
44 integer :: end = 0
45 logical :: parallel = .false.
46 integer, allocatable :: process(:)
47 integer, allocatable :: range(:, :)
48 ! dim(2, 0:n_processes-1)
49 ! Defined the same for all processes of mpi_grp
50 integer, allocatable :: num(:)
51 ! dim(mpi_grp%size)
52 type(mpi_grp_t) :: mpi_grp
53 contains
54 procedure :: nlocal => distributed_nlocal
55 procedure :: nglobal => distributed_nglobal
56 procedure :: displs => distributed_displs
57 end type distributed_t
58
59contains
60
62 pure integer function distributed_nlocal(this)
63 class(distributed_t), intent(in) :: this
64
65 distributed_nlocal = this%num(this%mpi_grp%rank)
66
67 end function distributed_nlocal
68
69
71 pure integer function distributed_nglobal(this)
72 class(distributed_t), intent(in) :: this
73
74 distributed_nglobal = size(this%process)
75
76 end function distributed_nglobal
77
78
81 pure function distributed_displs(this) result(displs)
82 class(distributed_t), intent(in) :: this
83 integer, allocatable :: displs(:)
84
85 displs = this%range(1, :) - 1
86
87 end function distributed_displs
88
89
91 subroutine distributed_init(this, total, comm, tag, scalapack_compat)
92 type(distributed_t), intent(out) :: this
93 integer, intent(in) :: total
94 type(MPI_Comm), intent(in) :: comm
95 character(len=*), optional, intent(in) :: tag
96 logical, optional, intent(in) :: scalapack_compat
97
98 integer :: i
99
100 push_sub(distributed_init)
101
102 safe_allocate(this%process(1:total))
103
104 call mpi_grp_init(this%mpi_grp, comm)
105 safe_allocate(this%num(0:this%mpi_grp%size - 1))
106 safe_allocate(this%range(1:2, 0:this%mpi_grp%size - 1))
107
108 ! Defaults
109 if (this%mpi_grp%size == 1 .or. total == 1) then
110 this%process(1:total) = 0
111 this%start = 1
112 this%end = total
113 this%parallel = .false.
114 this%range(:, 0) = [1, total]
115 this%num(0) = total
117
118 else
119 this%parallel = .true.
120
121 call multicomm_divide_range(total, this%mpi_grp%size, this%range(1, :), this%range(2, :), &
122 lsize = this%num, scalapack_compat = scalapack_compat)
123
124 this%start = this%range(1, this%mpi_grp%rank)
125 this%end = this%range(2, this%mpi_grp%rank)
126
127 do i = 0, this%mpi_grp%size - 1
128 this%process(this%range(1, i):this%range(2, i)) = i
129 end do
130
131 if (present(tag)) then
132 message(1) = 'Info: Parallelization in ' // trim(tag)
133 call messages_info(1)
134 do i = 0, this%mpi_grp%size - 1
135 write(message(1),'(a,i4,a,i6,a)') 'Info: Process in group ', i, &
136 ' will manage ', this%num(i), ' '//trim(tag)
137 if (this%num(i) > 0) then
138 write(message(1),'(a,a,i6,a,i6)') trim(message(1)), ':', this%range(1, i), " - ", this%range(2, i)
139 end if
141 end do
142 end if
143
144 end if
146 pop_sub(distributed_init)
147 end subroutine distributed_init
148
153 subroutine distributed_init_serial(this, total)
154 type(distributed_t), intent(out) :: this
155 integer, intent(in) :: total
156
158
159 call distributed_init(this, total, mpi_comm_undefined)
160
162
163 end subroutine distributed_init_serial
164
165
167 subroutine distributed_copy(in, out)
168 type(distributed_t), intent(in) :: in
169 type(distributed_t), intent(inout) :: out
170
171 integer :: nprocs
172
173 push_sub(distributed_copy)
174
175 call distributed_end(out)
177 out%start = in%start
178 out%end = in%end
179 out%parallel = in%parallel
180
181 nprocs = in%mpi_grp%size
182
183 call mpi_grp_init(out%mpi_grp, in%mpi_grp%comm)
184
185 if (allocated(in%process)) then
186 safe_allocate(out%process(1:size(in%process)))
187 out%process(:) = in%process(:)
188 end if
189
190 if (allocated(in%range)) then
191 safe_allocate(out%range(1:2, 0:nprocs - 1))
192 out%range(1:2, 0:nprocs - 1) = in%range(1:2, 0:nprocs - 1)
193 end if
194
195 if (allocated(in%num)) then
196 safe_allocate(out%num(0:nprocs - 1))
197 out%num(0:nprocs - 1) = in%num(0:nprocs - 1)
198 end if
199
200 pop_sub(distributed_copy)
201 end subroutine distributed_copy
202
203
204 subroutine distributed_end(this)
205 type(distributed_t), intent(inout) :: this
206
207 push_sub(distributed_end)
208
209 safe_deallocate_a(this%process)
210 safe_deallocate_a(this%range)
211 safe_deallocate_a(this%num)
212
213 pop_sub(distributed_end)
214 end subroutine distributed_end
215
216end module distributed_oct_m
217
218
219!! Local Variables:
220!! mode: f90
221!! coding: utf-8
222!! End:
pure integer function, dimension(:), allocatable distributed_displs(this)
Displacement of each process''s local part, relative to the start of the distributed quantity,...
subroutine, public distributed_end(this)
subroutine, public distributed_init(this, total, comm, tag, scalapack_compat)
Distribute N instances across M processes of communicator comm
subroutine, public distributed_copy(in, out)
Create a copy of a distributed instance.
subroutine, public distributed_init_serial(this, total)
Serial initialization of a distributed instance. The calling process is assigned all total instances,...
pure integer function distributed_nglobal(this)
Total number of distributed instances.
pure integer function distributed_nlocal(this)
Number of instances of the distributed quantity on process mpi_grprank.
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
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:138
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
Definition: mpi.F90:345
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
subroutine, public multicomm_divide_range(nobjs, nprocs, istart, ifinal, lsize, scalapack_compat)
This routine uses the one-factorization (or near-one-factorization of a complete graph to construct a...
Definition: multicomm.F90:748
Distribution of N instances over mpi_grpsize processes, for the local rank mpi_grprank....
int true(void)