Octopus
states_elec_parallel.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
21
27 use batch_oct_m
28 use debug_oct_m
29 use global_oct_m
30 use mesh_oct_m
32 use mpi_oct_m
37 use types_oct_m
39
40 implicit none
41
42 private
43
44 public :: &
52
56 end interface states_elec_parallel_gather
57
58
59contains
61 !
62 subroutine states_elec_parallel_blacs_blocksize(st, namespace, mesh, blocksize, total_np)
63 type(states_elec_t), intent(in) :: st
64 type(namespace_t), intent(in) :: namespace
65 type(mesh_t), intent(in) :: mesh
66 integer, intent(out) :: blocksize(2)
67 integer, intent(out) :: total_np
68
70
71#ifdef HAVE_SCALAPACK
72 ! We need to select the block size of the decomposition. This is
73 ! tricky, since not all processors have the same number of
74 ! points.
75 !
76 ! What we do for now is to use the maximum of the number of
77 ! points and we set to zero the remaining points.
78
79 if (.not. st%scalapack_compatible) then
80 message(1) = "Attempt to use ScaLAPACK when processes have not been distributed in compatible layout."
81 message(2) = "You need to set ScaLAPACKCompatible = yes in the input file and re-run."
82 call messages_fatal(2, only_root_writes = .true., namespace=namespace)
83 end if
84
85 if (mesh%parallel_in_domains) then
86 blocksize(1) = maxval(mesh%pv%np_local_vec) + (st%d%dim - 1) * &
87 maxval(mesh%pv%np_local_vec + mesh%pv%np_bndry + mesh%pv%np_ghost)
88 else
89 blocksize(1) = mesh%np + (st%d%dim - 1)*mesh%np_part
90 end if
91
92 if (st%parallel_in_states) then
93 blocksize(2) = maxval(st%dist%num)
94 else
95 blocksize(2) = st%nst
96 end if
97
98 total_np = blocksize(1)*st%dom_st_proc_grid%nprow
99
100
101 assert(st%d%dim*mesh%np_part >= blocksize(1))
102#else
103 blocksize(1) = 0
104 blocksize(2) = 0
105 total_np = 0
106#endif
107
110
111 ! ------------------------------------------------------------
119 !
121 type(states_elec_t), intent(inout) :: this
122
123 integer :: ib, iqn
124
126
127 assert(allocated(this%group%psib))
128
129 if (this%st_kpt_mpi_grp%size == 1) then
131 return
132 end if
133
134 assert(.not. allocated(this%group%rma_win))
135
136 safe_allocate(this%group%rma_win(1:this%group%nblocks, 1:this%nik))
137
138 do iqn = 1, this%nik
139 do ib = 1, this%group%nblocks
140 if (this%group%block_is_local(ib, iqn)) then
141 call this%group%psib(ib, iqn)%remote_access_start(this%st_kpt_mpi_grp, this%group%rma_win(ib, iqn))
142 else
143#ifdef HAVE_MPI
144 ! create an empty window
145 call mpi_win_create(0, int(0, mpi_address_kind), 1, &
146 mpi_info_null, this%st_kpt_mpi_grp%comm, this%group%rma_win(ib, iqn))
147#endif
148 end if
149 end do
150 end do
151
154
155 ! ---------------------------------------------------------
160 !
162 type(states_elec_t), intent(inout) :: this
163
164 integer :: ib, iqn
165
166 if (.not. allocated(this%group%rma_win)) return
167
169
170 assert(allocated(this%group%psib))
171
172 do iqn = 1, this%nik
173 do ib = 1, this%group%nblocks
174 if (this%group%block_is_local(ib, iqn)) then
175 call this%group%psib(ib, iqn)%remote_access_stop(this%group%rma_win(ib, iqn))
176 else
177#ifdef HAVE_MPI
178 call mpi_win_free(this%group%rma_win(ib, iqn))
179#endif
180 end if
181 end do
182 end do
184 safe_deallocate_a(this%group%rma_win)
185
188
190 subroutine states_elec_parallel_allocate_batch(st, psib, np, ib, ik, packed)
191 type(states_elec_t), intent(in) :: st
192 type(wfs_elec_t), intent(inout) :: psib
193 integer, intent(in) :: np
194 integer, intent(in) :: ib
195 integer, intent(in) :: ik
196 logical, optional, intent(in) :: packed
197
199
200 ! Pick the batch precision from st%wfs_type: a single-precision shadow
201 ! (TYPE_FLOAT_SINGLE / TYPE_CMPLX_SINGLE) allocates single-precision (s/c)
202 ! batches; otherwise double precision (d/z).
203 if (states_are_real(st)) then
204 if (type_is_single(st%wfs_type)) then
205 call swfs_elec_init(psib, st%d%dim, st%group%block_range(ib, 1), st%group%block_range(ib, 2), &
206 np, ik, packed=packed)
207 else
208 call dwfs_elec_init(psib, st%d%dim, st%group%block_range(ib, 1), st%group%block_range(ib, 2), &
209 np, ik, packed=packed)
210 end if
211 else
212 if (type_is_single(st%wfs_type)) then
213 call cwfs_elec_init(psib, st%d%dim, st%group%block_range(ib, 1), st%group%block_range(ib, 2), &
214 np, ik, packed=packed)
215 else
216 call zwfs_elec_init(psib, st%d%dim, st%group%block_range(ib, 1), st%group%block_range(ib, 2), &
217 np, ik, packed=packed)
218 end if
219 end if
220
223
224 ! --------------------------------------
231 subroutine states_elec_parallel_get_block(this, mesh, ib, iqn, psib)
232 type(states_elec_t), target, intent(in) :: this
233 class(mesh_t), intent(in) :: mesh
234 integer, intent(in) :: ib
235 integer, intent(in) :: iqn
236 class(wfs_elec_t), pointer, intent(out) :: psib
237
238 integer :: total_size
239
241
242 call profiling_in("STATES_GET_BLOCK")
243
244 if (this%group%block_is_local(ib, iqn)) then
245 psib => this%group%psib(ib, iqn)
246 call profiling_out("STATES_GET_BLOCK")
248 return
249 else
250 safe_allocate_type(wfs_elec_t, psib)
251 call states_elec_parallel_allocate_batch(this, psib, mesh%np_part, ib, iqn)
252
253 assert(allocated(this%group%rma_win))
254
255 call psib%do_pack(copy = .false.)
256 assert(product(psib%pack_size) < huge(0_int32))
257 total_size = product(int(psib%pack_size, int32))
258
259#ifdef HAVE_MPI
260
261 call profiling_in("STATES_GET_BLOCK_MPI")
262 call mpi_win_lock(mpi_lock_shared, this%group%block_node(ib, iqn), 0, this%group%rma_win(ib, iqn))
263
264 if (states_are_real(this)) then
265 call mpi_get(psib%dff_pack(1, 1), total_size, mpi_double_precision, &
266 this%group%block_node(ib, iqn), int(0, mpi_address_kind), total_size, mpi_double_precision, &
267 this%group%rma_win(ib, iqn))
268 else
269 call mpi_get(psib%zff_pack(1, 1), total_size, mpi_double_complex, &
270 this%group%block_node(ib, iqn), int(0, mpi_address_kind), total_size, mpi_double_complex, &
271 this%group%rma_win(ib, iqn))
272 end if
273
274 call mpi_win_unlock(this%group%block_node(ib, iqn), this%group%rma_win(ib, iqn))
275
276 call profiling_out("STATES_GET_BLOCK_MPI")
277#endif
278 end if
279
280 call profiling_out("STATES_GET_BLOCK")
281
283 end subroutine states_elec_parallel_get_block
284
285 ! --------------------------------------
286 !
287 subroutine states_elec_parallel_release_block(this, ib, psib)
288 type(states_elec_t), target, intent(in) :: this
289 integer, intent(in) :: ib
290 class(wfs_elec_t), pointer :: psib
291
293
294 if (this%group%block_is_local(ib, psib%ik)) then
295 nullify(psib)
296 else
297 call psib%end()
298 safe_deallocate_p(psib)
299 end if
300
303
304 ! --------------------------------------
305
306#include "undef.F90"
307#include "real.F90"
308#include "states_elec_parallel_inc.F90"
309
310#include "undef.F90"
311#include "complex.F90"
312#include "states_elec_parallel_inc.F90"
313#include "undef.F90"
314
315
317
318!! Local Variables:
319!! mode: f90
320!! coding: utf-8
321!! End:
This module implements batches of mesh functions.
Definition: batch.F90:135
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
pure logical function, public states_are_real(st)
This module provides routines for communicating states when using states parallelization.
subroutine, public states_elec_parallel_remote_access_stop(this)
stop remote memory access for states on other processors
subroutine dstates_elec_parallel_gather_3(st, dims, psi)
gather distributed states into a local array
subroutine dstates_elec_parallel_gather_1(st, aa)
gather a one-dimensional array, distributed over states
subroutine zstates_elec_parallel_gather_1(st, aa)
gather a one-dimensional array, distributed over states
subroutine, public states_elec_parallel_get_block(this, mesh, ib, iqn, psib)
retrieve wave functions from a different node
subroutine, public states_elec_parallel_allocate_batch(st, psib, np, ib, ik, packed)
Initializes a wfs_elec_t for np points, given block index ib, ad the k-point index ik.
subroutine, public states_elec_parallel_remote_access_start(this)
start remote memory access for states on other processors
subroutine zstates_elec_parallel_gather_3(st, dims, psi)
gather distributed states into a local array
subroutine, public states_elec_parallel_blacs_blocksize(st, namespace, mesh, blocksize, total_np)
determine the block size for a BLACS distribution
subroutine, public states_elec_parallel_release_block(this, ib, psib)
logical pure function, public type_is_single(this)
Definition: types.F90:194
subroutine, public zwfs_elec_init(this, dim, st_start, st_end, np, ik, special, packed)
initialize an empty wfs_elec_t object
Definition: wfs_elec.F90:568
subroutine, public cwfs_elec_init(this, dim, st_start, st_end, np, ik, special, packed)
initialize an empty wfs_elec_t object
Definition: wfs_elec.F90:864
subroutine, public dwfs_elec_init(this, dim, st_start, st_end, np, ik, special, packed)
initialize an empty wfs_elec_t object
Definition: wfs_elec.F90:424
subroutine, public swfs_elec_init(this, dim, st_start, st_end, np, ik, special, packed)
initialize an empty wfs_elec_t object
Definition: wfs_elec.F90:716
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
batches of electronic states
Definition: wfs_elec.F90:143
int true(void)