Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Interface to the message passing library MPI
10 : !> \par History
11 : !> JGH (02-Jan-2001): New error handling
12 : !> Performance tools
13 : !> JGH (14-Jan-2001): New routines mp_comm_compare, mp_cart_coords,
14 : !> mp_rank_compare, mp_alltoall
15 : !> JGH (06-Feb-2001): New routines mp_comm_free
16 : !> JGH (22-Mar-2001): New routines mp_comm_dup
17 : !> fawzi (04-NOV-2004): storable performance info (for f77 interface)
18 : !> Wrapper routine for mpi_gatherv added (22.12.2005,MK)
19 : !> JGH (13-Feb-2006): Flexible precision
20 : !> JGH (15-Feb-2006): single precision mp_alltoall
21 : !> \author JGH
22 : ! **************************************************************************************************
23 : MODULE message_passing
24 : USE ISO_C_BINDING, ONLY: C_F_POINTER, C_PTR
25 : USE kinds, ONLY: &
26 : dp, int_4, int_4_size, int_8, int_8_size, real_4, real_4_size, real_8, &
27 : real_8_size, default_string_length
28 : USE machine, ONLY: m_abort
29 : USE mp_perf_env, ONLY: add_perf, add_mp_perf_env, rm_mp_perf_env
30 : #if defined(__MIMIC)
31 : USE mcl, ONLY: mcl_initialize, mcl_is_initialized, mcl_abort
32 : #endif
33 :
34 : #include "../base/base_uses.f90"
35 :
36 : ! To simplify the transition between the old MPI module and the F08-style module,
37 : ! we introduce these constants to switch between the required handle types
38 : ! Unfortunately, Fortran does not offer something like typedef in C++
39 : #if defined(__parallel) && defined(__MPI_F08)
40 : #define MPI_DATA_TYPE TYPE(MPI_Datatype)
41 : #define MPI_COMM_TYPE TYPE(MPI_Comm)
42 : #define MPI_REQUEST_TYPE TYPE(MPI_Request)
43 : #define MPI_WIN_TYPE TYPE(MPI_Win)
44 : #define MPI_FILE_TYPE TYPE(MPI_File)
45 : #define MPI_INFO_TYPE TYPE(MPI_Info)
46 : #define MPI_STATUS_TYPE TYPE(MPI_Status)
47 : #define MPI_GROUP_TYPE TYPE(MPI_Group)
48 : #define MPI_STATUS_EXTRACT(X) %X
49 : #define MPI_GET_COMP %mpi_val
50 : #else
51 : #define MPI_DATA_TYPE INTEGER
52 : #define MPI_COMM_TYPE INTEGER
53 : #define MPI_REQUEST_TYPE INTEGER
54 : #define MPI_WIN_TYPE INTEGER
55 : #define MPI_FILE_TYPE INTEGER
56 : #define MPI_INFO_TYPE INTEGER
57 : #define MPI_STATUS_TYPE INTEGER, DIMENSION(MPI_STATUS_SIZE)
58 : #define MPI_GROUP_TYPE INTEGER
59 : #define MPI_STATUS_EXTRACT(X) (X)
60 : #define MPI_GET_COMP
61 : #endif
62 :
63 : #if defined(__parallel)
64 : ! subroutines: unfortunately, mpi implementations do not provide interfaces for all subroutines
65 : ! (problems with types and ranks explosion),
66 : ! we do not quite know what is in the module, so we can not include any....
67 : ! to nevertheless get checking for what is included, we use the mpi module
68 : ! without use clause, getting all there is
69 : #if defined(__MPI_F08)
70 : USE mpi_f08
71 : #else
72 : USE mpi
73 : #endif
74 : #endif
75 : IMPLICIT NONE
76 : PRIVATE
77 :
78 : ! parameters that might be needed
79 : #if defined(__parallel)
80 : LOGICAL, PARAMETER :: cp2k_is_parallel = .TRUE.
81 : INTEGER, PARAMETER, PUBLIC :: mp_any_tag = MPI_ANY_TAG
82 : INTEGER, PARAMETER, PUBLIC :: mp_any_source = MPI_ANY_SOURCE
83 : MPI_COMM_TYPE, PARAMETER :: mp_comm_null_handle = MPI_COMM_NULL
84 : MPI_COMM_TYPE, PARAMETER :: mp_comm_self_handle = MPI_COMM_SELF
85 : MPI_COMM_TYPE, PARAMETER :: mp_comm_world_handle = MPI_COMM_WORLD
86 : MPI_REQUEST_TYPE, PARAMETER :: mp_request_null_handle = MPI_REQUEST_NULL
87 : MPI_WIN_TYPE, PARAMETER :: mp_win_null_handle = MPI_WIN_NULL
88 : MPI_FILE_TYPE, PARAMETER :: mp_file_null_handle = MPI_FILE_NULL
89 : MPI_INFO_TYPE, PARAMETER :: mp_info_null_handle = MPI_INFO_NULL
90 : MPI_DATA_TYPE, PARAMETER :: mp_datatype_null_handle = MPI_DATATYPE_NULL
91 : INTEGER, PARAMETER, PRIVATE :: mp_comm_split_type_shared_id = MPI_COMM_TYPE_SHARED
92 : INTEGER, PARAMETER, PUBLIC :: mp_status_size = MPI_STATUS_SIZE
93 : INTEGER, PARAMETER, PUBLIC :: mp_proc_null = MPI_PROC_NULL
94 : ! Set max allocatable memory by MPI to 2 GiByte
95 : INTEGER(KIND=MPI_ADDRESS_KIND), PARAMETER, PRIVATE :: mp_max_memory_size = HUGE(INT(1, KIND=int_4))
96 :
97 : INTEGER, PARAMETER, PUBLIC :: mp_max_library_version_string = MPI_MAX_LIBRARY_VERSION_STRING
98 :
99 : INTEGER, PARAMETER, PUBLIC :: file_offset = MPI_OFFSET_KIND
100 : INTEGER, PARAMETER, PUBLIC :: address_kind = MPI_ADDRESS_KIND
101 : INTEGER, PARAMETER, PUBLIC :: file_amode_create = MPI_MODE_CREATE
102 : INTEGER, PARAMETER, PUBLIC :: file_amode_rdonly = MPI_MODE_RDONLY
103 : INTEGER, PARAMETER, PUBLIC :: file_amode_wronly = MPI_MODE_WRONLY
104 : INTEGER, PARAMETER, PUBLIC :: file_amode_rdwr = MPI_MODE_RDWR
105 : INTEGER, PARAMETER, PUBLIC :: file_amode_excl = MPI_MODE_EXCL
106 : INTEGER, PARAMETER, PUBLIC :: file_amode_append = MPI_MODE_APPEND
107 : #else
108 : LOGICAL, PARAMETER :: cp2k_is_parallel = .FALSE.
109 : INTEGER, PARAMETER, PUBLIC :: mp_any_tag = -1
110 : INTEGER, PARAMETER, PUBLIC :: mp_any_source = -2
111 : MPI_COMM_TYPE, PARAMETER :: mp_comm_null_handle = -3
112 : MPI_COMM_TYPE, PARAMETER :: mp_comm_self_handle = -11
113 : MPI_COMM_TYPE, PARAMETER :: mp_comm_world_handle = -12
114 : MPI_REQUEST_TYPE, PARAMETER :: mp_request_null_handle = -4
115 : MPI_WIN_TYPE, PARAMETER :: mp_win_null_handle = -5
116 : MPI_FILE_TYPE, PARAMETER :: mp_file_null_handle = -6
117 : MPI_INFO_TYPE, PARAMETER :: mp_info_null_handle = -7
118 : MPI_DATA_TYPE, PARAMETER :: mp_datatype_null_handle = -8
119 : INTEGER, PARAMETER, PRIVATE :: mp_comm_split_type_shared_id = -13
120 : INTEGER, PARAMETER, PUBLIC :: mp_status_size = -9
121 : INTEGER, PARAMETER, PUBLIC :: mp_proc_null = -10
122 : INTEGER, PARAMETER, PUBLIC :: mp_max_library_version_string = 1
123 :
124 : INTEGER, PARAMETER, PUBLIC :: file_offset = int_8
125 : INTEGER, PARAMETER, PUBLIC :: address_kind = int_8
126 : INTEGER, PARAMETER, PUBLIC :: file_amode_create = 1
127 : INTEGER, PARAMETER, PUBLIC :: file_amode_rdonly = 2
128 : INTEGER, PARAMETER, PUBLIC :: file_amode_wronly = 4
129 : INTEGER, PARAMETER, PUBLIC :: file_amode_rdwr = 8
130 : INTEGER, PARAMETER, PUBLIC :: file_amode_excl = 64
131 : INTEGER, PARAMETER, PUBLIC :: file_amode_append = 128
132 : #endif
133 :
134 : ! we need to fix this to a given number (crossing fingers)
135 : ! so that the serial code using Fortran stream IO and the MPI have the same sizes.
136 : INTEGER, PARAMETER, PUBLIC :: mpi_character_size = 1
137 : INTEGER, PARAMETER, PUBLIC :: mpi_integer_size = 4
138 :
139 : CHARACTER(LEN=*), PARAMETER, PRIVATE :: moduleN = 'message_passing'
140 :
141 : ! internal reference counter used to debug communicator leaks
142 : INTEGER, PRIVATE, SAVE :: debug_comm_count
143 :
144 : PUBLIC :: mp_comm_type
145 : PUBLIC :: mp_request_type
146 : PUBLIC :: mp_win_type
147 : PUBLIC :: mp_file_type
148 : PUBLIC :: mp_info_type
149 : PUBLIC :: mp_split_type
150 : PUBLIC :: mp_cart_type
151 :
152 : PUBLIC :: mp_para_env_type, mp_para_env_p_type, mp_para_cart_type
153 : PUBLIC :: mp_para_env_create, mp_para_env_release, &
154 : mp_para_cart_create, mp_para_cart_release
155 :
156 : #if defined(__MIMIC)
157 : ! Stores the split world communicator to finalize a MiMiC run
158 : MPI_COMM_TYPE, PRIVATE, SAVE :: mimic_comm_world
159 : #endif
160 :
161 : TYPE mp_comm_type
162 : PRIVATE
163 : MPI_COMM_TYPE :: handle = mp_comm_null_handle
164 : ! Number of dimensions within a Cartesian topology (useful with mp_cart_type)
165 : INTEGER :: ndims = 1
166 : ! Meta data to the communicator
167 : INTEGER, PUBLIC :: mepos = -1, source = -1, num_pe = -1
168 : CONTAINS
169 : ! Setters/Getters
170 : PROCEDURE, PASS, NON_OVERRIDABLE :: set_handle => mp_comm_type_set_handle
171 : PROCEDURE, PASS, NON_OVERRIDABLE :: get_handle => mp_comm_type_get_handle
172 : ! Comparisons
173 : PROCEDURE, PRIVATE, PASS, NON_OVERRIDABLE :: mp_comm_op_eq
174 : PROCEDURE, PRIVATE, PASS, NON_OVERRIDABLE :: mp_comm_op_neq
175 : GENERIC, PUBLIC :: operator(==) => mp_comm_op_eq
176 : GENERIC, PUBLIC :: operator(/=) => mp_comm_op_neq
177 : ! Communication routines
178 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: &
179 : mp_sendrecv_i, mp_sendrecv_l, mp_sendrecv_r, mp_sendrecv_d, &
180 : mp_sendrecv_c, mp_sendrecv_z, &
181 : mp_sendrecv_iv, mp_sendrecv_im2, mp_sendrecv_im3, mp_sendrecv_im4, &
182 : mp_sendrecv_lv, mp_sendrecv_lm2, mp_sendrecv_lm3, mp_sendrecv_lm4, &
183 : mp_sendrecv_rv, mp_sendrecv_rm2, mp_sendrecv_rm3, mp_sendrecv_rm4, &
184 : mp_sendrecv_dv, mp_sendrecv_dm2, mp_sendrecv_dm3, mp_sendrecv_dm4, &
185 : mp_sendrecv_cv, mp_sendrecv_cm2, mp_sendrecv_cm3, mp_sendrecv_cm4, &
186 : mp_sendrecv_zv, mp_sendrecv_zm2, mp_sendrecv_zm3, mp_sendrecv_zm4
187 : GENERIC, PUBLIC :: sendrecv => mp_sendrecv_i, mp_sendrecv_l, &
188 : mp_sendrecv_r, mp_sendrecv_d, mp_sendrecv_c, mp_sendrecv_z, &
189 : mp_sendrecv_iv, mp_sendrecv_im2, mp_sendrecv_im3, mp_sendrecv_im4, &
190 : mp_sendrecv_lv, mp_sendrecv_lm2, mp_sendrecv_lm3, mp_sendrecv_lm4, &
191 : mp_sendrecv_rv, mp_sendrecv_rm2, mp_sendrecv_rm3, mp_sendrecv_rm4, &
192 : mp_sendrecv_dv, mp_sendrecv_dm2, mp_sendrecv_dm3, mp_sendrecv_dm4, &
193 : mp_sendrecv_cv, mp_sendrecv_cm2, mp_sendrecv_cm3, mp_sendrecv_cm4, &
194 : mp_sendrecv_zv, mp_sendrecv_zm2, mp_sendrecv_zm3, mp_sendrecv_zm4
195 :
196 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_minloc_iv, &
197 : mp_minloc_lv, mp_minloc_rv, mp_minloc_dv
198 : GENERIC, PUBLIC :: minloc => mp_minloc_iv, &
199 : mp_minloc_lv, mp_minloc_rv, mp_minloc_dv
200 :
201 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_maxloc_iv, &
202 : mp_maxloc_lv, mp_maxloc_rv, mp_maxloc_dv
203 : GENERIC, PUBLIC :: maxloc => mp_maxloc_iv, &
204 : mp_maxloc_lv, mp_maxloc_rv, mp_maxloc_dv
205 :
206 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_shift_im, mp_shift_i, &
207 : mp_shift_lm, mp_shift_l, mp_shift_rm, mp_shift_r, &
208 : mp_shift_dm, mp_shift_d, mp_shift_cm, mp_shift_c, &
209 : mp_shift_zm, mp_shift_z
210 : GENERIC, PUBLIC :: shift => mp_shift_im, mp_shift_i, &
211 : mp_shift_lm, mp_shift_l, mp_shift_rm, mp_shift_r, &
212 : mp_shift_dm, mp_shift_d, mp_shift_cm, mp_shift_c, &
213 : mp_shift_zm, mp_shift_z
214 :
215 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_bcast_i, mp_bcast_iv, mp_bcast_im, mp_bcast_i3, &
216 : mp_bcast_l, mp_bcast_lv, mp_bcast_lm, mp_bcast_l3, &
217 : mp_bcast_r, mp_bcast_rv, mp_bcast_rm, mp_bcast_r3, &
218 : mp_bcast_d, mp_bcast_dv, mp_bcast_dm, mp_bcast_d3, &
219 : mp_bcast_c, mp_bcast_cv, mp_bcast_cm, mp_bcast_c3, &
220 : mp_bcast_z, mp_bcast_zv, mp_bcast_zm, mp_bcast_z3, &
221 : mp_bcast_b, mp_bcast_bv, mp_bcast_av, mp_bcast_am, &
222 : mp_bcast_i_src, mp_bcast_iv_src, mp_bcast_im_src, mp_bcast_i3_src, &
223 : mp_bcast_l_src, mp_bcast_lv_src, mp_bcast_lm_src, mp_bcast_l3_src, &
224 : mp_bcast_r_src, mp_bcast_rv_src, mp_bcast_rm_src, mp_bcast_r3_src, &
225 : mp_bcast_d_src, mp_bcast_dv_src, mp_bcast_dm_src, mp_bcast_d3_src, &
226 : mp_bcast_c_src, mp_bcast_cv_src, mp_bcast_cm_src, mp_bcast_c3_src, &
227 : mp_bcast_z_src, mp_bcast_zv_src, mp_bcast_zm_src, mp_bcast_z3_src, &
228 : mp_bcast_b_src, mp_bcast_bv_src, mp_bcast_av_src, mp_bcast_am_src
229 : GENERIC, PUBLIC :: bcast => mp_bcast_i, mp_bcast_iv, mp_bcast_im, mp_bcast_i3, &
230 : mp_bcast_l, mp_bcast_lv, mp_bcast_lm, mp_bcast_l3, &
231 : mp_bcast_r, mp_bcast_rv, mp_bcast_rm, mp_bcast_r3, &
232 : mp_bcast_d, mp_bcast_dv, mp_bcast_dm, mp_bcast_d3, &
233 : mp_bcast_c, mp_bcast_cv, mp_bcast_cm, mp_bcast_c3, &
234 : mp_bcast_z, mp_bcast_zv, mp_bcast_zm, mp_bcast_z3, &
235 : mp_bcast_b, mp_bcast_bv, mp_bcast_av, mp_bcast_am, &
236 : mp_bcast_i_src, mp_bcast_iv_src, mp_bcast_im_src, mp_bcast_i3_src, &
237 : mp_bcast_l_src, mp_bcast_lv_src, mp_bcast_lm_src, mp_bcast_l3_src, &
238 : mp_bcast_r_src, mp_bcast_rv_src, mp_bcast_rm_src, mp_bcast_r3_src, &
239 : mp_bcast_d_src, mp_bcast_dv_src, mp_bcast_dm_src, mp_bcast_d3_src, &
240 : mp_bcast_c_src, mp_bcast_cv_src, mp_bcast_cm_src, mp_bcast_c3_src, &
241 : mp_bcast_z_src, mp_bcast_zv_src, mp_bcast_zm_src, mp_bcast_z3_src, &
242 : mp_bcast_b_src, mp_bcast_bv_src, mp_bcast_av_src, mp_bcast_am_src
243 :
244 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_ibcast_i, mp_ibcast_iv, &
245 : mp_ibcast_l, mp_ibcast_lv, mp_ibcast_r, mp_ibcast_rv, &
246 : mp_ibcast_d, mp_ibcast_dv, mp_ibcast_c, mp_ibcast_cv, &
247 : mp_ibcast_z, mp_ibcast_zv
248 : GENERIC, PUBLIC :: ibcast => mp_ibcast_i, mp_ibcast_iv, &
249 : mp_ibcast_l, mp_ibcast_lv, mp_ibcast_r, mp_ibcast_rv, &
250 : mp_ibcast_d, mp_ibcast_dv, mp_ibcast_c, mp_ibcast_cv, &
251 : mp_ibcast_z, mp_ibcast_zv
252 :
253 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: &
254 : mp_sum_i, mp_sum_iv, mp_sum_im, mp_sum_im3, mp_sum_im4, &
255 : mp_sum_l, mp_sum_lv, mp_sum_lm, mp_sum_lm3, mp_sum_lm4, &
256 : mp_sum_r, mp_sum_rv, mp_sum_rm, mp_sum_rm3, mp_sum_rm4, &
257 : mp_sum_d, mp_sum_dv, mp_sum_dm, mp_sum_dm3, mp_sum_dm4, &
258 : mp_sum_c, mp_sum_cv, mp_sum_cm, mp_sum_cm3, mp_sum_cm4, &
259 : mp_sum_z, mp_sum_zv, mp_sum_zm, mp_sum_zm3, mp_sum_zm4, &
260 : mp_sum_root_iv, mp_sum_root_im, mp_sum_root_lv, mp_sum_root_lm, &
261 : mp_sum_root_rv, mp_sum_root_rm, mp_sum_root_dv, mp_sum_root_dm, &
262 : mp_sum_root_cv, mp_sum_root_cm, mp_sum_root_zv, mp_sum_root_zm, &
263 : mp_sum_b, mp_sum_bv
264 : GENERIC, PUBLIC :: sum => mp_sum_i, mp_sum_iv, mp_sum_im, mp_sum_im3, mp_sum_im4, &
265 : mp_sum_l, mp_sum_lv, mp_sum_lm, mp_sum_lm3, mp_sum_lm4, &
266 : mp_sum_r, mp_sum_rv, mp_sum_rm, mp_sum_rm3, mp_sum_rm4, &
267 : mp_sum_d, mp_sum_dv, mp_sum_dm, mp_sum_dm3, mp_sum_dm4, &
268 : mp_sum_c, mp_sum_cv, mp_sum_cm, mp_sum_cm3, mp_sum_cm4, &
269 : mp_sum_z, mp_sum_zv, mp_sum_zm, mp_sum_zm3, mp_sum_zm4, &
270 : mp_sum_root_iv, mp_sum_root_im, mp_sum_root_lv, mp_sum_root_lm, &
271 : mp_sum_root_rv, mp_sum_root_rm, mp_sum_root_dv, mp_sum_root_dm, &
272 : mp_sum_root_cv, mp_sum_root_cm, mp_sum_root_zv, mp_sum_root_zm, &
273 : mp_sum_b, mp_sum_bv
274 :
275 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_isum_iv, &
276 : mp_isum_lv, mp_isum_rv, mp_isum_dv, mp_isum_cv, &
277 : mp_isum_zv, mp_isum_bv
278 : GENERIC, PUBLIC :: isum => mp_isum_iv, &
279 : mp_isum_lv, mp_isum_rv, mp_isum_dv, mp_isum_cv, &
280 : mp_isum_zv, mp_isum_bv
281 :
282 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_sum_partial_im, &
283 : mp_sum_partial_lm, mp_sum_partial_rm, mp_sum_partial_dm, &
284 : mp_sum_partial_cm, mp_sum_partial_zm
285 : GENERIC, PUBLIC :: sum_partial => mp_sum_partial_im, &
286 : mp_sum_partial_lm, mp_sum_partial_rm, mp_sum_partial_dm, &
287 : mp_sum_partial_cm, mp_sum_partial_zm
288 :
289 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_max_i, mp_max_iv, &
290 : mp_max_im, &
291 : mp_max_l, mp_max_lv, mp_max_lm, &
292 : mp_max_r, mp_max_rv, mp_max_rm, &
293 : mp_max_d, mp_max_dv, mp_max_dm, &
294 : mp_max_c, mp_max_cv, mp_max_cm, &
295 : mp_max_z, mp_max_zv, mp_max_zm, &
296 : mp_max_root_i, mp_max_root_l, &
297 : mp_max_root_r, mp_max_root_d, mp_max_root_c, mp_max_root_z, &
298 : mp_max_root_im, mp_max_root_lm, mp_max_root_rm, mp_max_root_dm, &
299 : mp_max_root_cm, mp_max_root_zm
300 : GENERIC, PUBLIC :: max => mp_max_i, mp_max_iv, &
301 : mp_max_im, &
302 : mp_max_l, mp_max_lv, mp_max_lm, &
303 : mp_max_r, mp_max_rv, mp_max_rm, &
304 : mp_max_d, mp_max_dv, mp_max_dm, &
305 : mp_max_c, mp_max_cv, mp_max_cm, &
306 : mp_max_z, mp_max_zv, mp_max_zm, &
307 : mp_max_root_i, mp_max_root_l, &
308 : mp_max_root_r, mp_max_root_d, mp_max_root_c, mp_max_root_z, &
309 : mp_max_root_im, mp_max_root_lm, mp_max_root_rm, mp_max_root_dm, &
310 : mp_max_root_cm, mp_max_root_zm
311 :
312 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_min_i, mp_min_iv, &
313 : mp_min_im, &
314 : mp_min_l, mp_min_lv, mp_min_lm, &
315 : mp_min_r, mp_min_rv, mp_min_rm, &
316 : mp_min_d, mp_min_dv, mp_min_dm, &
317 : mp_min_c, mp_min_cv, mp_min_cm, &
318 : mp_min_z, mp_min_zv, mp_min_zm
319 : GENERIC, PUBLIC :: min => mp_min_i, mp_min_iv, &
320 : mp_min_im, &
321 : mp_min_l, mp_min_lv, mp_min_lm, &
322 : mp_min_r, mp_min_rv, mp_min_rm, &
323 : mp_min_d, mp_min_dv, mp_min_dm, &
324 : mp_min_c, mp_min_cv, mp_min_cm, &
325 : mp_min_z, mp_min_zv, mp_min_zm
326 :
327 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: &
328 : mp_sum_scatter_iv, mp_sum_scatter_lv, mp_sum_scatter_rv, &
329 : mp_sum_scatter_dv, mp_sum_scatter_cv, mp_sum_scatter_zv
330 : GENERIC, PUBLIC :: sum_scatter => &
331 : mp_sum_scatter_iv, mp_sum_scatter_lv, mp_sum_scatter_rv, &
332 : mp_sum_scatter_dv, mp_sum_scatter_cv, mp_sum_scatter_zv
333 :
334 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_prod_r, mp_prod_d, mp_prod_c, mp_prod_z
335 : GENERIC, PUBLIC :: prod => mp_prod_r, mp_prod_d, mp_prod_c, mp_prod_z
336 :
337 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_gather_i, mp_gather_iv, mp_gather_im, &
338 : mp_gather_l, mp_gather_lv, mp_gather_lm, &
339 : mp_gather_r, mp_gather_rv, mp_gather_rm, &
340 : mp_gather_d, mp_gather_dv, mp_gather_dm, &
341 : mp_gather_c, mp_gather_cv, mp_gather_cm, &
342 : mp_gather_z, mp_gather_zv, mp_gather_zm, &
343 : mp_gather_i_src, mp_gather_iv_src, mp_gather_im_src, &
344 : mp_gather_l_src, mp_gather_lv_src, mp_gather_lm_src, &
345 : mp_gather_r_src, mp_gather_rv_src, mp_gather_rm_src, &
346 : mp_gather_d_src, mp_gather_dv_src, mp_gather_dm_src, &
347 : mp_gather_c_src, mp_gather_cv_src, mp_gather_cm_src, &
348 : mp_gather_z_src, mp_gather_zv_src, mp_gather_zm_src
349 : GENERIC, PUBLIC :: gather => mp_gather_i, mp_gather_iv, mp_gather_im, &
350 : mp_gather_l, mp_gather_lv, mp_gather_lm, &
351 : mp_gather_r, mp_gather_rv, mp_gather_rm, &
352 : mp_gather_d, mp_gather_dv, mp_gather_dm, &
353 : mp_gather_c, mp_gather_cv, mp_gather_cm, &
354 : mp_gather_z, mp_gather_zv, mp_gather_zm, &
355 : mp_gather_i_src, mp_gather_iv_src, mp_gather_im_src, &
356 : mp_gather_l_src, mp_gather_lv_src, mp_gather_lm_src, &
357 : mp_gather_r_src, mp_gather_rv_src, mp_gather_rm_src, &
358 : mp_gather_d_src, mp_gather_dv_src, mp_gather_dm_src, &
359 : mp_gather_c_src, mp_gather_cv_src, mp_gather_cm_src, &
360 : mp_gather_z_src, mp_gather_zv_src, mp_gather_zm_src
361 :
362 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_gatherv_iv, &
363 : mp_gatherv_lv, mp_gatherv_rv, mp_gatherv_dv, &
364 : mp_gatherv_cv, mp_gatherv_zv, mp_gatherv_lm2, mp_gatherv_rm2, &
365 : mp_gatherv_dm2, mp_gatherv_cm2, mp_gatherv_zm2, mp_gatherv_iv_src, &
366 : mp_gatherv_lv_src, mp_gatherv_rv_src, mp_gatherv_dv_src, &
367 : mp_gatherv_cv_src, mp_gatherv_zv_src, mp_gatherv_lm2_src, mp_gatherv_rm2_src, &
368 : mp_gatherv_dm2_src, mp_gatherv_cm2_src, mp_gatherv_zm2_src
369 : GENERIC, PUBLIC :: gatherv => mp_gatherv_iv, &
370 : mp_gatherv_lv, mp_gatherv_rv, mp_gatherv_dv, &
371 : mp_gatherv_cv, mp_gatherv_zv, mp_gatherv_lm2, mp_gatherv_rm2, &
372 : mp_gatherv_dm2, mp_gatherv_cm2, mp_gatherv_zm2, mp_gatherv_iv_src, &
373 : mp_gatherv_lv_src, mp_gatherv_rv_src, mp_gatherv_dv_src, &
374 : mp_gatherv_cv_src, mp_gatherv_zv_src, mp_gatherv_lm2_src, mp_gatherv_rm2_src, &
375 : mp_gatherv_dm2_src, mp_gatherv_cm2_src, mp_gatherv_zm2_src
376 :
377 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_igatherv_iv, &
378 : mp_igatherv_lv, mp_igatherv_rv, mp_igatherv_dv, &
379 : mp_igatherv_cv, mp_igatherv_zv
380 : GENERIC, PUBLIC :: igatherv => mp_igatherv_iv, &
381 : mp_igatherv_lv, mp_igatherv_rv, mp_igatherv_dv, &
382 : mp_igatherv_cv, mp_igatherv_zv
383 :
384 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_allgather_i, mp_allgather_i2, &
385 : mp_allgather_i12, mp_allgather_i23, mp_allgather_i34, &
386 : mp_allgather_i22, mp_allgather_l, mp_allgather_l2, &
387 : mp_allgather_l12, mp_allgather_l23, mp_allgather_l34, &
388 : mp_allgather_l22, mp_allgather_r, mp_allgather_r2, &
389 : mp_allgather_r12, mp_allgather_r23, mp_allgather_r34, &
390 : mp_allgather_r22, mp_allgather_d, mp_allgather_d2, &
391 : mp_allgather_d12, mp_allgather_d23, mp_allgather_d34, &
392 : mp_allgather_d22, mp_allgather_c, mp_allgather_c2, &
393 : mp_allgather_c12, mp_allgather_c23, mp_allgather_c34, &
394 : mp_allgather_c22, mp_allgather_z, mp_allgather_z2, &
395 : mp_allgather_z12, mp_allgather_z23, mp_allgather_z34, &
396 : mp_allgather_z22
397 : GENERIC, PUBLIC :: allgather => mp_allgather_i, mp_allgather_i2, &
398 : mp_allgather_i12, mp_allgather_i23, mp_allgather_i34, &
399 : mp_allgather_i22, mp_allgather_l, mp_allgather_l2, &
400 : mp_allgather_l12, mp_allgather_l23, mp_allgather_l34, &
401 : mp_allgather_l22, mp_allgather_r, mp_allgather_r2, &
402 : mp_allgather_r12, mp_allgather_r23, mp_allgather_r34, &
403 : mp_allgather_r22, mp_allgather_d, mp_allgather_d2, &
404 : mp_allgather_d12, mp_allgather_d23, mp_allgather_d34, &
405 : mp_allgather_d22, mp_allgather_c, mp_allgather_c2, &
406 : mp_allgather_c12, mp_allgather_c23, mp_allgather_c34, &
407 : mp_allgather_c22, mp_allgather_z, mp_allgather_z2, &
408 : mp_allgather_z12, mp_allgather_z23, mp_allgather_z34, &
409 : mp_allgather_z22
410 :
411 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_allgatherv_iv, mp_allgatherv_lv, &
412 : mp_allgatherv_rv, mp_allgatherv_dv, mp_allgatherv_cv, mp_allgatherv_zv, &
413 : mp_allgatherv_im2, mp_allgatherv_lm2, mp_allgatherv_rm2, &
414 : mp_allgatherv_dm2, mp_allgatherv_cm2, mp_allgatherv_zm2
415 : GENERIC, PUBLIC :: allgatherv => mp_allgatherv_iv, mp_allgatherv_lv, &
416 : mp_allgatherv_rv, mp_allgatherv_dv, mp_allgatherv_cv, mp_allgatherv_zv, &
417 : mp_allgatherv_im2, mp_allgatherv_lm2, mp_allgatherv_rm2, &
418 : mp_allgatherv_dm2, mp_allgatherv_cm2, mp_allgatherv_zm2
419 :
420 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_iallgather_i, mp_iallgather_l, &
421 : mp_iallgather_r, mp_iallgather_d, mp_iallgather_c, mp_iallgather_z, &
422 : mp_iallgather_i11, mp_iallgather_l11, mp_iallgather_r11, mp_iallgather_d11, &
423 : mp_iallgather_c11, mp_iallgather_z11, mp_iallgather_i13, mp_iallgather_l13, &
424 : mp_iallgather_r13, mp_iallgather_d13, mp_iallgather_c13, mp_iallgather_z13, &
425 : mp_iallgather_i22, mp_iallgather_l22, mp_iallgather_r22, mp_iallgather_d22, &
426 : mp_iallgather_c22, mp_iallgather_z22, mp_iallgather_i24, mp_iallgather_l24, &
427 : mp_iallgather_r24, mp_iallgather_d24, mp_iallgather_c24, mp_iallgather_z24, &
428 : mp_iallgather_i33, mp_iallgather_l33, mp_iallgather_r33, mp_iallgather_d33, &
429 : mp_iallgather_c33, mp_iallgather_z33
430 : GENERIC, PUBLIC :: iallgather => mp_iallgather_i, mp_iallgather_l, &
431 : mp_iallgather_r, mp_iallgather_d, mp_iallgather_c, mp_iallgather_z, &
432 : mp_iallgather_i11, mp_iallgather_l11, mp_iallgather_r11, mp_iallgather_d11, &
433 : mp_iallgather_c11, mp_iallgather_z11, mp_iallgather_i13, mp_iallgather_l13, &
434 : mp_iallgather_r13, mp_iallgather_d13, mp_iallgather_c13, mp_iallgather_z13, &
435 : mp_iallgather_i22, mp_iallgather_l22, mp_iallgather_r22, mp_iallgather_d22, &
436 : mp_iallgather_c22, mp_iallgather_z22, mp_iallgather_i24, mp_iallgather_l24, &
437 : mp_iallgather_r24, mp_iallgather_d24, mp_iallgather_c24, mp_iallgather_z24, &
438 : mp_iallgather_i33, mp_iallgather_l33, mp_iallgather_r33, mp_iallgather_d33, &
439 : mp_iallgather_c33, mp_iallgather_z33
440 :
441 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_iallgatherv_iv, mp_iallgatherv_iv2, &
442 : mp_iallgatherv_lv, mp_iallgatherv_lv2, mp_iallgatherv_rv, mp_iallgatherv_rv2, &
443 : mp_iallgatherv_dv, mp_iallgatherv_dv2, mp_iallgatherv_cv, mp_iallgatherv_cv2, &
444 : mp_iallgatherv_zv, mp_iallgatherv_zv2
445 : GENERIC, PUBLIC :: iallgatherv => mp_iallgatherv_iv, mp_iallgatherv_iv2, &
446 : mp_iallgatherv_lv, mp_iallgatherv_lv2, mp_iallgatherv_rv, mp_iallgatherv_rv2, &
447 : mp_iallgatherv_dv, mp_iallgatherv_dv2, mp_iallgatherv_cv, mp_iallgatherv_cv2, &
448 : mp_iallgatherv_zv, mp_iallgatherv_zv2
449 :
450 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_scatter_iv, mp_scatter_lv, &
451 : mp_scatter_rv, mp_scatter_dv, mp_scatter_cv, mp_scatter_zv
452 : GENERIC, PUBLIC :: scatter => mp_scatter_iv, mp_scatter_lv, &
453 : mp_scatter_rv, mp_scatter_dv, mp_scatter_cv, mp_scatter_zv
454 :
455 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_iscatter_i, mp_iscatter_l, &
456 : mp_iscatter_r, mp_iscatter_d, mp_iscatter_c, mp_iscatter_z, &
457 : mp_iscatter_iv2, mp_iscatter_lv2, mp_iscatter_rv2, mp_iscatter_dv2, &
458 : mp_iscatter_cv2, mp_iscatter_zv2
459 : GENERIC, PUBLIC :: iscatter => mp_iscatter_i, mp_iscatter_l, &
460 : mp_iscatter_r, mp_iscatter_d, mp_iscatter_c, mp_iscatter_z, &
461 : mp_iscatter_iv2, mp_iscatter_lv2, mp_iscatter_rv2, mp_iscatter_dv2, &
462 : mp_iscatter_cv2, mp_iscatter_zv2
463 :
464 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_iscatterv_iv, mp_iscatterv_lv, &
465 : mp_iscatterv_rv, mp_iscatterv_dv, mp_iscatterv_cv, mp_iscatterv_zv
466 : GENERIC, PUBLIC :: iscatterv => mp_iscatterv_iv, mp_iscatterv_lv, &
467 : mp_iscatterv_rv, mp_iscatterv_dv, mp_iscatterv_cv, mp_iscatterv_zv
468 :
469 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_alltoall_i, mp_alltoall_i22, mp_alltoall_i33, &
470 : mp_alltoall_i44, mp_alltoall_i55, mp_alltoall_i45, mp_alltoall_i34, &
471 : mp_alltoall_i11v, mp_alltoall_i22v, mp_alltoall_i54, &
472 : mp_alltoall_l, mp_alltoall_l22, mp_alltoall_l33, &
473 : mp_alltoall_l44, mp_alltoall_l55, mp_alltoall_l45, mp_alltoall_l34, &
474 : mp_alltoall_l11v, mp_alltoall_l22v, mp_alltoall_l54, &
475 : mp_alltoall_r, mp_alltoall_r22, mp_alltoall_r33, &
476 : mp_alltoall_r44, mp_alltoall_r55, mp_alltoall_r45, mp_alltoall_r34, &
477 : mp_alltoall_r11v, mp_alltoall_r22v, mp_alltoall_r54, &
478 : mp_alltoall_d, mp_alltoall_d22, mp_alltoall_d33, &
479 : mp_alltoall_d44, mp_alltoall_d55, mp_alltoall_d45, mp_alltoall_d34, &
480 : mp_alltoall_d11v, mp_alltoall_d22v, mp_alltoall_d54, &
481 : mp_alltoall_c, mp_alltoall_c22, mp_alltoall_c33, &
482 : mp_alltoall_c44, mp_alltoall_c55, mp_alltoall_c45, mp_alltoall_c34, &
483 : mp_alltoall_c11v, mp_alltoall_c22v, mp_alltoall_c54, &
484 : mp_alltoall_z, mp_alltoall_z22, mp_alltoall_z33, &
485 : mp_alltoall_z44, mp_alltoall_z55, mp_alltoall_z45, mp_alltoall_z34, &
486 : mp_alltoall_z11v, mp_alltoall_z22v, mp_alltoall_z54
487 : GENERIC, PUBLIC :: alltoall => mp_alltoall_i, mp_alltoall_i22, mp_alltoall_i33, &
488 : mp_alltoall_i44, mp_alltoall_i55, mp_alltoall_i45, mp_alltoall_i34, &
489 : mp_alltoall_i11v, mp_alltoall_i22v, mp_alltoall_i54, &
490 : mp_alltoall_l, mp_alltoall_l22, mp_alltoall_l33, &
491 : mp_alltoall_l44, mp_alltoall_l55, mp_alltoall_l45, mp_alltoall_l34, &
492 : mp_alltoall_l11v, mp_alltoall_l22v, mp_alltoall_l54, &
493 : mp_alltoall_r, mp_alltoall_r22, mp_alltoall_r33, &
494 : mp_alltoall_r44, mp_alltoall_r55, mp_alltoall_r45, mp_alltoall_r34, &
495 : mp_alltoall_r11v, mp_alltoall_r22v, mp_alltoall_r54, &
496 : mp_alltoall_d, mp_alltoall_d22, mp_alltoall_d33, &
497 : mp_alltoall_d44, mp_alltoall_d55, mp_alltoall_d45, mp_alltoall_d34, &
498 : mp_alltoall_d11v, mp_alltoall_d22v, mp_alltoall_d54, &
499 : mp_alltoall_c, mp_alltoall_c22, mp_alltoall_c33, &
500 : mp_alltoall_c44, mp_alltoall_c55, mp_alltoall_c45, mp_alltoall_c34, &
501 : mp_alltoall_c11v, mp_alltoall_c22v, mp_alltoall_c54, &
502 : mp_alltoall_z, mp_alltoall_z22, mp_alltoall_z33, &
503 : mp_alltoall_z44, mp_alltoall_z55, mp_alltoall_z45, mp_alltoall_z34, &
504 : mp_alltoall_z11v, mp_alltoall_z22v, mp_alltoall_z54
505 :
506 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_send_i, mp_send_iv, mp_send_im2, mp_send_im3, &
507 : mp_send_l, mp_send_lv, mp_send_lm2, mp_send_lm3, &
508 : mp_send_r, mp_send_rv, mp_send_rm2, mp_send_rm3, &
509 : mp_send_d, mp_send_dv, mp_send_dm2, mp_send_dm3, &
510 : mp_send_c, mp_send_cv, mp_send_cm2, mp_send_cm3, &
511 : mp_send_z, mp_send_zv, mp_send_zm2, mp_send_zm3
512 : GENERIC, PUBLIC :: send => mp_send_i, mp_send_iv, mp_send_im2, mp_send_im3, &
513 : mp_send_l, mp_send_lv, mp_send_lm2, mp_send_lm3, &
514 : mp_send_r, mp_send_rv, mp_send_rm2, mp_send_rm3, &
515 : mp_send_d, mp_send_dv, mp_send_dm2, mp_send_dm3, &
516 : mp_send_c, mp_send_cv, mp_send_cm2, mp_send_cm3, &
517 : mp_send_z, mp_send_zv, mp_send_zm2, mp_send_zm3
518 :
519 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_recv_i, mp_recv_iv, mp_recv_im2, mp_recv_im3, &
520 : mp_recv_l, mp_recv_lv, mp_recv_lm2, mp_recv_lm3, &
521 : mp_recv_r, mp_recv_rv, mp_recv_rm2, mp_recv_rm3, &
522 : mp_recv_d, mp_recv_dv, mp_recv_dm2, mp_recv_dm3, &
523 : mp_recv_c, mp_recv_cv, mp_recv_cm2, mp_recv_cm3, &
524 : mp_recv_z, mp_recv_zv, mp_recv_zm2, mp_recv_zm3
525 : GENERIC, PUBLIC :: recv => mp_recv_i, mp_recv_iv, mp_recv_im2, mp_recv_im3, &
526 : mp_recv_l, mp_recv_lv, mp_recv_lm2, mp_recv_lm3, &
527 : mp_recv_r, mp_recv_rv, mp_recv_rm2, mp_recv_rm3, &
528 : mp_recv_d, mp_recv_dv, mp_recv_dm2, mp_recv_dm3, &
529 : mp_recv_c, mp_recv_cv, mp_recv_cm2, mp_recv_cm3, &
530 : mp_recv_z, mp_recv_zv, mp_recv_zm2, mp_recv_zm3
531 :
532 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_isendrecv_i, mp_isendrecv_iv, &
533 : mp_isendrecv_l, mp_isendrecv_lv, mp_isendrecv_r, mp_isendrecv_rv, &
534 : mp_isendrecv_d, mp_isendrecv_dv, mp_isendrecv_c, mp_isendrecv_cv, &
535 : mp_isendrecv_z, mp_isendrecv_zv
536 : GENERIC, PUBLIC :: isendrecv => mp_isendrecv_i, mp_isendrecv_iv, &
537 : mp_isendrecv_l, mp_isendrecv_lv, mp_isendrecv_r, mp_isendrecv_rv, &
538 : mp_isendrecv_d, mp_isendrecv_dv, mp_isendrecv_c, mp_isendrecv_cv, &
539 : mp_isendrecv_z, mp_isendrecv_zv
540 :
541 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_isend_iv, mp_isend_im2, mp_isend_im3, mp_isend_im4, &
542 : mp_isend_lv, mp_isend_lm2, mp_isend_lm3, mp_isend_lm4, &
543 : mp_isend_rv, mp_isend_rm2, mp_isend_rm3, mp_isend_rm4, &
544 : mp_isend_dv, mp_isend_dm2, mp_isend_dm3, mp_isend_dm4, &
545 : mp_isend_cv, mp_isend_cm2, mp_isend_cm3, mp_isend_cm4, &
546 : mp_isend_zv, mp_isend_zm2, mp_isend_zm3, mp_isend_zm4, &
547 : mp_isend_bv, mp_isend_bm3, mp_isend_custom
548 : GENERIC, PUBLIC :: isend => mp_isend_iv, mp_isend_im2, mp_isend_im3, mp_isend_im4, &
549 : mp_isend_lv, mp_isend_lm2, mp_isend_lm3, mp_isend_lm4, &
550 : mp_isend_rv, mp_isend_rm2, mp_isend_rm3, mp_isend_rm4, &
551 : mp_isend_dv, mp_isend_dm2, mp_isend_dm3, mp_isend_dm4, &
552 : mp_isend_cv, mp_isend_cm2, mp_isend_cm3, mp_isend_cm4, &
553 : mp_isend_zv, mp_isend_zm2, mp_isend_zm3, mp_isend_zm4, &
554 : mp_isend_bv, mp_isend_bm3, mp_isend_custom
555 :
556 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_irecv_iv, mp_irecv_im2, mp_irecv_im3, mp_irecv_im4, &
557 : mp_irecv_lv, mp_irecv_lm2, mp_irecv_lm3, mp_irecv_lm4, &
558 : mp_irecv_rv, mp_irecv_rm2, mp_irecv_rm3, mp_irecv_rm4, &
559 : mp_irecv_dv, mp_irecv_dm2, mp_irecv_dm3, mp_irecv_dm4, &
560 : mp_irecv_cv, mp_irecv_cm2, mp_irecv_cm3, mp_irecv_cm4, &
561 : mp_irecv_zv, mp_irecv_zm2, mp_irecv_zm3, mp_irecv_zm4, &
562 : mp_irecv_bv, mp_irecv_bm3, mp_irecv_custom
563 : GENERIC, PUBLIC :: irecv => mp_irecv_iv, mp_irecv_im2, mp_irecv_im3, mp_irecv_im4, &
564 : mp_irecv_lv, mp_irecv_lm2, mp_irecv_lm3, mp_irecv_lm4, &
565 : mp_irecv_rv, mp_irecv_rm2, mp_irecv_rm3, mp_irecv_rm4, &
566 : mp_irecv_dv, mp_irecv_dm2, mp_irecv_dm3, mp_irecv_dm4, &
567 : mp_irecv_cv, mp_irecv_cm2, mp_irecv_cm3, mp_irecv_cm4, &
568 : mp_irecv_zv, mp_irecv_zm2, mp_irecv_zm3, mp_irecv_zm4, &
569 : mp_irecv_bv, mp_irecv_bm3, mp_irecv_custom
570 :
571 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: probe => mp_probe
572 :
573 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: sync => mp_sync
574 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: isync => mp_isync
575 :
576 : PROCEDURE, PUBLIC, PASS(comm1), NON_OVERRIDABLE :: compare => mp_comm_compare
577 : PROCEDURE, PUBLIC, PASS(comm1), NON_OVERRIDABLE :: rank_compare => mp_rank_compare
578 :
579 : PROCEDURE, PUBLIC, PASS(comm2), NON_OVERRIDABLE :: from_dup => mp_comm_dup
580 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: mp_comm_free
581 : GENERIC, PUBLIC :: free => mp_comm_free
582 :
583 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: mp_comm_init
584 : GENERIC, PUBLIC :: init => mp_comm_init
585 :
586 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: get_size => mp_comm_size
587 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: get_rank => mp_comm_rank
588 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: get_ndims => mp_comm_get_ndims
589 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: is_source => mp_comm_is_source
590 :
591 : ! Creation routines
592 : PROCEDURE, PRIVATE, PASS(sub_comm), NON_OVERRIDABLE :: mp_comm_split, mp_comm_split_direct
593 : GENERIC, PUBLIC :: from_split => mp_comm_split, mp_comm_split_direct
594 : PROCEDURE, PUBLIC, PASS(sub_comm), NON_OVERRIDABLE :: from_split_type => mp_comm_split_type
595 : PROCEDURE, PUBLIC, PASS(mp_new_comm), NON_OVERRIDABLE :: from_reordering => mp_reordering
596 : PROCEDURE, PUBLIC, PASS(comm_new), NON_OVERRIDABLE :: mp_comm_assign
597 : GENERIC, PUBLIC :: ASSIGNMENT(=) => mp_comm_assign
598 :
599 : ! Other Getters
600 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_comm_get_tag_ub
601 : GENERIC, PUBLIC :: get_tag_ub => mp_comm_get_tag_ub
602 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_comm_get_host_rank
603 : GENERIC, PUBLIC :: get_host_rank => mp_comm_get_host_rank
604 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_comm_get_io_rank
605 : GENERIC, PUBLIC :: get_io_rank => mp_comm_get_io_rank
606 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: mp_comm_get_wtime_is_global
607 : GENERIC, PUBLIC :: get_wtime_is_global => mp_comm_get_wtime_is_global
608 : END TYPE
609 :
610 : TYPE mp_request_type
611 : PRIVATE
612 : MPI_REQUEST_TYPE :: handle = mp_request_null_handle
613 : CONTAINS
614 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: set_handle => mp_request_type_set_handle
615 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: get_handle => mp_request_type_get_handle
616 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_request_op_eq
617 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_request_op_neq
618 : GENERIC, PUBLIC :: OPERATOR(==) => mp_request_op_eq
619 : GENERIC, PUBLIC :: OPERATOR(/=) => mp_request_op_neq
620 :
621 : PROCEDURE, PUBLIC, PASS(request), NON_OVERRIDABLE :: test => mp_test_1
622 :
623 : PROCEDURE, PUBLIC, PASS(request), NON_OVERRIDABLE :: wait => mp_wait
624 : END TYPE
625 :
626 : TYPE mp_win_type
627 : PRIVATE
628 : MPI_WIN_TYPE :: handle = mp_win_null_handle
629 : CONTAINS
630 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: set_handle => mp_win_type_set_handle
631 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: get_handle => mp_win_type_get_handle
632 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_win_op_eq
633 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_win_op_neq
634 : GENERIC, PUBLIC :: OPERATOR(==) => mp_win_op_eq
635 : GENERIC, PUBLIC :: OPERATOR(/=) => mp_win_op_neq
636 :
637 : PROCEDURE, PRIVATE, PASS(win), NON_OVERRIDABLE :: mp_win_create_iv, mp_win_create_lv, &
638 : mp_win_create_rv, mp_win_create_dv, mp_win_create_cv, mp_win_create_zv
639 : GENERIC, PUBLIC :: create => mp_win_create_iv, mp_win_create_lv, &
640 : mp_win_create_rv, mp_win_create_dv, mp_win_create_cv, mp_win_create_zv
641 :
642 : PROCEDURE, PRIVATE, PASS(win), NON_OVERRIDABLE :: mp_rget_iv, mp_rget_lv, &
643 : mp_rget_rv, mp_rget_dv, mp_rget_cv, mp_rget_zv
644 : GENERIC, PUBLIC :: rget => mp_rget_iv, mp_rget_lv, &
645 : mp_rget_rv, mp_rget_dv, mp_rget_cv, mp_rget_zv
646 :
647 : PROCEDURE, PUBLIC, PASS(win), NON_OVERRIDABLE :: free => mp_win_free
648 : PROCEDURE, PUBLIC, PASS(win_new), NON_OVERRIDABLE :: mp_win_assign
649 : GENERIC, PUBLIC :: ASSIGNMENT(=) => mp_win_assign
650 :
651 : PROCEDURE, PUBLIC, PASS(win), NON_OVERRIDABLE :: lock_all => mp_win_lock_all
652 : PROCEDURE, PUBLIC, PASS(win), NON_OVERRIDABLE :: unlock_all => mp_win_unlock_all
653 : PROCEDURE, PUBLIC, PASS(win), NON_OVERRIDABLE :: flush_all => mp_win_flush_all
654 : END TYPE
655 :
656 : TYPE mp_file_type
657 : PRIVATE
658 : MPI_FILE_TYPE :: handle = mp_file_null_handle
659 : CONTAINS
660 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: set_handle => mp_file_type_set_handle
661 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: get_handle => mp_file_type_get_handle
662 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_file_op_eq
663 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_file_op_neq
664 : GENERIC, PUBLIC :: OPERATOR(==) => mp_file_op_eq
665 : GENERIC, PUBLIC :: OPERATOR(/=) => mp_file_op_neq
666 :
667 : PROCEDURE, PRIVATE, PASS(fh), NON_OVERRIDABLE :: mp_file_write_at_ch, mp_file_write_at_chv, &
668 : mp_file_write_at_i, mp_file_write_at_iv, mp_file_write_at_r, mp_file_write_at_rv, &
669 : mp_file_write_at_d, mp_file_write_at_dv, mp_file_write_at_c, mp_file_write_at_cv, &
670 : mp_file_write_at_z, mp_file_write_at_zv, mp_file_write_at_l, mp_file_write_at_lv
671 : GENERIC, PUBLIC :: write_at => mp_file_write_at_ch, mp_file_write_at_chv, &
672 : mp_file_write_at_i, mp_file_write_at_iv, mp_file_write_at_r, mp_file_write_at_rv, &
673 : mp_file_write_at_d, mp_file_write_at_dv, mp_file_write_at_c, mp_file_write_at_cv, &
674 : mp_file_write_at_z, mp_file_write_at_zv, mp_file_write_at_l, mp_file_write_at_lv
675 :
676 : PROCEDURE, PRIVATE, PASS(fh), NON_OVERRIDABLE :: mp_file_write_at_all_ch, mp_file_write_at_all_chv, &
677 : mp_file_write_at_all_i, mp_file_write_at_all_iv, mp_file_write_at_all_l, mp_file_write_at_all_lv, &
678 : mp_file_write_at_all_r, mp_file_write_at_all_rv, mp_file_write_at_all_d, mp_file_write_at_all_dv, &
679 : mp_file_write_at_all_c, mp_file_write_at_all_cv, mp_file_write_at_all_z, mp_file_write_at_all_zv
680 : GENERIC, PUBLIC :: write_at_all => mp_file_write_at_all_ch, mp_file_write_at_all_chv, &
681 : mp_file_write_at_all_i, mp_file_write_at_all_iv, mp_file_write_at_all_l, mp_file_write_at_all_lv, &
682 : mp_file_write_at_all_r, mp_file_write_at_all_rv, mp_file_write_at_all_d, mp_file_write_at_all_dv, &
683 : mp_file_write_at_all_c, mp_file_write_at_all_cv, mp_file_write_at_all_z, mp_file_write_at_all_zv
684 :
685 : PROCEDURE, PRIVATE, PASS(fh), NON_OVERRIDABLE :: mp_file_read_at_ch, mp_file_read_at_chv, &
686 : mp_file_read_at_i, mp_file_read_at_iv, mp_file_read_at_r, mp_file_read_at_rv, &
687 : mp_file_read_at_d, mp_file_read_at_dv, mp_file_read_at_c, mp_file_read_at_cv, &
688 : mp_file_read_at_z, mp_file_read_at_zv, mp_file_read_at_l, mp_file_read_at_lv
689 : GENERIC, PUBLIC :: read_at => mp_file_read_at_ch, mp_file_read_at_chv, &
690 : mp_file_read_at_i, mp_file_read_at_iv, mp_file_read_at_r, mp_file_read_at_rv, &
691 : mp_file_read_at_d, mp_file_read_at_dv, mp_file_read_at_c, mp_file_read_at_cv, &
692 : mp_file_read_at_z, mp_file_read_at_zv, mp_file_read_at_l, mp_file_read_at_lv
693 :
694 : PROCEDURE, PRIVATE, PASS(fh), NON_OVERRIDABLE :: mp_file_read_at_all_ch, mp_file_read_at_all_chv, &
695 : mp_file_read_at_all_i, mp_file_read_at_all_iv, mp_file_read_at_all_l, mp_file_read_at_all_lv, &
696 : mp_file_read_at_all_r, mp_file_read_at_all_rv, mp_file_read_at_all_d, mp_file_read_at_all_dv, &
697 : mp_file_read_at_all_c, mp_file_read_at_all_cv, mp_file_read_at_all_z, mp_file_read_at_all_zv
698 : GENERIC, PUBLIC :: read_at_all => mp_file_read_at_all_ch, mp_file_read_at_all_chv, &
699 : mp_file_read_at_all_i, mp_file_read_at_all_iv, mp_file_read_at_all_l, mp_file_read_at_all_lv, &
700 : mp_file_read_at_all_r, mp_file_read_at_all_rv, mp_file_read_at_all_d, mp_file_read_at_all_dv, &
701 : mp_file_read_at_all_c, mp_file_read_at_all_cv, mp_file_read_at_all_z, mp_file_read_at_all_zv
702 :
703 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: open => mp_file_open
704 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: close => mp_file_close
705 : PROCEDURE, PRIVATE, PASS(fh_new), NON_OVERRIDABLE :: mp_file_assign
706 : GENERIC, PUBLIC :: ASSIGNMENT(=) => mp_file_assign
707 :
708 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: get_size => mp_file_get_size
709 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: get_position => mp_file_get_position
710 :
711 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: read_all => mp_file_read_all_chv
712 : PROCEDURE, PUBLIC, PASS(fh), NON_OVERRIDABLE :: write_all => mp_file_write_all_chv
713 : END TYPE
714 :
715 : TYPE mp_info_type
716 : PRIVATE
717 : MPI_INFO_TYPE :: handle = mp_info_null_handle
718 : CONTAINS
719 : PROCEDURE, NON_OVERRIDABLE :: set_handle => mp_info_type_set_handle
720 : PROCEDURE, NON_OVERRIDABLE :: get_handle => mp_info_type_get_handle
721 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_info_op_eq
722 : PROCEDURE, PRIVATE, NON_OVERRIDABLE :: mp_info_op_neq
723 : GENERIC, PUBLIC :: OPERATOR(==) => mp_info_op_eq
724 : GENERIC, PUBLIC :: OPERATOR(/=) => mp_info_op_neq
725 : END TYPE
726 :
727 : TYPE, EXTENDS(mp_comm_type) :: mp_cart_type
728 : INTEGER, DIMENSION(:), ALLOCATABLE, PUBLIC :: mepos_cart, num_pe_cart
729 : LOGICAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: periodic
730 : CONTAINS
731 : PROCEDURE, PUBLIC, PASS(comm_cart), NON_OVERRIDABLE :: create => mp_cart_create
732 : PROCEDURE, PUBLIC, PASS(sub_comm), NON_OVERRIDABLE :: from_sub => mp_cart_sub
733 :
734 : PROCEDURE, PRIVATE, PASS(comm), NON_OVERRIDABLE :: get_info_cart => mp_cart_get
735 :
736 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: coords => mp_cart_coords
737 : PROCEDURE, PUBLIC, PASS(comm), NON_OVERRIDABLE :: rank_cart => mp_cart_rank
738 : END TYPE
739 :
740 : ! **************************************************************************************************
741 : !> \brief stores all the informations relevant to an mpi environment
742 : !> \param owns_group if it owns the group (and thus should free it when
743 : !> this object is deallocated)
744 : !> \param ref_count the reference count, when it is zero this object gets
745 : !> deallocated
746 : !> \par History
747 : !> 08.2002 created [fawzi]
748 : !> \author Fawzi Mohamed
749 : ! **************************************************************************************************
750 : TYPE, EXTENDS(mp_comm_type) :: mp_para_env_type
751 : PRIVATE
752 : ! We set it to true to have less initialization steps in case we create a new communicator
753 : LOGICAL :: owns_group = .TRUE.
754 : INTEGER :: ref_count = -1
755 : CONTAINS
756 : PROCEDURE, PUBLIC, PASS(para_env), NON_OVERRIDABLE :: retain => mp_para_env_retain
757 : PROCEDURE, PUBLIC, PASS(para_env), NON_OVERRIDABLE :: is_valid => mp_para_env_is_valid
758 : END TYPE mp_para_env_type
759 :
760 : ! **************************************************************************************************
761 : !> \brief represent a pointer to a para env (to build arrays)
762 : !> \param para_env the pointer to the para_env
763 : !> \par History
764 : !> 07.2003 created [fawzi]
765 : !> \author Fawzi Mohamed
766 : ! **************************************************************************************************
767 : TYPE mp_para_env_p_type
768 : TYPE(mp_para_env_type), POINTER :: para_env => NULL()
769 : END TYPE mp_para_env_p_type
770 :
771 : ! **************************************************************************************************
772 : !> \brief represent a multidimensional parallel environment
773 : !> \param mepos_cart the position of the actual processor
774 : !> \param num_pe_cart number of processors in the group in each dimension
775 : !> \param source_cart id of a special processor (for example the one for i-o,
776 : !> or the master
777 : !> \param owns_group if it owns the group (and thus should free it when
778 : !> this object is deallocated)
779 : !> \param ref_count the reference count, when it is zero this object gets
780 : !> deallocated
781 : !> \note
782 : !> not yet implemented for mpi
783 : !> \par History
784 : !> 08.2002 created [fawzi]
785 : !> \author Fawzi Mohamed
786 : ! **************************************************************************************************
787 : TYPE, EXTENDS(mp_cart_type) :: mp_para_cart_type
788 : PRIVATE
789 : ! We set it to true to have less initialization steps in case we create a new communicator
790 : LOGICAL :: owns_group = .TRUE.
791 : INTEGER :: ref_count = -1
792 : CONTAINS
793 : PROCEDURE, PUBLIC, PASS(cart), NON_OVERRIDABLE :: retain => mp_para_cart_retain
794 : PROCEDURE, PUBLIC, PASS(cart), NON_OVERRIDABLE :: is_valid => mp_para_cart_is_valid
795 : END TYPE mp_para_cart_type
796 :
797 : ! Create the constants from the corresponding handles
798 : TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_null = mp_comm_type(mp_comm_null_handle)
799 : TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_self = mp_comm_type(mp_comm_self_handle)
800 : TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_world = mp_comm_type(mp_comm_world_handle)
801 : TYPE(mp_request_type), PARAMETER, PUBLIC :: mp_request_null = mp_request_type(mp_request_null_handle)
802 : TYPE(mp_win_type), PARAMETER, PUBLIC :: mp_win_null = mp_win_type(mp_win_null_handle)
803 : TYPE(mp_file_type), PARAMETER, PUBLIC :: mp_file_null = mp_file_type(mp_file_null_handle)
804 : TYPE(mp_info_type), PARAMETER, PUBLIC :: mp_info_null = mp_info_type(mp_info_null_handle)
805 :
806 : ! Bundles an MPI communicator split type with the info hint it requires
807 : TYPE mp_split_type
808 : PRIVATE
809 : INTEGER :: split_type = mp_comm_split_type_shared_id
810 : TYPE(mp_info_type) :: info = mp_info_null
811 : END TYPE
812 :
813 : ! Node-local (shared-memory) split; needs no info hint.
814 : TYPE(mp_split_type), PARAMETER, PUBLIC :: mp_comm_split_type_shared = &
815 : mp_split_type(mp_comm_split_type_shared_id, mp_info_null)
816 :
817 : #if !defined(__parallel)
818 : ! This communicator is to be used in serial mode to emulate a valid communicator which is not a compiler constant
819 : INTEGER, PARAMETER, PRIVATE :: mp_comm_default_handle = 1
820 : TYPE(mp_comm_type), PARAMETER, PRIVATE :: mp_comm_default = mp_comm_type(mp_comm_default_handle)
821 : #endif
822 :
823 : ! Constants to compare communicators
824 : INTEGER, PARAMETER, PUBLIC :: mp_comm_ident = 0
825 : INTEGER, PARAMETER, PUBLIC :: mp_comm_congruent = 1
826 : INTEGER, PARAMETER, PUBLIC :: mp_comm_similar = 2
827 : INTEGER, PARAMETER, PUBLIC :: mp_comm_unequal = 3
828 : INTEGER, PARAMETER, PUBLIC :: mp_comm_compare_default = -1
829 :
830 : ! init and error
831 : PUBLIC :: mp_world_init, mp_world_finalize
832 : PUBLIC :: mp_abort
833 :
834 : ! informational / generation of sub comms
835 : PUBLIC :: mp_dims_create
836 : PUBLIC :: cp2k_is_parallel
837 :
838 : ! message passing
839 : PUBLIC :: mp_waitall, mp_waitany
840 : PUBLIC :: mp_testall, mp_testany
841 :
842 : ! Memory management
843 : PUBLIC :: mp_allocate, mp_deallocate
844 :
845 : ! I/O
846 : PUBLIC :: mp_file_delete
847 : PUBLIC :: mp_file_get_amode
848 :
849 : ! some 'advanced types' currently only used for dbcsr
850 : PUBLIC :: mp_type_descriptor_type
851 : PUBLIC :: mp_type_make
852 : PUBLIC :: mp_type_size
853 :
854 : ! vector types
855 : PUBLIC :: mp_type_indexed_make_r, mp_type_indexed_make_d, &
856 : mp_type_indexed_make_c, mp_type_indexed_make_z
857 :
858 : ! More I/O types and routines: variable spaced data using bytes for spacings
859 : PUBLIC :: mp_file_descriptor_type
860 : PUBLIC :: mp_file_type_free
861 : PUBLIC :: mp_file_type_hindexed_make_chv
862 : PUBLIC :: mp_file_type_set_view_chv
863 :
864 : PUBLIC :: mp_get_library_version
865 :
866 : ! assumed to be private
867 :
868 : INTERFACE mp_waitall
869 : MODULE PROCEDURE mp_waitall_1, mp_waitall_2
870 : END INTERFACE
871 :
872 : INTERFACE mp_testall
873 : MODULE PROCEDURE mp_testall_tv
874 : END INTERFACE
875 :
876 : INTERFACE mp_testany
877 : MODULE PROCEDURE mp_testany_1, mp_testany_2
878 : END INTERFACE
879 :
880 : INTERFACE mp_type_free
881 : MODULE PROCEDURE mp_type_free_m, mp_type_free_v
882 : END INTERFACE
883 :
884 : !
885 : ! interfaces to deal easily with scalars / vectors / matrices / ...
886 : ! of the different types (integers, doubles, logicals, characters)
887 : !
888 : INTERFACE mp_allocate
889 : MODULE PROCEDURE mp_allocate_i, &
890 : mp_allocate_l, &
891 : mp_allocate_r, &
892 : mp_allocate_d, &
893 : mp_allocate_c, &
894 : mp_allocate_z
895 : END INTERFACE
896 :
897 : INTERFACE mp_deallocate
898 : MODULE PROCEDURE mp_deallocate_i, &
899 : mp_deallocate_l, &
900 : mp_deallocate_r, &
901 : mp_deallocate_d, &
902 : mp_deallocate_c, &
903 : mp_deallocate_z
904 : END INTERFACE
905 :
906 : INTERFACE mp_type_make
907 : MODULE PROCEDURE mp_type_make_struct
908 : MODULE PROCEDURE mp_type_make_i, mp_type_make_l, &
909 : mp_type_make_r, mp_type_make_d, &
910 : mp_type_make_c, mp_type_make_z
911 : END INTERFACE
912 :
913 : INTERFACE mp_alloc_mem
914 : MODULE PROCEDURE mp_alloc_mem_i, mp_alloc_mem_l, &
915 : mp_alloc_mem_d, mp_alloc_mem_z, &
916 : mp_alloc_mem_r, mp_alloc_mem_c
917 : END INTERFACE
918 :
919 : INTERFACE mp_free_mem
920 : MODULE PROCEDURE mp_free_mem_i, mp_free_mem_l, &
921 : mp_free_mem_d, mp_free_mem_z, &
922 : mp_free_mem_r, mp_free_mem_c
923 : END INTERFACE
924 :
925 : ! Type declarations
926 : TYPE mp_indexing_meta_type
927 : INTEGER, DIMENSION(:), POINTER :: index => NULL(), chunks => NULL()
928 : END TYPE mp_indexing_meta_type
929 :
930 : TYPE mp_type_descriptor_type
931 : MPI_DATA_TYPE :: type_handle = mp_datatype_null_handle
932 : INTEGER :: length = -1
933 : #if defined(__parallel)
934 : INTEGER(kind=mpi_address_kind) :: base = -1
935 : #endif
936 : INTEGER(kind=int_4), DIMENSION(:), POINTER :: data_i => NULL()
937 : INTEGER(kind=int_8), DIMENSION(:), POINTER :: data_l => NULL()
938 : REAL(kind=real_4), DIMENSION(:), POINTER :: data_r => NULL()
939 : REAL(kind=real_8), DIMENSION(:), POINTER :: data_d => NULL()
940 : COMPLEX(kind=real_4), DIMENSION(:), POINTER :: data_c => NULL()
941 : COMPLEX(kind=real_8), DIMENSION(:), POINTER :: data_z => NULL()
942 : TYPE(mp_type_descriptor_type), DIMENSION(:), POINTER :: subtype => NULL()
943 : INTEGER :: vector_descriptor(2) = -1
944 : LOGICAL :: has_indexing = .FALSE.
945 : TYPE(mp_indexing_meta_type) :: index_descriptor = mp_indexing_meta_type()
946 : END TYPE mp_type_descriptor_type
947 :
948 : TYPE mp_file_indexing_meta_type
949 : INTEGER, DIMENSION(:), POINTER :: index => NULL()
950 : INTEGER(kind=file_offset), &
951 : DIMENSION(:), POINTER :: chunks => NULL()
952 : END TYPE mp_file_indexing_meta_type
953 :
954 : TYPE mp_file_descriptor_type
955 : MPI_DATA_TYPE :: type_handle = mp_datatype_null_handle
956 : INTEGER :: length = -1
957 : LOGICAL :: has_indexing = .FALSE.
958 : TYPE(mp_file_indexing_meta_type) :: index_descriptor = mp_file_indexing_meta_type()
959 : END TYPE
960 :
961 : ! we make some assumptions on the length of INTEGERS, REALS and LOGICALS
962 : INTEGER, PARAMETER :: intlen = BIT_SIZE(0)/8
963 : INTEGER, PARAMETER :: reallen = 8
964 : INTEGER, PARAMETER :: loglen = BIT_SIZE(0)/8
965 : INTEGER, PARAMETER :: charlen = 1
966 :
967 : LOGICAL, PUBLIC, SAVE :: mp_collect_timings = .FALSE.
968 :
969 : CONTAINS
970 :
971 : #:mute
972 : #:set types = ["comm", "request", "win", "file", "info"]
973 : #:endmute
974 : #:for type in types
975 3298215 : LOGICAL FUNCTION mp_${type}$_op_eq(${type}$1, ${type}$2)
976 : CLASS(mp_${type}$_type), INTENT(IN) :: ${type}$1, ${type}$2
977 : #if defined(__parallel) && defined(__MPI_F08)
978 3298215 : mp_${type}$_op_eq = (${type}$1%handle%mpi_val == ${type}$2%handle%mpi_val)
979 : #else
980 : mp_${type}$_op_eq = (${type}$1%handle == ${type}$2%handle)
981 : #endif
982 3298215 : END FUNCTION mp_${type}$_op_eq
983 :
984 3533810 : LOGICAL FUNCTION mp_${type}$_op_neq(${type}$1, ${type}$2)
985 : CLASS(mp_${type}$_type), INTENT(IN) :: ${type}$1, ${type}$2
986 : #if defined(__parallel) && defined(__MPI_F08)
987 3533810 : mp_${type}$_op_neq = (${type}$1%handle%mpi_val /= ${type}$2%handle%mpi_val)
988 : #else
989 : mp_${type}$_op_neq = (${type}$1%handle /= ${type}$2%handle)
990 : #endif
991 3533810 : END FUNCTION mp_${type}$_op_neq
992 :
993 8137498 : ELEMENTAL #{if type=="comm"}#IMPURE #{endif}#SUBROUTINE mp_${type}$_type_set_handle(this, handle #{if type=="comm"}#, ndims#{endif}#)
994 : CLASS(mp_${type}$_type), INTENT(INOUT) :: this
995 : INTEGER, INTENT(IN) :: handle
996 : #:if type=="comm"
997 : INTEGER, INTENT(IN), OPTIONAL :: ndims
998 : #:endif
999 :
1000 : #if defined(__parallel) && defined(__MPI_F08)
1001 8137498 : this%handle%mpi_val = handle
1002 : #else
1003 : this%handle = handle
1004 : #endif
1005 :
1006 : #:if type=="comm"
1007 : SELECT TYPE (this)
1008 : CLASS IS (mp_cart_type)
1009 0 : IF (.NOT. PRESENT(ndims)) &
1010 : CALL cp_abort(__LOCATION__, &
1011 0 : "Setup of a cartesian communicator requires information on the number of dimensions!")
1012 : END SELECT
1013 8133458 : IF (PRESENT(ndims)) this%ndims = ndims
1014 8133458 : CALL this%init()
1015 : #:endif
1016 :
1017 8137498 : END SUBROUTINE mp_${type}$_type_set_handle
1018 :
1019 3061645 : ELEMENTAL FUNCTION mp_${type}$_type_get_handle(this) RESULT(handle)
1020 : CLASS(mp_${type}$_type), INTENT(IN) :: this
1021 : INTEGER :: handle
1022 :
1023 : #if defined(__parallel) && defined(__MPI_F08)
1024 3061645 : handle = this%handle%mpi_val
1025 : #else
1026 : handle = this%handle
1027 : #endif
1028 3061645 : END FUNCTION mp_${type}$_type_get_handle
1029 : #:endfor
1030 :
1031 27908 : FUNCTION mp_comm_get_tag_ub(comm) RESULT(tag_ub)
1032 : CLASS(mp_comm_type), INTENT(IN) :: comm
1033 : INTEGER :: tag_ub
1034 :
1035 : #if defined(__parallel)
1036 : INTEGER :: ierr
1037 : LOGICAL :: flag
1038 : INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1039 :
1040 27908 : CALL MPI_COMM_GET_ATTR(comm%handle, MPI_TAG_UB, attrval, flag, ierr)
1041 27908 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_tag_ub")
1042 27908 : IF (.NOT. flag) THEN
1043 : CALL cp_warn(__LOCATION__, "Upper bound of tags not available! "// &
1044 0 : "Only the guaranteed minimum of 32767 is used.")
1045 0 : tag_ub = 32767
1046 : ELSE
1047 27908 : tag_ub = INT(attrval, KIND=KIND(tag_ub))
1048 : END IF
1049 : #else
1050 : MARK_USED(comm)
1051 : tag_ub = HUGE(1)
1052 : #endif
1053 27908 : END FUNCTION mp_comm_get_tag_ub
1054 :
1055 0 : FUNCTION mp_comm_get_host_rank(comm) RESULT(host_rank)
1056 : CLASS(mp_comm_type), INTENT(IN) :: comm
1057 : INTEGER :: host_rank
1058 :
1059 : #if defined(__parallel)
1060 : INTEGER :: ierr
1061 : LOGICAL :: flag
1062 : INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1063 :
1064 0 : CALL MPI_COMM_GET_ATTR(comm%handle, MPI_HOST, attrval, flag, ierr)
1065 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_host_rank")
1066 0 : IF (.NOT. flag) CPABORT("Host process rank not available!")
1067 0 : host_rank = INT(attrval, KIND=KIND(host_rank))
1068 : #else
1069 : MARK_USED(comm)
1070 : host_rank = 0
1071 : #endif
1072 0 : END FUNCTION mp_comm_get_host_rank
1073 :
1074 0 : FUNCTION mp_comm_get_io_rank(comm) RESULT(io_rank)
1075 : CLASS(mp_comm_type), INTENT(IN) :: comm
1076 : INTEGER :: io_rank
1077 :
1078 : #if defined(__parallel)
1079 : INTEGER :: ierr
1080 : LOGICAL :: flag
1081 : INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1082 :
1083 0 : CALL MPI_COMM_GET_ATTR(comm%handle, MPI_IO, attrval, flag, ierr)
1084 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_io_rank")
1085 0 : IF (.NOT. flag) CPABORT("IO rank not available!")
1086 0 : io_rank = INT(attrval, KIND=KIND(io_rank))
1087 : #else
1088 : MARK_USED(comm)
1089 : io_rank = 0
1090 : #endif
1091 0 : END FUNCTION mp_comm_get_io_rank
1092 :
1093 0 : FUNCTION mp_comm_get_wtime_is_global(comm) RESULT(wtime_is_global)
1094 : CLASS(mp_comm_type), INTENT(IN) :: comm
1095 : LOGICAL :: wtime_is_global
1096 :
1097 : #if defined(__parallel)
1098 : INTEGER :: ierr
1099 : LOGICAL :: flag
1100 : INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1101 :
1102 0 : CALL MPI_COMM_GET_ATTR(comm%handle, MPI_TAG_UB, attrval, flag, ierr)
1103 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_wtime_is_global")
1104 0 : IF (.NOT. flag) CPABORT("Synchronization state of WTIME not available!")
1105 0 : wtime_is_global = (attrval == 1_MPI_ADDRESS_KIND)
1106 : #else
1107 : MARK_USED(comm)
1108 : wtime_is_global = .TRUE.
1109 : #endif
1110 0 : END FUNCTION mp_comm_get_wtime_is_global
1111 :
1112 : ! **************************************************************************************************
1113 : !> \brief initializes the system default communicator
1114 : !> \param mp_comm [output] : handle of the default communicator
1115 : !> \par History
1116 : !> 2.2004 created [Joost VandeVondele ]
1117 : !> \note
1118 : !> should only be called once
1119 : ! **************************************************************************************************
1120 10630 : SUBROUTINE mp_world_init(mp_comm)
1121 : CLASS(mp_comm_type), INTENT(OUT) :: mp_comm
1122 : #if defined(__parallel)
1123 : INTEGER :: ierr, provided_tsl
1124 : #if defined(__MIMIC)
1125 : INTEGER :: mimic_handle
1126 : #endif
1127 :
1128 10630 : !$OMP MASTER
1129 : #if defined(__DLAF) || defined(__OPENPMD)
1130 : ! Both DLA-Future and (some IO backends of) the openPMD-api require
1131 : ! that the MPI library supports THREAD_MULTIPLE mode
1132 : CALL mpi_init_thread(MPI_THREAD_MULTIPLE, provided_tsl, ierr)
1133 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_init_thread @ mp_world_init")
1134 : IF (provided_tsl < MPI_THREAD_MULTIPLE) THEN
1135 : CALL mp_stop(0, "MPI library does not support the requested level of threading (MPI_THREAD_MULTIPLE),"// &
1136 : " required by DLA-Future/openPMD-api. Build CP2K without DLA-Future and openPMD-api.")
1137 : END IF
1138 : #else
1139 10630 : CALL mpi_init_thread(MPI_THREAD_SERIALIZED, provided_tsl, ierr)
1140 10630 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_init_thread @ mp_world_init")
1141 10630 : IF (provided_tsl < MPI_THREAD_SERIALIZED) THEN
1142 0 : CALL mp_stop(0, "MPI library does not support the requested level of threading (MPI_THREAD_SERIALIZED).")
1143 : END IF
1144 : #endif
1145 : !$OMP END MASTER
1146 10630 : CALL mpi_comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN, ierr)
1147 10630 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_set_errhandler @ mp_world_init")
1148 : #endif
1149 10630 : debug_comm_count = 1
1150 10630 : mp_comm = mp_comm_world
1151 : #if defined(__MIMIC)
1152 10630 : mimic_handle = mp_comm%get_handle()
1153 10630 : CALL mcl_initialize(mimic_handle)
1154 10630 : CALL mp_comm%set_handle(mimic_handle)
1155 : #if defined(__MPI_F08)
1156 10630 : mimic_comm_world%mpi_val = mimic_handle
1157 : #else
1158 : mimic_comm_world = mimic_handle
1159 : #endif
1160 : #endif
1161 10630 : CALL mp_comm%init()
1162 10630 : CALL add_mp_perf_env()
1163 10630 : END SUBROUTINE mp_world_init
1164 :
1165 : ! **************************************************************************************************
1166 : !> \brief re-create the system default communicator with a different MPI
1167 : !> rank order
1168 : !> \param mp_comm [output] : handle of the default communicator
1169 : !> \param mp_new_comm ...
1170 : !> \param ranks_order ...
1171 : !> \par History
1172 : !> 1.2012 created [ Christiane Pousa ]
1173 : !> \note
1174 : !> should only be called once, at very beginning of CP2K run
1175 : ! **************************************************************************************************
1176 764 : SUBROUTINE mp_reordering(mp_comm, mp_new_comm, ranks_order)
1177 : CLASS(mp_comm_type), INTENT(IN) :: mp_comm
1178 : CLASS(mp_comm_type), INTENT(out) :: mp_new_comm
1179 : INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: ranks_order
1180 :
1181 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_reordering'
1182 :
1183 : INTEGER :: handle, ierr
1184 : #if defined(__parallel)
1185 : MPI_GROUP_TYPE :: newgroup, oldgroup
1186 : #endif
1187 :
1188 764 : CALL mp_timeset(routineN, handle)
1189 : ierr = 0
1190 : #if defined(__parallel)
1191 :
1192 764 : CALL mpi_comm_group(mp_comm%handle, oldgroup, ierr)
1193 764 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_reordering")
1194 764 : CALL mpi_group_incl(oldgroup, SIZE(ranks_order), ranks_order, newgroup, ierr)
1195 764 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_incl @ mp_reordering")
1196 :
1197 764 : CALL mpi_comm_create(mp_comm%handle, newgroup, mp_new_comm%handle, ierr)
1198 764 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_create @ mp_reordering")
1199 :
1200 764 : CALL mpi_group_free(oldgroup, ierr)
1201 764 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_free @ mp_reordering")
1202 764 : CALL mpi_group_free(newgroup, ierr)
1203 764 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_free @ mp_reordering")
1204 :
1205 764 : CALL add_perf(perf_id=1, count=1)
1206 : #else
1207 : MARK_USED(mp_comm)
1208 : MARK_USED(ranks_order)
1209 : mp_new_comm%handle = mp_comm_default_handle
1210 : #endif
1211 764 : debug_comm_count = debug_comm_count + 1
1212 764 : CALL mp_new_comm%init()
1213 764 : CALL mp_timestop(handle)
1214 764 : END SUBROUTINE mp_reordering
1215 :
1216 : ! **************************************************************************************************
1217 : !> \brief finalizes the system default communicator
1218 : !> \par History
1219 : !> 2.2004 created [Joost VandeVondele]
1220 : ! **************************************************************************************************
1221 21260 : SUBROUTINE mp_world_finalize()
1222 :
1223 : CHARACTER(LEN=default_string_length) :: debug_comm_count_char
1224 : #if defined(__parallel)
1225 : INTEGER :: ierr
1226 : #if defined(__MIMIC)
1227 10630 : CALL mpi_barrier(mimic_comm_world, ierr)
1228 : #else
1229 : CALL mpi_barrier(MPI_COMM_WORLD, ierr) ! call mpi directly to avoid 0 stack pointer
1230 : #endif
1231 : #endif
1232 10630 : CALL rm_mp_perf_env()
1233 :
1234 10630 : debug_comm_count = debug_comm_count - 1
1235 : #if defined(__parallel)
1236 10630 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_barrier @ mp_world_finalize")
1237 : #endif
1238 10630 : IF (debug_comm_count /= 0) THEN
1239 : ! A bug, we're leaking or double-freeing communicators. Needs to be fixed where the leak happens.
1240 : ! Memory leak checking might be helpful to locate the culprit
1241 0 : WRITE (unit=debug_comm_count_char, FMT='(I2)') debug_comm_count
1242 : CALL cp_abort(__LOCATION__, "mp_world_finalize: assert failed:"// &
1243 0 : " leaking communicators "//ADJUSTL(TRIM(debug_comm_count_char)))
1244 : END IF
1245 : #if defined(__parallel)
1246 10630 : CALL mpi_finalize(ierr)
1247 10630 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_finalize @ mp_world_finalize")
1248 : #endif
1249 :
1250 10630 : END SUBROUTINE mp_world_finalize
1251 :
1252 : ! all the following routines should work for a given communicator, not MPI_WORLD
1253 :
1254 : ! **************************************************************************************************
1255 : !> \brief globally stops all tasks
1256 : !> this is intended to be low level, most of CP2K should call cp_abort()
1257 : ! **************************************************************************************************
1258 0 : SUBROUTINE mp_abort()
1259 : INTEGER :: ierr
1260 : #if defined(__MIMIC)
1261 : LOGICAL :: mcl_initialized
1262 : #endif
1263 :
1264 0 : ierr = 0
1265 :
1266 : #if !defined(__NO_ABORT)
1267 : #if defined(__parallel)
1268 : #if defined(__MIMIC)
1269 : CALL mcl_is_initialized(mcl_initialized)
1270 : IF (mcl_initialized) CALL mcl_abort(1, ierr)
1271 : #endif
1272 : CALL mpi_abort(MPI_COMM_WORLD, 1, ierr)
1273 : #else
1274 : CALL m_abort()
1275 : #endif
1276 : #endif
1277 : ! this routine never returns and levels with non-zero exit code
1278 0 : STOP 1
1279 : END SUBROUTINE mp_abort
1280 :
1281 : ! **************************************************************************************************
1282 : !> \brief stops *after an mpi error* translating the error code
1283 : !> \param ierr an error code * returned by an mpi call *
1284 : !> \param prg_code ...
1285 : !> \note
1286 : !> this function is private to message_passing.F
1287 : ! **************************************************************************************************
1288 0 : SUBROUTINE mp_stop(ierr, prg_code)
1289 : INTEGER, INTENT(IN) :: ierr
1290 : CHARACTER(LEN=*), INTENT(IN) :: prg_code
1291 :
1292 : #if defined(__parallel)
1293 : INTEGER :: istat, len
1294 : CHARACTER(LEN=MPI_MAX_ERROR_STRING) :: error_string
1295 : CHARACTER(LEN=MPI_MAX_ERROR_STRING + 512) :: full_error
1296 : #else
1297 : CHARACTER(LEN=512) :: full_error
1298 : #endif
1299 :
1300 : #if defined(__parallel)
1301 0 : CALL mpi_error_string(ierr, error_string, len, istat)
1302 0 : WRITE (full_error, '(A,I0,A)') ' MPI error ', ierr, ' in '//TRIM(prg_code)//' : '//error_string(1:len)
1303 : #else
1304 : WRITE (full_error, '(A,I0,A)') ' MPI error (!?) ', ierr, ' in '//TRIM(prg_code)
1305 : #endif
1306 :
1307 0 : CPABORT(full_error)
1308 :
1309 0 : END SUBROUTINE mp_stop
1310 :
1311 : ! **************************************************************************************************
1312 : !> \brief synchronizes with a barrier a given group of mpi tasks
1313 : !> \param group mpi communicator
1314 : ! **************************************************************************************************
1315 9110248 : SUBROUTINE mp_sync(comm)
1316 : CLASS(mp_comm_type), INTENT(IN) :: comm
1317 :
1318 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_sync'
1319 :
1320 : INTEGER :: handle, ierr
1321 :
1322 : ierr = 0
1323 4555124 : CALL mp_timeset(routineN, handle)
1324 :
1325 : #if defined(__parallel)
1326 4555124 : CALL mpi_barrier(comm%handle, ierr)
1327 4555124 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_barrier @ mp_sync")
1328 4555124 : CALL add_perf(perf_id=5, count=1)
1329 : #else
1330 : MARK_USED(comm)
1331 : #endif
1332 4555124 : CALL mp_timestop(handle)
1333 :
1334 4555124 : END SUBROUTINE mp_sync
1335 :
1336 : ! **************************************************************************************************
1337 : !> \brief synchronizes with a barrier a given group of mpi tasks
1338 : !> \param comm mpi communicator
1339 : !> \param request ...
1340 : ! **************************************************************************************************
1341 0 : SUBROUTINE mp_isync(comm, request)
1342 : CLASS(mp_comm_type), INTENT(IN) :: comm
1343 : TYPE(mp_request_type), INTENT(OUT) :: request
1344 :
1345 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_isync'
1346 :
1347 : INTEGER :: handle, ierr
1348 :
1349 : ierr = 0
1350 0 : CALL mp_timeset(routineN, handle)
1351 :
1352 : #if defined(__parallel)
1353 0 : CALL mpi_ibarrier(comm%handle, request%handle, ierr)
1354 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibarrier @ mp_isync")
1355 0 : CALL add_perf(perf_id=26, count=1)
1356 : #else
1357 : MARK_USED(comm)
1358 : request = mp_request_null
1359 : #endif
1360 0 : CALL mp_timestop(handle)
1361 :
1362 0 : END SUBROUTINE mp_isync
1363 :
1364 : ! **************************************************************************************************
1365 : !> \brief returns task id for a given mpi communicator
1366 : !> \param taskid The ID of the communicator
1367 : !> \param comm mpi communicator
1368 : ! **************************************************************************************************
1369 49590172 : SUBROUTINE mp_comm_rank(taskid, comm)
1370 :
1371 : INTEGER, INTENT(OUT) :: taskid
1372 : CLASS(mp_comm_type), INTENT(IN) :: comm
1373 :
1374 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_rank'
1375 :
1376 : INTEGER :: handle
1377 : #if defined(__parallel)
1378 : INTEGER :: ierr
1379 : #endif
1380 :
1381 24795086 : CALL mp_timeset(routineN, handle)
1382 :
1383 : #if defined(__parallel)
1384 24795086 : CALL mpi_comm_rank(comm%handle, taskid, ierr)
1385 24795086 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ mp_comm_rank")
1386 : #else
1387 : MARK_USED(comm)
1388 : taskid = 0
1389 : #endif
1390 24795086 : CALL mp_timestop(handle)
1391 :
1392 24795086 : END SUBROUTINE mp_comm_rank
1393 :
1394 : ! **************************************************************************************************
1395 : !> \brief returns number of tasks for a given mpi communicator
1396 : !> \param numtask ...
1397 : !> \param comm mpi communicator
1398 : ! **************************************************************************************************
1399 49590172 : SUBROUTINE mp_comm_size(numtask, comm)
1400 :
1401 : INTEGER, INTENT(OUT) :: numtask
1402 : CLASS(mp_comm_type), INTENT(IN) :: comm
1403 :
1404 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_size'
1405 :
1406 : INTEGER :: handle
1407 : #if defined(__parallel)
1408 : INTEGER :: ierr
1409 : #endif
1410 :
1411 24795086 : CALL mp_timeset(routineN, handle)
1412 :
1413 : #if defined(__parallel)
1414 24795086 : CALL mpi_comm_size(comm%handle, numtask, ierr)
1415 24795086 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ mp_comm_size")
1416 : #else
1417 : MARK_USED(comm)
1418 : numtask = 1
1419 : #endif
1420 24795086 : CALL mp_timestop(handle)
1421 :
1422 24795086 : END SUBROUTINE mp_comm_size
1423 :
1424 : ! **************************************************************************************************
1425 : !> \brief returns info for a given Cartesian MPI communicator
1426 : !> \param comm ...
1427 : !> \param ndims ...
1428 : !> \param dims ...
1429 : !> \param task_coor ...
1430 : !> \param periods ...
1431 : ! **************************************************************************************************
1432 12185494 : SUBROUTINE mp_cart_get(comm, dims, task_coor, periods)
1433 :
1434 : CLASS(mp_cart_type), INTENT(IN) :: comm
1435 : INTEGER, INTENT(OUT), OPTIONAL :: dims(comm%ndims), task_coor(comm%ndims)
1436 : LOGICAL, INTENT(out), OPTIONAL :: periods(comm%ndims)
1437 :
1438 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_cart_get'
1439 :
1440 : INTEGER :: handle
1441 : #if defined(__parallel)
1442 : INTEGER :: ierr
1443 24370988 : INTEGER :: my_dims(comm%ndims), my_task_coor(comm%ndims)
1444 24370988 : LOGICAL :: my_periods(comm%ndims)
1445 : #endif
1446 :
1447 12185494 : CALL mp_timeset(routineN, handle)
1448 :
1449 : #if defined(__parallel)
1450 12185494 : CALL mpi_cart_get(comm%handle, comm%ndims, my_dims, my_periods, my_task_coor, ierr)
1451 12185494 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_get @ mp_cart_get")
1452 48742884 : IF (PRESENT(dims)) dims = my_dims
1453 48742884 : IF (PRESENT(task_coor)) task_coor = my_task_coor
1454 48742884 : IF (PRESENT(periods)) periods = my_periods
1455 : #else
1456 : MARK_USED(comm)
1457 : IF (PRESENT(task_coor)) task_coor = 0
1458 : IF (PRESENT(dims)) dims = 1
1459 : IF (PRESENT(periods)) periods = .FALSE.
1460 : #endif
1461 12185494 : CALL mp_timestop(handle)
1462 :
1463 12185494 : END SUBROUTINE mp_cart_get
1464 :
1465 0 : INTEGER ELEMENTAL FUNCTION mp_comm_get_ndims(comm)
1466 : CLASS(mp_comm_type), INTENT(IN) :: comm
1467 :
1468 0 : mp_comm_get_ndims = comm%ndims
1469 :
1470 0 : END FUNCTION
1471 :
1472 : ! **************************************************************************************************
1473 : !> \brief creates a cartesian communicator from any communicator
1474 : !> \param comm_old ...
1475 : !> \param ndims ...
1476 : !> \param dims ...
1477 : !> \param pos ...
1478 : !> \param comm_cart ...
1479 : ! **************************************************************************************************
1480 2431294 : SUBROUTINE mp_cart_create(comm_old, ndims, dims, comm_cart)
1481 :
1482 : CLASS(mp_comm_type), INTENT(IN) :: comm_old
1483 : INTEGER, INTENT(IN) :: ndims
1484 : INTEGER, INTENT(INOUT) :: dims(ndims)
1485 : CLASS(mp_cart_type), INTENT(OUT) :: comm_cart
1486 :
1487 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_cart_create'
1488 :
1489 : INTEGER :: handle, ierr
1490 : #if defined(__parallel)
1491 2431294 : LOGICAL, DIMENSION(1:ndims) :: period
1492 : LOGICAL :: reorder
1493 : #endif
1494 :
1495 2431294 : ierr = 0
1496 2431294 : CALL mp_timeset(routineN, handle)
1497 :
1498 2431294 : comm_cart%handle = comm_old%handle
1499 : #if defined(__parallel)
1500 :
1501 6597438 : IF (ANY(dims == 0)) CALL mpi_dims_create(comm_old%num_pe, ndims, dims, ierr)
1502 2431294 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_dims_create @ mp_cart_create")
1503 :
1504 : ! FIX ME. Quick hack to avoid problems with realspace grids for compilers
1505 : ! like IBM that actually reorder the processors when creating the new
1506 : ! communicator
1507 2431294 : reorder = .FALSE.
1508 7294790 : period = .TRUE.
1509 : CALL mpi_cart_create(comm_old%handle, ndims, dims, period, reorder, comm_cart%handle, &
1510 2431294 : ierr)
1511 2431294 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_create @ mp_cart_create")
1512 2431294 : CALL add_perf(perf_id=1, count=1)
1513 : #else
1514 : dims = 1
1515 : comm_cart%handle = mp_comm_default_handle
1516 : #endif
1517 2431294 : comm_cart%ndims = ndims
1518 2431294 : debug_comm_count = debug_comm_count + 1
1519 2431294 : CALL comm_cart%init()
1520 2431294 : CALL mp_timestop(handle)
1521 :
1522 2431294 : END SUBROUTINE mp_cart_create
1523 :
1524 : ! **************************************************************************************************
1525 : !> \brief wrapper to MPI_Cart_coords
1526 : !> \param comm ...
1527 : !> \param rank ...
1528 : !> \param coords ...
1529 : ! **************************************************************************************************
1530 74856 : SUBROUTINE mp_cart_coords(comm, rank, coords)
1531 :
1532 : CLASS(mp_cart_type), INTENT(IN) :: comm
1533 : INTEGER, INTENT(IN) :: rank
1534 : INTEGER, DIMENSION(:), INTENT(OUT) :: coords
1535 :
1536 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_cart_coords'
1537 :
1538 : INTEGER :: handle, ierr, m
1539 :
1540 : ierr = 0
1541 74856 : CALL mp_timeset(routineN, handle)
1542 :
1543 74856 : m = SIZE(coords)
1544 : #if defined(__parallel)
1545 74856 : CALL mpi_cart_coords(comm%handle, rank, m, coords, ierr)
1546 74856 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_coords @ mp_cart_coords")
1547 : #else
1548 : coords = 0
1549 : MARK_USED(rank)
1550 : MARK_USED(comm)
1551 : #endif
1552 74856 : CALL mp_timestop(handle)
1553 :
1554 74856 : END SUBROUTINE mp_cart_coords
1555 :
1556 : ! **************************************************************************************************
1557 : !> \brief wrapper to MPI_Comm_compare
1558 : !> \param comm1 ...
1559 : !> \param comm2 ...
1560 : !> \param res ...
1561 : ! **************************************************************************************************
1562 4616 : FUNCTION mp_comm_compare(comm1, comm2) RESULT(res)
1563 :
1564 : CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
1565 : INTEGER :: res
1566 :
1567 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_compare'
1568 :
1569 : INTEGER :: handle
1570 : #if defined(__parallel)
1571 : INTEGER :: ierr, iout
1572 : #endif
1573 :
1574 2308 : CALL mp_timeset(routineN, handle)
1575 :
1576 2308 : res = 0
1577 : #if defined(__parallel)
1578 2308 : CALL mpi_comm_compare(comm1%handle, comm2%handle, iout, ierr)
1579 2308 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_compare @ mp_comm_compare")
1580 : SELECT CASE (iout)
1581 : CASE (MPI_IDENT)
1582 2308 : res = mp_comm_ident
1583 : CASE (MPI_CONGRUENT)
1584 2308 : res = mp_comm_congruent
1585 : CASE (MPI_SIMILAR)
1586 0 : res = mp_comm_similar
1587 : CASE (MPI_UNEQUAL)
1588 0 : res = mp_comm_unequal
1589 : CASE default
1590 2308 : CPABORT("Unknown comparison state of the communicators!")
1591 : END SELECT
1592 : #else
1593 : MARK_USED(comm1)
1594 : MARK_USED(comm2)
1595 : #endif
1596 2308 : CALL mp_timestop(handle)
1597 :
1598 2308 : END FUNCTION mp_comm_compare
1599 :
1600 : ! **************************************************************************************************
1601 : !> \brief wrapper to MPI_Cart_sub
1602 : !> \param comm ...
1603 : !> \param rdim ...
1604 : !> \param sub_comm ...
1605 : ! **************************************************************************************************
1606 1816 : SUBROUTINE mp_cart_sub(comm, rdim, sub_comm)
1607 :
1608 : CLASS(mp_cart_type), INTENT(IN) :: comm
1609 : LOGICAL, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: rdim
1610 : CLASS(mp_cart_type), INTENT(OUT) :: sub_comm
1611 :
1612 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_cart_sub'
1613 :
1614 : INTEGER :: handle
1615 : #if defined(__parallel)
1616 : INTEGER :: ierr
1617 : #endif
1618 :
1619 1816 : CALL mp_timeset(routineN, handle)
1620 :
1621 : #if defined(__parallel)
1622 1816 : CALL mpi_cart_sub(comm%handle, rdim, sub_comm%handle, ierr)
1623 1816 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_sub @ mp_cart_sub")
1624 : #else
1625 : MARK_USED(comm)
1626 : MARK_USED(rdim)
1627 : sub_comm%handle = mp_comm_default_handle
1628 : #endif
1629 7264 : sub_comm%ndims = COUNT(rdim)
1630 1816 : debug_comm_count = debug_comm_count + 1
1631 1816 : CALL sub_comm%init()
1632 1816 : CALL mp_timestop(handle)
1633 :
1634 1816 : END SUBROUTINE mp_cart_sub
1635 :
1636 : ! **************************************************************************************************
1637 : !> \brief wrapper to MPI_Comm_free
1638 : !> \param comm ...
1639 : ! **************************************************************************************************
1640 5884726 : SUBROUTINE mp_comm_free(comm)
1641 :
1642 : CLASS(mp_comm_type), INTENT(INOUT) :: comm
1643 :
1644 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_free'
1645 :
1646 : INTEGER :: handle
1647 : LOGICAL :: free_comm
1648 : #if defined(__parallel)
1649 : INTEGER :: ierr
1650 : #endif
1651 :
1652 5884726 : free_comm = .TRUE.
1653 : SELECT TYPE (comm)
1654 : CLASS IS (mp_para_env_type)
1655 1365632 : free_comm = .FALSE.
1656 1365632 : IF (comm%ref_count <= 0) &
1657 0 : CPABORT("para_env%ref_count <= 0")
1658 1365632 : comm%ref_count = comm%ref_count - 1
1659 1365632 : IF (comm%ref_count <= 0) THEN
1660 315197 : free_comm = comm%owns_group
1661 : END IF
1662 : CLASS IS (mp_para_cart_type)
1663 148 : free_comm = .FALSE.
1664 148 : IF (comm%ref_count <= 0) &
1665 0 : CPABORT("para_cart%ref_count <= 0")
1666 148 : comm%ref_count = comm%ref_count - 1
1667 148 : IF (comm%ref_count <= 0) THEN
1668 148 : free_comm = comm%owns_group
1669 : END IF
1670 : END SELECT
1671 :
1672 5884726 : CALL mp_timeset(routineN, handle)
1673 :
1674 5884726 : IF (free_comm) THEN
1675 : #if defined(__parallel)
1676 4799942 : CALL mpi_comm_free(comm%handle, ierr)
1677 4799942 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_free @ mp_comm_free")
1678 : #else
1679 : comm%handle = mp_comm_null_handle
1680 : #endif
1681 4799942 : debug_comm_count = debug_comm_count - 1
1682 : END IF
1683 :
1684 : SELECT TYPE (comm)
1685 : CLASS IS (mp_cart_type)
1686 3342307 : DEALLOCATE (comm%periodic, comm%mepos_cart, comm%num_pe_cart)
1687 : END SELECT
1688 :
1689 5884726 : CALL mp_timestop(handle)
1690 :
1691 5884726 : END SUBROUTINE mp_comm_free
1692 :
1693 : ! **************************************************************************************************
1694 : !> \brief check whether the environment exists
1695 : !> \param para_env ...
1696 : !> \return ...
1697 : ! **************************************************************************************************
1698 1116775 : ELEMENTAL LOGICAL FUNCTION mp_para_env_is_valid(para_env)
1699 : CLASS(mp_para_env_type), INTENT(IN) :: para_env
1700 :
1701 1116775 : mp_para_env_is_valid = para_env%ref_count > 0
1702 :
1703 1116775 : END FUNCTION mp_para_env_is_valid
1704 :
1705 : ! **************************************************************************************************
1706 : !> \brief increase the reference counter but ensure that you free it later
1707 : !> \param para_env ...
1708 : ! **************************************************************************************************
1709 1050443 : ELEMENTAL SUBROUTINE mp_para_env_retain(para_env)
1710 : CLASS(mp_para_env_type), INTENT(INOUT) :: para_env
1711 :
1712 1050443 : para_env%ref_count = para_env%ref_count + 1
1713 :
1714 1050443 : END SUBROUTINE mp_para_env_retain
1715 :
1716 : ! **************************************************************************************************
1717 : !> \brief check whether the given environment is valid, i.e. existent
1718 : !> \param cart ...
1719 : !> \return ...
1720 : ! **************************************************************************************************
1721 148 : ELEMENTAL LOGICAL FUNCTION mp_para_cart_is_valid(cart)
1722 : CLASS(mp_para_cart_type), INTENT(IN) :: cart
1723 :
1724 148 : mp_para_cart_is_valid = cart%ref_count > 0
1725 :
1726 148 : END FUNCTION mp_para_cart_is_valid
1727 :
1728 : ! **************************************************************************************************
1729 : !> \brief increase the reference counter, don't forget to free it later
1730 : !> \param cart ...
1731 : ! **************************************************************************************************
1732 0 : ELEMENTAL SUBROUTINE mp_para_cart_retain(cart)
1733 : CLASS(mp_para_cart_type), INTENT(INOUT) :: cart
1734 :
1735 0 : cart%ref_count = cart%ref_count + 1
1736 :
1737 0 : END SUBROUTINE mp_para_cart_retain
1738 :
1739 : ! **************************************************************************************************
1740 : !> \brief wrapper to MPI_Comm_dup
1741 : !> \param comm1 ...
1742 : !> \param comm2 ...
1743 : ! **************************************************************************************************
1744 947755 : SUBROUTINE mp_comm_dup(comm1, comm2)
1745 :
1746 : CLASS(mp_comm_type), INTENT(IN) :: comm1
1747 : CLASS(mp_comm_type), INTENT(OUT) :: comm2
1748 :
1749 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_dup'
1750 :
1751 : INTEGER :: handle
1752 : #if defined(__parallel)
1753 : INTEGER :: ierr
1754 : #endif
1755 :
1756 947755 : CALL mp_timeset(routineN, handle)
1757 :
1758 : #if defined(__parallel)
1759 947755 : CALL mpi_comm_dup(comm1%handle, comm2%handle, ierr)
1760 947755 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_dup @ mp_comm_dup")
1761 : #else
1762 : MARK_USED(comm1)
1763 : comm2%handle = mp_comm_default_handle
1764 : #endif
1765 947755 : comm2%ndims = comm1%ndims
1766 947755 : debug_comm_count = debug_comm_count + 1
1767 947755 : CALL comm2%init()
1768 947755 : CALL mp_timestop(handle)
1769 :
1770 947755 : END SUBROUTINE mp_comm_dup
1771 :
1772 : ! **************************************************************************************************
1773 : !> \brief Implements a simple assignment function to overload the assignment operator
1774 : !> \param comm_new communicator on the r.h.s. of the assignment operator
1775 : !> \param comm_old communicator on the l.h.s. of the assignment operator
1776 : ! **************************************************************************************************
1777 11758527 : ELEMENTAL IMPURE SUBROUTINE mp_comm_assign(comm_new, comm_old)
1778 : CLASS(mp_comm_type), INTENT(IN) :: comm_old
1779 : CLASS(mp_comm_type), INTENT(OUT) :: comm_new
1780 :
1781 11758527 : comm_new%handle = comm_old%handle
1782 11758527 : comm_new%ndims = comm_old%ndims
1783 11758527 : CALL comm_new%init(.FALSE.)
1784 11758527 : END SUBROUTINE
1785 :
1786 : ! **************************************************************************************************
1787 : !> \brief check whether the local process is the source process
1788 : !> \param para_env ...
1789 : !> \return ...
1790 : ! **************************************************************************************************
1791 17018369 : ELEMENTAL LOGICAL FUNCTION mp_comm_is_source(comm)
1792 : CLASS(mp_comm_type), INTENT(IN) :: comm
1793 :
1794 17018369 : mp_comm_is_source = comm%source == comm%mepos
1795 :
1796 17018369 : END FUNCTION mp_comm_is_source
1797 :
1798 : ! **************************************************************************************************
1799 : !> \brief Initializes the communicator (mostly relevant for its derived classes)
1800 : !> \param comm ...
1801 : ! **************************************************************************************************
1802 24702557 : ELEMENTAL IMPURE SUBROUTINE mp_comm_init(comm, owns_group)
1803 : CLASS(mp_comm_type), INTENT(INOUT) :: comm
1804 : LOGICAL, INTENT(IN), OPTIONAL :: owns_group
1805 :
1806 24702557 : IF (comm%handle MPI_GET_COMP /= mp_comm_null_handle MPI_GET_COMP) THEN
1807 24523405 : comm%source = 0
1808 24523405 : CALL comm%get_size(comm%num_pe)
1809 24523405 : CALL comm%get_rank(comm%mepos)
1810 : END IF
1811 :
1812 : SELECT TYPE (comm)
1813 : CLASS IS (mp_cart_type)
1814 12185494 : IF (ALLOCATED(comm%periodic)) DEALLOCATE (comm%periodic)
1815 12185494 : IF (ALLOCATED(comm%mepos_cart)) DEALLOCATE (comm%mepos_cart)
1816 12185494 : IF (ALLOCATED(comm%num_pe_cart)) DEALLOCATE (comm%num_pe_cart)
1817 :
1818 : ASSOCIATE (ndims => comm%ndims)
1819 :
1820 0 : ALLOCATE (comm%periodic(ndims), comm%mepos_cart(ndims), &
1821 60927470 : comm%num_pe_cart(ndims))
1822 : END ASSOCIATE
1823 :
1824 36557390 : comm%mepos_cart = 0
1825 36557390 : comm%periodic = .FALSE.
1826 12185494 : IF (comm%handle MPI_GET_COMP /= mp_comm_null_handle MPI_GET_COMP) THEN
1827 : CALL comm%get_info_cart(comm%num_pe_cart, comm%mepos_cart, &
1828 12185494 : comm%periodic)
1829 : END IF
1830 : END SELECT
1831 :
1832 : SELECT TYPE (comm)
1833 : CLASS IS (mp_para_env_type)
1834 336453 : IF (PRESENT(owns_group)) comm%owns_group = owns_group
1835 336453 : comm%ref_count = 1
1836 : CLASS IS (mp_para_cart_type)
1837 148 : IF (PRESENT(owns_group)) comm%owns_group = owns_group
1838 148 : comm%ref_count = 1
1839 : END SELECT
1840 :
1841 24702557 : END SUBROUTINE
1842 :
1843 : ! **************************************************************************************************
1844 : !> \brief creates a new para environment
1845 : !> \param para_env the new parallel environment
1846 : !> \param group the id of the actual mpi_group
1847 : !> \par History
1848 : !> 08.2002 created [fawzi]
1849 : !> \author Fawzi Mohamed
1850 : ! **************************************************************************************************
1851 0 : SUBROUTINE mp_para_env_create(para_env, group)
1852 : TYPE(mp_para_env_type), POINTER :: para_env
1853 : CLASS(mp_comm_type), INTENT(in) :: group
1854 :
1855 0 : IF (ASSOCIATED(para_env)) &
1856 0 : CPABORT("The passed para_env must not be associated!")
1857 0 : ALLOCATE (para_env)
1858 0 : para_env%mp_comm_type = group
1859 0 : CALL para_env%init()
1860 0 : END SUBROUTINE mp_para_env_create
1861 :
1862 : ! **************************************************************************************************
1863 : !> \brief releases the para object (to be called when you don't want anymore
1864 : !> the shared copy of this object)
1865 : !> \param para_env the new group
1866 : !> \par History
1867 : !> 08.2002 created [fawzi]
1868 : !> \author Fawzi Mohamed
1869 : !> \note
1870 : !> to avoid circular dependencies cp_log_handling has a private copy
1871 : !> of this method (see cp_log_handling:my_mp_para_env_release)!
1872 : ! **************************************************************************************************
1873 1129416 : SUBROUTINE mp_para_env_release(para_env)
1874 : TYPE(mp_para_env_type), POINTER :: para_env
1875 :
1876 1129416 : IF (ASSOCIATED(para_env)) THEN
1877 1093712 : CALL para_env%free()
1878 1093712 : IF (.NOT. para_env%is_valid()) DEALLOCATE (para_env)
1879 : END IF
1880 1129416 : NULLIFY (para_env)
1881 1129416 : END SUBROUTINE mp_para_env_release
1882 :
1883 : ! **************************************************************************************************
1884 : !> \brief creates a cart (multidimensional parallel environment)
1885 : !> \param cart the cart environment to create
1886 : !> \param group the mpi communicator
1887 : !> \author fawzi
1888 : ! **************************************************************************************************
1889 0 : SUBROUTINE mp_para_cart_create(cart, group)
1890 : TYPE(mp_para_cart_type), POINTER, INTENT(OUT) :: cart
1891 : CLASS(mp_comm_type), INTENT(in) :: group
1892 :
1893 0 : IF (ASSOCIATED(cart)) &
1894 0 : CPABORT("The passed para_cart must not be associated!")
1895 0 : ALLOCATE (cart)
1896 0 : cart%mp_cart_type = group
1897 0 : CALL cart%init()
1898 :
1899 0 : END SUBROUTINE mp_para_cart_create
1900 :
1901 : ! **************************************************************************************************
1902 : !> \brief releases the given cart
1903 : !> \param cart the cart to release
1904 : !> \author fawzi
1905 : ! **************************************************************************************************
1906 148 : SUBROUTINE mp_para_cart_release(cart)
1907 : TYPE(mp_para_cart_type), POINTER :: cart
1908 :
1909 148 : IF (ASSOCIATED(cart)) THEN
1910 148 : CALL cart%free()
1911 148 : IF (.NOT. cart%is_valid()) DEALLOCATE (cart)
1912 : END IF
1913 148 : NULLIFY (cart)
1914 148 : END SUBROUTINE mp_para_cart_release
1915 :
1916 : ! **************************************************************************************************
1917 : !> \brief wrapper to MPI_Group_translate_ranks
1918 : !> \param comm1 ...
1919 : !> \param comm2 ...
1920 : !> \param rank ...
1921 : ! **************************************************************************************************
1922 3331446 : SUBROUTINE mp_rank_compare(comm1, comm2, rank)
1923 :
1924 : CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
1925 : INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rank
1926 :
1927 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_rank_compare'
1928 :
1929 : INTEGER :: handle
1930 : #if defined(__parallel)
1931 : INTEGER :: i, ierr, n, n1, n2
1932 3331446 : INTEGER, ALLOCATABLE, DIMENSION(:) :: rin
1933 : MPI_GROUP_TYPE :: g1, g2
1934 : #endif
1935 :
1936 3331446 : CALL mp_timeset(routineN, handle)
1937 :
1938 9994338 : rank = 0
1939 : #if defined(__parallel)
1940 3331446 : CALL mpi_comm_size(comm1%handle, n1, ierr)
1941 3331446 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ mp_rank_compare")
1942 3331446 : CALL mpi_comm_size(comm2%handle, n2, ierr)
1943 3331446 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ mp_rank_compare")
1944 3331446 : n = MAX(n1, n2)
1945 3331446 : CALL mpi_comm_group(comm1%handle, g1, ierr)
1946 3331446 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_rank_compare")
1947 3331446 : CALL mpi_comm_group(comm2%handle, g2, ierr)
1948 3331446 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_rank_compare")
1949 9994338 : ALLOCATE (rin(0:n - 1), STAT=ierr)
1950 3331446 : IF (ierr /= 0) &
1951 0 : CPABORT("allocate @ mp_rank_compare")
1952 9994338 : DO i = 0, n - 1
1953 9994338 : rin(i) = i
1954 : END DO
1955 3331446 : CALL mpi_group_translate_ranks(g1, n, rin, g2, rank, ierr)
1956 3331446 : IF (ierr /= 0) CALL mp_stop(ierr, &
1957 0 : "mpi_group_translate_rank @ mp_rank_compare")
1958 3331446 : CALL mpi_group_free(g1, ierr)
1959 3331446 : IF (ierr /= 0) &
1960 0 : CPABORT("group_free @ mp_rank_compare")
1961 3331446 : CALL mpi_group_free(g2, ierr)
1962 3331446 : IF (ierr /= 0) &
1963 0 : CPABORT("group_free @ mp_rank_compare")
1964 3331446 : DEALLOCATE (rin)
1965 : #else
1966 : MARK_USED(comm1)
1967 : MARK_USED(comm2)
1968 : #endif
1969 3331446 : CALL mp_timestop(handle)
1970 :
1971 23320122 : END SUBROUTINE mp_rank_compare
1972 :
1973 : ! **************************************************************************************************
1974 : !> \brief wrapper to MPI_Dims_create
1975 : !> \param nodes ...
1976 : !> \param dims ...
1977 : ! **************************************************************************************************
1978 1194800 : SUBROUTINE mp_dims_create(nodes, dims)
1979 :
1980 : INTEGER, INTENT(IN) :: nodes
1981 : INTEGER, DIMENSION(:), INTENT(INOUT) :: dims
1982 :
1983 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_dims_create'
1984 :
1985 : INTEGER :: handle, ndim
1986 : #if defined(__parallel)
1987 : INTEGER :: ierr
1988 : #endif
1989 :
1990 1194800 : CALL mp_timeset(routineN, handle)
1991 :
1992 1194800 : ndim = SIZE(dims)
1993 : #if defined(__parallel)
1994 1194800 : IF (ANY(dims == 0)) CALL mpi_dims_create(nodes, ndim, dims, ierr)
1995 1194800 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_dims_create @ mp_dims_create")
1996 : #else
1997 : dims = 1
1998 : MARK_USED(nodes)
1999 : #endif
2000 1194800 : CALL mp_timestop(handle)
2001 :
2002 1194800 : END SUBROUTINE mp_dims_create
2003 :
2004 : ! **************************************************************************************************
2005 : !> \brief wrapper to MPI_Cart_rank
2006 : !> \param comm ...
2007 : !> \param pos ...
2008 : !> \param rank ...
2009 : ! **************************************************************************************************
2010 11308586 : SUBROUTINE mp_cart_rank(comm, pos, rank)
2011 : CLASS(mp_cart_type), INTENT(IN) :: comm
2012 : INTEGER, DIMENSION(:), INTENT(IN) :: pos
2013 : INTEGER, INTENT(OUT) :: rank
2014 :
2015 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_cart_rank'
2016 :
2017 : INTEGER :: handle
2018 : #if defined(__parallel)
2019 : INTEGER :: ierr
2020 : #endif
2021 :
2022 11308586 : CALL mp_timeset(routineN, handle)
2023 :
2024 : #if defined(__parallel)
2025 11308586 : CALL mpi_cart_rank(comm%handle, pos, rank, ierr)
2026 11308586 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_rank @ mp_cart_rank")
2027 : #else
2028 : rank = 0
2029 : MARK_USED(comm)
2030 : MARK_USED(pos)
2031 : #endif
2032 11308586 : CALL mp_timestop(handle)
2033 :
2034 11308586 : END SUBROUTINE mp_cart_rank
2035 :
2036 : ! **************************************************************************************************
2037 : !> \brief waits for completion of the given request
2038 : !> \param request ...
2039 : !> \par History
2040 : !> 08.2003 created [f&j]
2041 : !> \author joost & fawzi
2042 : !> \note
2043 : !> see isendrecv
2044 : ! **************************************************************************************************
2045 17996 : SUBROUTINE mp_wait(request)
2046 : CLASS(mp_request_type), INTENT(inout) :: request
2047 :
2048 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_wait'
2049 :
2050 : INTEGER :: handle
2051 : #if defined(__parallel)
2052 : INTEGER :: ierr
2053 : #endif
2054 :
2055 8998 : CALL mp_timeset(routineN, handle)
2056 :
2057 : #if defined(__parallel)
2058 :
2059 8998 : CALL mpi_wait(request%handle, MPI_STATUS_IGNORE, ierr)
2060 8998 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_wait @ mp_wait")
2061 :
2062 8998 : CALL add_perf(perf_id=9, count=1)
2063 : #else
2064 : request%handle = mp_request_null_handle
2065 : #endif
2066 8998 : CALL mp_timestop(handle)
2067 8998 : END SUBROUTINE mp_wait
2068 :
2069 : ! **************************************************************************************************
2070 : !> \brief waits for completion of the given requests
2071 : !> \param requests ...
2072 : !> \par History
2073 : !> 08.2003 created [f&j]
2074 : !> \author joost & fawzi
2075 : !> \note
2076 : !> see isendrecv
2077 : ! **************************************************************************************************
2078 4117051 : SUBROUTINE mp_waitall_1(requests)
2079 : TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2080 :
2081 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_waitall_1'
2082 :
2083 : INTEGER :: handle
2084 : #if defined(__parallel)
2085 : INTEGER :: count, ierr
2086 : #endif
2087 :
2088 4117051 : CALL mp_timeset(routineN, handle)
2089 : #if defined(__parallel)
2090 4117051 : count = SIZE(requests)
2091 4117051 : CALL mpi_waitall_internal(count, requests, ierr)
2092 4117051 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitall @ mp_waitall_1")
2093 4117051 : CALL add_perf(perf_id=9, count=1)
2094 : #else
2095 : requests = mp_request_null
2096 : #endif
2097 4117051 : CALL mp_timestop(handle)
2098 4117051 : END SUBROUTINE mp_waitall_1
2099 :
2100 : ! **************************************************************************************************
2101 : !> \brief waits for completion of the given requests
2102 : !> \param requests ...
2103 : !> \par History
2104 : !> 08.2003 created [f&j]
2105 : !> \author joost & fawzi
2106 : ! **************************************************************************************************
2107 1022792 : SUBROUTINE mp_waitall_2(requests)
2108 : TYPE(mp_request_type), DIMENSION(:, :), INTENT(inout) :: requests
2109 :
2110 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_waitall_2'
2111 :
2112 : INTEGER :: handle
2113 : #if defined(__parallel)
2114 : INTEGER :: count, ierr
2115 : #endif
2116 :
2117 1022792 : CALL mp_timeset(routineN, handle)
2118 : #if defined(__parallel)
2119 3068376 : count = SIZE(requests)
2120 5880563 : CALL mpi_waitall_internal(count, requests, ierr)
2121 1022792 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitall @ mp_waitall_2")
2122 1022792 : CALL add_perf(perf_id=9, count=1)
2123 : #else
2124 : requests = mp_request_null
2125 : #endif
2126 1022792 : CALL mp_timestop(handle)
2127 1022792 : END SUBROUTINE mp_waitall_2
2128 :
2129 : ! **************************************************************************************************
2130 : !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
2131 : !> the issue is with the rank or requests
2132 : !> \param count ...
2133 : !> \param array_of_requests ...
2134 : !> \param ierr ...
2135 : !> \author Joost VandeVondele
2136 : ! **************************************************************************************************
2137 : #if defined(__parallel)
2138 5139843 : SUBROUTINE mpi_waitall_internal(count, array_of_requests, ierr)
2139 : INTEGER, INTENT(in) :: count
2140 : TYPE(mp_request_type), DIMENSION(count), INTENT(inout) :: array_of_requests
2141 : INTEGER, INTENT(out) :: ierr
2142 :
2143 5139843 : MPI_REQUEST_TYPE, ALLOCATABLE, DIMENSION(:), TARGET :: request_handles
2144 :
2145 49431047 : ALLOCATE (request_handles(count), SOURCE=array_of_requests(1:count)%handle)
2146 5139843 : CALL mpi_waitall(count, request_handles, MPI_STATUSES_IGNORE, ierr)
2147 19596843 : array_of_requests(1:count)%handle = request_handles(:)
2148 5139843 : DEALLOCATE (request_handles)
2149 :
2150 5139843 : END SUBROUTINE mpi_waitall_internal
2151 : #endif
2152 :
2153 : ! **************************************************************************************************
2154 : !> \brief waits for completion of any of the given requests
2155 : !> \param requests ...
2156 : !> \param completed ...
2157 : !> \par History
2158 : !> 09.2008 created
2159 : !> \author Iain Bethune (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
2160 : ! **************************************************************************************************
2161 12536 : SUBROUTINE mp_waitany(requests, completed)
2162 : TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2163 : INTEGER, INTENT(out) :: completed
2164 :
2165 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_waitany'
2166 :
2167 : INTEGER :: handle
2168 : #if defined(__parallel)
2169 : INTEGER :: count, ierr
2170 12536 : MPI_REQUEST_TYPE, ALLOCATABLE, DIMENSION(:) :: request_handles
2171 : #endif
2172 :
2173 12536 : CALL mp_timeset(routineN, handle)
2174 :
2175 : #if defined(__parallel)
2176 12536 : count = SIZE(requests)
2177 : ! Convert CP2K's request_handles to the plain handle for the library
2178 100288 : ALLOCATE (request_handles(count), SOURCE=requests(1:count)%handle)
2179 :
2180 12536 : CALL mpi_waitany(count, request_handles, completed, MPI_STATUS_IGNORE, ierr)
2181 12536 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitany @ mp_waitany")
2182 :
2183 : ! Convert the plain handles to CP2K handles
2184 37608 : requests(1:count)%handle = request_handles(:)
2185 12536 : DEALLOCATE (request_handles)
2186 12536 : CALL add_perf(perf_id=9, count=1)
2187 : #else
2188 : requests = mp_request_null
2189 : completed = 1
2190 : #endif
2191 12536 : CALL mp_timestop(handle)
2192 25072 : END SUBROUTINE mp_waitany
2193 :
2194 : ! **************************************************************************************************
2195 : !> \brief Tests for completion of the given requests.
2196 : !> \brief We use mpi_test so that we can use a single status.
2197 : !> \param requests the list of requests to test
2198 : !> \return logical which determines if requests are complete
2199 : !> \par History
2200 : !> 3.2016 adapted to any shape [Nico Holmberg]
2201 : !> \author Alfio Lazzaro
2202 : ! **************************************************************************************************
2203 6400 : FUNCTION mp_testall_tv(requests) RESULT(flag)
2204 : TYPE(mp_request_type), DIMENSION(:), INTENT(INOUT) :: requests
2205 : LOGICAL :: flag
2206 :
2207 : #if defined(__parallel)
2208 : INTEGER :: i, ierr
2209 : LOGICAL, DIMENSION(:), POINTER :: flags
2210 : #endif
2211 :
2212 6400 : flag = .TRUE.
2213 :
2214 : #if defined(__parallel)
2215 19200 : ALLOCATE (flags(SIZE(requests)))
2216 25600 : DO i = 1, SIZE(requests)
2217 19200 : CALL mpi_test(requests(i)%handle, flags(i), MPI_STATUS_IGNORE, ierr)
2218 19200 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testall @ mp_testall_tv")
2219 45329 : flag = flag .AND. flags(i)
2220 : END DO
2221 6400 : DEALLOCATE (flags)
2222 : #else
2223 : requests = mp_request_null
2224 : #endif
2225 6400 : END FUNCTION mp_testall_tv
2226 :
2227 : ! **************************************************************************************************
2228 : !> \brief Tests for completion of the given request.
2229 : !> \param request the request
2230 : !> \param flag logical which determines if the request is completed
2231 : !> \par History
2232 : !> 3.2016 created
2233 : !> \author Nico Holmberg
2234 : ! **************************************************************************************************
2235 540 : FUNCTION mp_test_1(request) RESULT(flag)
2236 : CLASS(mp_request_type), INTENT(inout) :: request
2237 : LOGICAL :: flag
2238 :
2239 : #if defined(__parallel)
2240 : INTEGER :: ierr
2241 :
2242 540 : CALL mpi_test(request%handle, flag, MPI_STATUS_IGNORE, ierr)
2243 540 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_test @ mp_test_1")
2244 : #else
2245 : MARK_USED(request)
2246 : flag = .TRUE.
2247 : #endif
2248 540 : END FUNCTION mp_test_1
2249 :
2250 : ! **************************************************************************************************
2251 : !> \brief tests for completion of the given requests
2252 : !> \param requests ...
2253 : !> \param completed ...
2254 : !> \param flag ...
2255 : !> \par History
2256 : !> 08.2011 created
2257 : !> \author Iain Bethune
2258 : ! **************************************************************************************************
2259 0 : SUBROUTINE mp_testany_1(requests, completed, flag)
2260 : TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2261 : INTEGER, INTENT(out), OPTIONAL :: completed
2262 : LOGICAL, INTENT(out), OPTIONAL :: flag
2263 :
2264 : #if defined(__parallel)
2265 : INTEGER :: completed_l, count, ierr
2266 : LOGICAL :: flag_l
2267 :
2268 0 : count = SIZE(requests)
2269 :
2270 0 : CALL mpi_testany_internal(count, requests, completed_l, flag_l, MPI_STATUS_IGNORE, ierr)
2271 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testany_1 @ mp_testany")
2272 :
2273 0 : IF (PRESENT(completed)) completed = completed_l
2274 0 : IF (PRESENT(flag)) flag = flag_l
2275 : #else
2276 : MARK_USED(requests)
2277 : IF (PRESENT(completed)) completed = 1
2278 : IF (PRESENT(flag)) flag = .TRUE.
2279 : #endif
2280 0 : END SUBROUTINE mp_testany_1
2281 :
2282 : ! **************************************************************************************************
2283 : !> \brief tests for completion of the given requests
2284 : !> \param requests ...
2285 : !> \param completed ...
2286 : !> \param flag ...
2287 : !> \par History
2288 : !> 08.2011 created
2289 : !> \author Iain Bethune
2290 : ! **************************************************************************************************
2291 0 : SUBROUTINE mp_testany_2(requests, completed, flag)
2292 : TYPE(mp_request_type), DIMENSION(:, :), INTENT(inout) :: requests
2293 : INTEGER, INTENT(out), OPTIONAL :: completed
2294 : LOGICAL, INTENT(out), OPTIONAL :: flag
2295 :
2296 : #if defined(__parallel)
2297 : INTEGER :: completed_l, count, ierr
2298 : LOGICAL :: flag_l
2299 :
2300 0 : count = SIZE(requests)
2301 :
2302 0 : CALL mpi_testany_internal(count, requests, completed_l, flag_l, MPI_STATUS_IGNORE, ierr)
2303 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testany_2 @ mp_testany")
2304 :
2305 0 : IF (PRESENT(completed)) completed = completed_l
2306 0 : IF (PRESENT(flag)) flag = flag_l
2307 : #else
2308 : MARK_USED(requests)
2309 : IF (PRESENT(completed)) completed = 1
2310 : IF (PRESENT(flag)) flag = .TRUE.
2311 : #endif
2312 0 : END SUBROUTINE mp_testany_2
2313 :
2314 : ! **************************************************************************************************
2315 : !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
2316 : !> the issue is with the rank or requests
2317 : !> \param count ...
2318 : !> \param array_of_requests ...
2319 : !> \param index ...
2320 : !> \param flag ...
2321 : !> \param status ...
2322 : !> \param ierr ...
2323 : !> \author Joost VandeVondele
2324 : ! **************************************************************************************************
2325 : #if defined(__parallel)
2326 0 : SUBROUTINE mpi_testany_internal(count, array_of_requests, index, flag, status, ierr)
2327 : INTEGER, INTENT(in) :: count
2328 : TYPE(mp_request_type), DIMENSION(count), INTENT(inout) :: array_of_requests
2329 : INTEGER, INTENT(out) :: index
2330 : LOGICAL, INTENT(out) :: flag
2331 : MPI_STATUS_TYPE, INTENT(out) :: status
2332 : INTEGER, INTENT(out) :: ierr
2333 :
2334 0 : MPI_REQUEST_TYPE, ALLOCATABLE, DIMENSION(:) :: request_handles
2335 :
2336 0 : ALLOCATE (request_handles(count), SOURCE=array_of_requests(1:count)%handle)
2337 0 : CALL mpi_testany(count, request_handles, index, flag, status, ierr)
2338 0 : array_of_requests(1:count)%handle = request_handles(:)
2339 0 : DEALLOCATE (request_handles)
2340 :
2341 0 : END SUBROUTINE mpi_testany_internal
2342 : #endif
2343 :
2344 : ! **************************************************************************************************
2345 : !> \brief the direct way to split a communicator each color is a sub_comm,
2346 : !> the rank order is according to the order in the orig comm
2347 : !> \param comm ...
2348 : !> \param sub_comm ...
2349 : !> \param color ...
2350 : !> \param key ...
2351 : !> \author Joost VandeVondele
2352 : ! **************************************************************************************************
2353 1146630 : SUBROUTINE mp_comm_split_direct(comm, sub_comm, color, key)
2354 : CLASS(mp_comm_type), INTENT(in) :: comm
2355 : CLASS(mp_comm_type), INTENT(OUT) :: sub_comm
2356 : INTEGER, INTENT(in) :: color
2357 : INTEGER, INTENT(in), OPTIONAL :: key
2358 :
2359 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_split_direct'
2360 :
2361 : INTEGER :: handle
2362 : #if defined(__parallel)
2363 : INTEGER :: ierr, my_key
2364 : #endif
2365 :
2366 1146630 : CALL mp_timeset(routineN, handle)
2367 :
2368 : #if defined(__parallel)
2369 1146630 : my_key = 0
2370 1146630 : IF (PRESENT(key)) my_key = key
2371 1146630 : CALL mpi_comm_split(comm%handle, color, my_key, sub_comm%handle, ierr)
2372 1146630 : IF (ierr /= mpi_success) CALL mp_stop(ierr, routineN)
2373 1146630 : CALL add_perf(perf_id=10, count=1)
2374 : #else
2375 : sub_comm%handle = mp_comm_default_handle
2376 : MARK_USED(comm)
2377 : MARK_USED(color)
2378 : MARK_USED(key)
2379 : #endif
2380 1146630 : debug_comm_count = debug_comm_count + 1
2381 1146630 : CALL sub_comm%init()
2382 1146630 : CALL mp_timestop(handle)
2383 :
2384 1146630 : END SUBROUTINE mp_comm_split_direct
2385 : ! **************************************************************************************************
2386 : !> \brief splits a communicator by a predefined MPI split type, e.g. mp_comm_split_type_shared
2387 : !> to obtain the node-local (shared-memory) sub-communicator each rank belongs to
2388 : !> \param comm ...
2389 : !> \param sub_comm ...
2390 : !> \param split the split-type/info bundle (e.g. mp_comm_split_type_shared)
2391 : !> \param key controls the rank ordering within each sub_comm (default 0)
2392 : ! **************************************************************************************************
2393 2 : SUBROUTINE mp_comm_split_type(comm, sub_comm, split, key)
2394 : CLASS(mp_comm_type), INTENT(in) :: comm
2395 : CLASS(mp_comm_type), INTENT(OUT) :: sub_comm
2396 : TYPE(mp_split_type), INTENT(in) :: split
2397 : INTEGER, INTENT(in), OPTIONAL :: key
2398 :
2399 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_comm_split_type'
2400 :
2401 : INTEGER :: handle
2402 : #if defined(__parallel)
2403 : INTEGER :: ierr, my_key
2404 : #endif
2405 :
2406 2 : CALL mp_timeset(routineN, handle)
2407 :
2408 : #if defined(__parallel)
2409 2 : my_key = 0
2410 2 : IF (PRESENT(key)) my_key = key
2411 : CALL mpi_comm_split_type(comm%handle, split%split_type, my_key, split%info%handle, &
2412 2 : sub_comm%handle, ierr)
2413 2 : IF (ierr /= mpi_success) CALL mp_stop(ierr, routineN)
2414 2 : CALL add_perf(perf_id=10, count=1)
2415 : #else
2416 : sub_comm%handle = mp_comm_default_handle
2417 : MARK_USED(comm)
2418 : MARK_USED(split)
2419 : MARK_USED(key)
2420 : #endif
2421 2 : debug_comm_count = debug_comm_count + 1
2422 2 : CALL sub_comm%init()
2423 2 : CALL mp_timestop(handle)
2424 :
2425 2 : END SUBROUTINE mp_comm_split_type
2426 : ! **************************************************************************************************
2427 : !> \brief splits the given communicator in group in subgroups trying to organize
2428 : !> them in a way that the communication within each subgroup is
2429 : !> efficient (but not necessarily the communication between subgroups)
2430 : !> \param comm the mpi communicator that you want to split
2431 : !> \param sub_comm the communicator for the subgroup (created, needs to be freed later)
2432 : !> \param ngroups actual number of groups
2433 : !> \param group_distribution input : allocated with array with the nprocs entries (0 .. nprocs-1)
2434 : !> \param subgroup_min_size the minimum size of the subgroup
2435 : !> \param n_subgroups the number of subgroups wanted
2436 : !> \param group_partition n_subgroups sized array containing the number of cpus wanted per group.
2437 : !> should match the total number of cpus (only used if present and associated) (0..ngroups-1)
2438 : !> \param stride create groups using a stride (default=1) through the ranks of the comm to be split.
2439 : !> \par History
2440 : !> 10.2003 created [fawzi]
2441 : !> 02.2004 modified [Joost VandeVondele]
2442 : !> \author Fawzi Mohamed
2443 : !> \note
2444 : !> at least one of subgroup_min_size and n_subgroups is needed,
2445 : !> the other default to the value needed to use most processors.
2446 : !> if less cpus are present than needed for subgroup min size, n_subgroups,
2447 : !> just one comm is created that contains all cpus
2448 : ! **************************************************************************************************
2449 271681 : SUBROUTINE mp_comm_split(comm, sub_comm, ngroups, group_distribution, &
2450 271681 : subgroup_min_size, n_subgroups, group_partition, stride)
2451 : CLASS(mp_comm_type), INTENT(in) :: comm
2452 : CLASS(mp_comm_type), INTENT(out) :: sub_comm
2453 : INTEGER, INTENT(out) :: ngroups
2454 : INTEGER, DIMENSION(0:), INTENT(INOUT) :: group_distribution
2455 : INTEGER, INTENT(in), OPTIONAL :: subgroup_min_size, &
2456 : n_subgroups
2457 : INTEGER, DIMENSION(0:), INTENT(IN), OPTIONAL :: group_partition
2458 : INTEGER, OPTIONAL, INTENT(IN) :: stride
2459 :
2460 : CHARACTER(LEN=*), PARAMETER :: routineN = 'mp_comm_split', &
2461 : routineP = moduleN//':'//routineN
2462 :
2463 : INTEGER :: handle, mepos, nnodes
2464 : #if defined(__parallel)
2465 : INTEGER :: color, i, ierr, j, k, &
2466 : my_subgroup_min_size, &
2467 : istride, local_stride, irank
2468 271681 : INTEGER, DIMENSION(:), ALLOCATABLE :: rank_permutation
2469 : #endif
2470 :
2471 271681 : CALL mp_timeset(routineN, handle)
2472 :
2473 : ! actual number of groups
2474 :
2475 271681 : IF (.NOT. PRESENT(subgroup_min_size) .AND. .NOT. PRESENT(n_subgroups)) THEN
2476 0 : CPABORT(routineP//" missing arguments")
2477 : END IF
2478 271681 : IF (PRESENT(subgroup_min_size) .AND. PRESENT(n_subgroups)) THEN
2479 0 : CPABORT(routineP//" too many arguments")
2480 : END IF
2481 :
2482 271681 : CALL comm%get_size(nnodes)
2483 271681 : CALL comm%get_rank(mepos)
2484 :
2485 271681 : IF (UBOUND(group_distribution, 1) /= nnodes - 1) THEN
2486 0 : CPABORT(routineP//" group_distribution wrong bounds")
2487 : END IF
2488 :
2489 : #if defined(__parallel)
2490 271681 : IF (PRESENT(subgroup_min_size)) THEN
2491 154 : IF (subgroup_min_size < 0 .OR. subgroup_min_size > nnodes) THEN
2492 0 : CPABORT(routineP//" subgroup_min_size too small or too large")
2493 : END IF
2494 154 : ngroups = nnodes/subgroup_min_size
2495 154 : my_subgroup_min_size = subgroup_min_size
2496 : ELSE ! n_subgroups
2497 271527 : IF (n_subgroups <= 0) THEN
2498 0 : CPABORT(routineP//" n_subgroups too small")
2499 : END IF
2500 271527 : IF (nnodes/n_subgroups > 0) THEN ! we have a least one cpu per group
2501 267751 : ngroups = n_subgroups
2502 : ELSE ! well, only one group then
2503 3776 : ngroups = 1
2504 : END IF
2505 271527 : my_subgroup_min_size = nnodes/ngroups
2506 : END IF
2507 :
2508 : ! rank_permutation: is a permutation of ranks, so that groups are not necessarily continuous in rank of the master group
2509 : ! while the order is not critical (we only color ranks), it can e.g. be used to make groups that have just 1 rank per node
2510 : ! (by setting stride equal to the number of mpi ranks per node), or by sharing a node between two groups (stride 2).
2511 815043 : ALLOCATE (rank_permutation(0:nnodes - 1))
2512 271681 : local_stride = 1
2513 271681 : IF (PRESENT(stride)) local_stride = stride
2514 271681 : k = 0
2515 543362 : DO istride = 1, local_stride
2516 543362 : DO irank = istride - 1, nnodes - 1, local_stride
2517 539585 : rank_permutation(k) = irank
2518 539585 : k = k + 1
2519 : END DO
2520 : END DO
2521 :
2522 811266 : DO i = 0, nnodes - 1
2523 811266 : group_distribution(rank_permutation(i)) = MIN(i/my_subgroup_min_size, ngroups - 1)
2524 : END DO
2525 : ! even the user gave a partition, see if we can use it to overwrite this choice
2526 271681 : IF (PRESENT(group_partition)) THEN
2527 1096362 : IF (ALL(group_partition > 0) .AND. (SUM(group_partition) == nnodes) .AND. (ngroups == SIZE(group_partition))) THEN
2528 90 : k = 0
2529 90 : DO i = 0, SIZE(group_partition) - 1
2530 150 : DO j = 1, group_partition(i)
2531 60 : group_distribution(rank_permutation(k)) = i
2532 120 : k = k + 1
2533 : END DO
2534 : END DO
2535 : ELSE
2536 : ! just ignore silently as we have reasonable defaults. Probably a warning would not be to bad
2537 : END IF
2538 : END IF
2539 271681 : DEALLOCATE (rank_permutation)
2540 271681 : color = group_distribution(mepos)
2541 271681 : CALL mpi_comm_split(comm%handle, color, 0, sub_comm%handle, ierr)
2542 271681 : IF (ierr /= mpi_success) CALL mp_stop(ierr, "in "//routineP//" split")
2543 :
2544 271681 : CALL add_perf(perf_id=10, count=1)
2545 : #else
2546 : sub_comm%handle = mp_comm_default_handle
2547 : group_distribution(0) = 0
2548 : ngroups = 1
2549 : MARK_USED(comm)
2550 : MARK_USED(stride)
2551 : MARK_USED(group_partition)
2552 : #endif
2553 271681 : debug_comm_count = debug_comm_count + 1
2554 271681 : CALL sub_comm%init()
2555 271681 : CALL mp_timestop(handle)
2556 :
2557 543362 : END SUBROUTINE mp_comm_split
2558 :
2559 : ! **************************************************************************************************
2560 : !> \brief probes for an incoming message with any tag
2561 : !> \param[inout] source the source of the possible incoming message,
2562 : !> if MP_ANY_SOURCE it is a blocking one and return value is the source
2563 : !> of the next incoming message
2564 : !> if source is a different value it is a non-blocking probe returning
2565 : !> MP_ANY_SOURCE if there is no incoming message
2566 : !> \param[in] comm the communicator
2567 : !> \param[out] tag the tag of the incoming message
2568 : !> \author Mandes
2569 : ! **************************************************************************************************
2570 1533997 : SUBROUTINE mp_probe(source, comm, tag)
2571 : INTEGER, INTENT(INOUT) :: source
2572 : CLASS(mp_comm_type), INTENT(IN) :: comm
2573 : INTEGER, INTENT(OUT) :: tag
2574 :
2575 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_probe'
2576 :
2577 : INTEGER :: handle
2578 : #if defined(__parallel)
2579 : INTEGER :: ierr
2580 : MPI_STATUS_TYPE :: status_single
2581 : LOGICAL :: flag
2582 : #endif
2583 :
2584 : ! ---------------------------------------------------------------------------
2585 :
2586 1533997 : CALL mp_timeset(routineN, handle)
2587 :
2588 : #if defined(__parallel)
2589 1533997 : IF (source == mp_any_source) THEN
2590 14 : CALL mpi_probe(mp_any_source, mp_any_tag, comm%handle, status_single, ierr)
2591 14 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_probe @ mp_probe")
2592 14 : source = status_single MPI_STATUS_EXTRACT(MPI_SOURCE)
2593 14 : tag = status_single MPI_STATUS_EXTRACT(MPI_TAG)
2594 : ELSE
2595 : flag = .FALSE.
2596 1533983 : CALL mpi_iprobe(source, mp_any_tag, comm%handle, flag, status_single, ierr)
2597 1533983 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iprobe @ mp_probe")
2598 1533983 : IF (flag .EQV. .FALSE.) THEN
2599 1525225 : source = mp_any_source
2600 1525225 : tag = -1 !status_single(MPI_TAG) ! in case of flag==false status is undefined
2601 : ELSE
2602 8758 : tag = status_single MPI_STATUS_EXTRACT(MPI_TAG)
2603 : END IF
2604 : END IF
2605 : #else
2606 : tag = -1
2607 : MARK_USED(comm)
2608 : MARK_USED(source)
2609 : #endif
2610 1533997 : CALL mp_timestop(handle)
2611 1533997 : END SUBROUTINE mp_probe
2612 :
2613 : ! **************************************************************************************************
2614 : ! Here come the data routines with none of the standard data types.
2615 : ! **************************************************************************************************
2616 :
2617 : ! **************************************************************************************************
2618 : !> \brief ...
2619 : !> \param msg ...
2620 : !> \param source ...
2621 : !> \param comm ...
2622 : ! **************************************************************************************************
2623 752830 : SUBROUTINE mp_bcast_b(msg, source, comm)
2624 : LOGICAL, INTENT(INOUT) :: msg
2625 : INTEGER, INTENT(IN) :: source
2626 : CLASS(mp_comm_type), INTENT(IN) :: comm
2627 :
2628 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_b'
2629 :
2630 : INTEGER :: handle
2631 : #if defined(__parallel)
2632 : INTEGER :: ierr, msglen
2633 : #endif
2634 :
2635 752830 : CALL mp_timeset(routineN, handle)
2636 :
2637 : #if defined(__parallel)
2638 752830 : msglen = 1
2639 752830 : CALL mpi_bcast(msg, msglen, MPI_LOGICAL, source, comm%handle, ierr)
2640 752830 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
2641 752830 : CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2642 : #else
2643 : MARK_USED(msg)
2644 : MARK_USED(source)
2645 : MARK_USED(comm)
2646 : #endif
2647 752830 : CALL mp_timestop(handle)
2648 752830 : END SUBROUTINE mp_bcast_b
2649 :
2650 : ! **************************************************************************************************
2651 : !> \brief ...
2652 : !> \param msg ...
2653 : !> \param source ...
2654 : !> \param comm ...
2655 : ! **************************************************************************************************
2656 686199 : SUBROUTINE mp_bcast_b_src(msg, comm)
2657 : LOGICAL, INTENT(INOUT) :: msg
2658 : CLASS(mp_comm_type), INTENT(IN) :: comm
2659 :
2660 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_b_src'
2661 :
2662 : INTEGER :: handle
2663 : #if defined(__parallel)
2664 : INTEGER :: ierr, msglen
2665 : #endif
2666 :
2667 686199 : CALL mp_timeset(routineN, handle)
2668 :
2669 : #if defined(__parallel)
2670 686199 : msglen = 1
2671 686199 : CALL mpi_bcast(msg, msglen, MPI_LOGICAL, comm%source, comm%handle, ierr)
2672 686199 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
2673 686199 : CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2674 : #else
2675 : MARK_USED(msg)
2676 : MARK_USED(comm)
2677 : #endif
2678 686199 : CALL mp_timestop(handle)
2679 686199 : END SUBROUTINE mp_bcast_b_src
2680 :
2681 : ! **************************************************************************************************
2682 : !> \brief ...
2683 : !> \param msg ...
2684 : !> \param source ...
2685 : !> \param comm ...
2686 : ! **************************************************************************************************
2687 0 : SUBROUTINE mp_bcast_bv(msg, source, comm)
2688 : LOGICAL, CONTIGUOUS, INTENT(INOUT) :: msg(:)
2689 : INTEGER, INTENT(IN) :: source
2690 : CLASS(mp_comm_type), INTENT(IN) :: comm
2691 :
2692 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_bv'
2693 :
2694 : INTEGER :: handle
2695 : #if defined(__parallel)
2696 : INTEGER :: ierr, msglen
2697 : #endif
2698 :
2699 0 : CALL mp_timeset(routineN, handle)
2700 :
2701 : #if defined(__parallel)
2702 0 : msglen = SIZE(msg)
2703 0 : CALL mpi_bcast(msg, msglen, MPI_LOGICAL, source, comm%handle, ierr)
2704 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
2705 0 : CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2706 : #else
2707 : MARK_USED(msg)
2708 : MARK_USED(source)
2709 : MARK_USED(comm)
2710 : #endif
2711 0 : CALL mp_timestop(handle)
2712 0 : END SUBROUTINE mp_bcast_bv
2713 :
2714 : ! **************************************************************************************************
2715 : !> \brief ...
2716 : !> \param msg ...
2717 : !> \param comm ...
2718 : ! **************************************************************************************************
2719 0 : SUBROUTINE mp_bcast_bv_src(msg, comm)
2720 : LOGICAL, CONTIGUOUS, INTENT(INOUT) :: msg(:)
2721 : CLASS(mp_comm_type), INTENT(IN) :: comm
2722 :
2723 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_bv_src'
2724 :
2725 : INTEGER :: handle
2726 : #if defined(__parallel)
2727 : INTEGER :: ierr, msglen
2728 : #endif
2729 :
2730 0 : CALL mp_timeset(routineN, handle)
2731 :
2732 : #if defined(__parallel)
2733 0 : msglen = SIZE(msg)
2734 0 : CALL mpi_bcast(msg, msglen, MPI_LOGICAL, comm%source, comm%handle, ierr)
2735 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
2736 0 : CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2737 : #else
2738 : MARK_USED(msg)
2739 : MARK_USED(comm)
2740 : #endif
2741 0 : CALL mp_timestop(handle)
2742 0 : END SUBROUTINE mp_bcast_bv_src
2743 :
2744 : ! **************************************************************************************************
2745 : !> \brief Non-blocking send of logical vector data
2746 : !> \param msgin the input message
2747 : !> \param dest the destination processor
2748 : !> \param comm the communicator object
2749 : !> \param request communication request index
2750 : !> \param tag message tag
2751 : !> \par History
2752 : !> 3.2016 added _bv subroutine [Nico Holmberg]
2753 : !> \author fawzi
2754 : !> \note see mp_irecv_iv
2755 : !> \note
2756 : !> arrays can be pointers or assumed shape, but they must be contiguous!
2757 : ! **************************************************************************************************
2758 16 : SUBROUTINE mp_isend_bv(msgin, dest, comm, request, tag)
2759 : LOGICAL, DIMENSION(:), INTENT(IN) :: msgin
2760 : INTEGER, INTENT(IN) :: dest
2761 : CLASS(mp_comm_type), INTENT(IN) :: comm
2762 : TYPE(mp_request_type), INTENT(out) :: request
2763 : INTEGER, INTENT(in), OPTIONAL :: tag
2764 :
2765 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_isend_bv'
2766 :
2767 : INTEGER :: handle
2768 : #if defined(__parallel)
2769 : INTEGER :: ierr, msglen, my_tag
2770 : LOGICAL :: foo(1)
2771 : #endif
2772 :
2773 16 : CALL mp_timeset(routineN, handle)
2774 :
2775 : #if defined(__parallel)
2776 : #if !defined(__GNUC__) || __GNUC__ >= 9
2777 32 : CPASSERT(IS_CONTIGUOUS(msgin) .OR. PRODUCT(SHAPE(msgin)) == 0)
2778 : #endif
2779 :
2780 16 : my_tag = 0
2781 16 : IF (PRESENT(tag)) my_tag = tag
2782 :
2783 16 : msglen = SIZE(msgin, 1)
2784 16 : IF (msglen > 0) THEN
2785 : CALL mpi_isend(msgin(1), msglen, MPI_LOGICAL, dest, my_tag, &
2786 16 : comm%handle, request%handle, ierr)
2787 : ELSE
2788 : CALL mpi_isend(foo, msglen, MPI_LOGICAL, dest, my_tag, &
2789 0 : comm%handle, request%handle, ierr)
2790 : END IF
2791 16 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routineN)
2792 :
2793 16 : CALL add_perf(perf_id=11, count=1, msg_size=msglen*loglen)
2794 : #else
2795 : CPABORT("mp_isend called in non parallel case")
2796 : MARK_USED(msgin)
2797 : MARK_USED(dest)
2798 : MARK_USED(comm)
2799 : MARK_USED(tag)
2800 : request = mp_request_null
2801 : #endif
2802 16 : CALL mp_timestop(handle)
2803 16 : END SUBROUTINE mp_isend_bv
2804 :
2805 : ! **************************************************************************************************
2806 : !> \brief Non-blocking receive of logical vector data
2807 : !> \param msgout the received message
2808 : !> \param source the source processor
2809 : !> \param comm the communicator object
2810 : !> \param request communication request index
2811 : !> \param tag message tag
2812 : !> \par History
2813 : !> 3.2016 added _bv subroutine [Nico Holmberg]
2814 : !> \author fawzi
2815 : !> \note see mp_irecv_iv
2816 : !> \note
2817 : !> arrays can be pointers or assumed shape, but they must be contiguous!
2818 : ! **************************************************************************************************
2819 16 : SUBROUTINE mp_irecv_bv(msgout, source, comm, request, tag)
2820 : LOGICAL, DIMENSION(:), INTENT(INOUT) :: msgout
2821 : INTEGER, INTENT(IN) :: source
2822 : CLASS(mp_comm_type), INTENT(IN) :: comm
2823 : TYPE(mp_request_type), INTENT(out) :: request
2824 : INTEGER, INTENT(in), OPTIONAL :: tag
2825 :
2826 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_irecv_bv'
2827 :
2828 : INTEGER :: handle
2829 : #if defined(__parallel)
2830 : INTEGER :: ierr, msglen, my_tag
2831 : LOGICAL :: foo(1)
2832 : #endif
2833 :
2834 16 : CALL mp_timeset(routineN, handle)
2835 :
2836 : #if defined(__parallel)
2837 : #if !defined(__GNUC__) || __GNUC__ >= 9
2838 32 : CPASSERT(IS_CONTIGUOUS(msgout) .OR. PRODUCT(SHAPE(msgout)) == 0)
2839 : #endif
2840 :
2841 16 : my_tag = 0
2842 16 : IF (PRESENT(tag)) my_tag = tag
2843 :
2844 16 : msglen = SIZE(msgout, 1)
2845 16 : IF (msglen > 0) THEN
2846 : CALL mpi_irecv(msgout(1), msglen, MPI_LOGICAL, source, my_tag, &
2847 16 : comm%handle, request%handle, ierr)
2848 : ELSE
2849 : CALL mpi_irecv(foo, msglen, MPI_LOGICAL, source, my_tag, &
2850 0 : comm%handle, request%handle, ierr)
2851 : END IF
2852 16 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routineN)
2853 :
2854 16 : CALL add_perf(perf_id=12, count=1, msg_size=msglen*loglen)
2855 : #else
2856 : CPABORT("mp_irecv called in non parallel case")
2857 : MARK_USED(msgout)
2858 : MARK_USED(source)
2859 : MARK_USED(comm)
2860 : MARK_USED(tag)
2861 : request = mp_request_null
2862 : #endif
2863 16 : CALL mp_timestop(handle)
2864 16 : END SUBROUTINE mp_irecv_bv
2865 :
2866 : ! **************************************************************************************************
2867 : !> \brief Non-blocking send of rank-3 logical data
2868 : !> \param msgin the input message
2869 : !> \param dest the destination processor
2870 : !> \param comm the communicator object
2871 : !> \param request communication request index
2872 : !> \param tag message tag
2873 : !> \par History
2874 : !> 2.2016 added _bm3 subroutine [Nico Holmberg]
2875 : !> \author fawzi
2876 : !> \note see mp_irecv_iv
2877 : !> \note
2878 : !> arrays can be pointers or assumed shape, but they must be contiguous!
2879 : ! **************************************************************************************************
2880 0 : SUBROUTINE mp_isend_bm3(msgin, dest, comm, request, tag)
2881 : LOGICAL, DIMENSION(:, :, :), INTENT(INOUT) :: msgin
2882 : INTEGER, INTENT(IN) :: dest
2883 : CLASS(mp_comm_type), INTENT(IN) :: comm
2884 : TYPE(mp_request_type), INTENT(out) :: request
2885 : INTEGER, INTENT(in), OPTIONAL :: tag
2886 :
2887 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_isend_bm3'
2888 :
2889 : INTEGER :: handle
2890 : #if defined(__parallel)
2891 : INTEGER :: ierr, msglen, my_tag
2892 : LOGICAL :: foo(1)
2893 : #endif
2894 :
2895 0 : CALL mp_timeset(routineN, handle)
2896 :
2897 : #if defined(__parallel)
2898 : #if !defined(__GNUC__) || __GNUC__ >= 9
2899 0 : CPASSERT(IS_CONTIGUOUS(msgin) .OR. PRODUCT(SHAPE(msgin)) == 0)
2900 : #endif
2901 :
2902 0 : my_tag = 0
2903 0 : IF (PRESENT(tag)) my_tag = tag
2904 :
2905 0 : msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
2906 0 : IF (msglen > 0) THEN
2907 : CALL mpi_isend(msgin(1, 1, 1), msglen, MPI_LOGICAL, dest, my_tag, &
2908 0 : comm%handle, request%handle, ierr)
2909 : ELSE
2910 : CALL mpi_isend(foo, msglen, MPI_LOGICAL, dest, my_tag, &
2911 0 : comm%handle, request%handle, ierr)
2912 : END IF
2913 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routineN)
2914 :
2915 0 : CALL add_perf(perf_id=11, count=1, msg_size=msglen*loglen)
2916 : #else
2917 : CPABORT("mp_isend called in non parallel case")
2918 : MARK_USED(msgin)
2919 : MARK_USED(dest)
2920 : MARK_USED(comm)
2921 : MARK_USED(tag)
2922 : request = mp_request_null
2923 : #endif
2924 0 : CALL mp_timestop(handle)
2925 0 : END SUBROUTINE mp_isend_bm3
2926 :
2927 : ! **************************************************************************************************
2928 : !> \brief Non-blocking receive of rank-3 logical data
2929 : !> \param msgout the received message
2930 : !> \param source the source processor
2931 : !> \param comm the communicator object
2932 : !> \param request communication request index
2933 : !> \param tag message tag
2934 : !> \par History
2935 : !> 2.2016 added _bm3 subroutine [Nico Holmberg]
2936 : !> \author fawzi
2937 : !> \note see mp_irecv_iv
2938 : !> \note
2939 : !> arrays can be pointers or assumed shape, but they must be contiguous!
2940 : ! **************************************************************************************************
2941 0 : SUBROUTINE mp_irecv_bm3(msgout, source, comm, request, tag)
2942 : LOGICAL, DIMENSION(:, :, :), INTENT(INOUT) :: msgout
2943 : INTEGER, INTENT(IN) :: source
2944 : CLASS(mp_comm_type), INTENT(IN) :: comm
2945 : TYPE(mp_request_type), INTENT(out) :: request
2946 : INTEGER, INTENT(in), OPTIONAL :: tag
2947 :
2948 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_irecv_bm3'
2949 :
2950 : INTEGER :: handle
2951 : #if defined(__parallel)
2952 : INTEGER :: ierr, msglen, my_tag
2953 : LOGICAL :: foo(1)
2954 : #endif
2955 :
2956 0 : CALL mp_timeset(routineN, handle)
2957 :
2958 : #if defined(__parallel)
2959 : #if !defined(__GNUC__) || __GNUC__ >= 9
2960 0 : CPASSERT(IS_CONTIGUOUS(msgout) .OR. PRODUCT(SHAPE(msgout)) == 0)
2961 : #endif
2962 :
2963 0 : my_tag = 0
2964 0 : IF (PRESENT(tag)) my_tag = tag
2965 :
2966 0 : msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
2967 0 : IF (msglen > 0) THEN
2968 : CALL mpi_irecv(msgout(1, 1, 1), msglen, MPI_LOGICAL, source, my_tag, &
2969 0 : comm%handle, request%handle, ierr)
2970 : ELSE
2971 : CALL mpi_irecv(foo, msglen, MPI_LOGICAL, source, my_tag, &
2972 0 : comm%handle, request%handle, ierr)
2973 : END IF
2974 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routineN)
2975 :
2976 0 : CALL add_perf(perf_id=12, count=1, msg_size=msglen*loglen)
2977 : #else
2978 : CPABORT("mp_irecv called in non parallel case")
2979 : MARK_USED(msgout)
2980 : MARK_USED(source)
2981 : MARK_USED(comm)
2982 : MARK_USED(request)
2983 : MARK_USED(tag)
2984 : request = mp_request_null
2985 : #endif
2986 0 : CALL mp_timestop(handle)
2987 0 : END SUBROUTINE mp_irecv_bm3
2988 :
2989 : ! **************************************************************************************************
2990 : !> \brief Broadcasts a string.
2991 : !> \param msg ...
2992 : !> \param source ...
2993 : !> \param comm ...
2994 : ! **************************************************************************************************
2995 4666397 : SUBROUTINE mp_bcast_av(msg, source, comm)
2996 : CHARACTER(LEN=*), INTENT(INOUT) :: msg
2997 : INTEGER, INTENT(IN) :: source
2998 : CLASS(mp_comm_type), INTENT(IN) :: comm
2999 :
3000 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_av'
3001 :
3002 : INTEGER :: handle
3003 : #if defined(__parallel)
3004 : INTEGER :: ierr, msglen
3005 : #endif
3006 :
3007 4666397 : CALL mp_timeset(routineN, handle)
3008 :
3009 : #if defined(__parallel)
3010 4666397 : msglen = LEN(msg)*charlen
3011 4666397 : IF (comm%mepos /= source) msg = "" ! need to clear msg
3012 4666397 : CALL mpi_bcast(msg, msglen, MPI_CHARACTER, source, comm%handle, ierr)
3013 4666397 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
3014 4666397 : CALL add_perf(perf_id=2, count=1, msg_size=msglen)
3015 : #else
3016 : MARK_USED(msg)
3017 : MARK_USED(source)
3018 : MARK_USED(comm)
3019 : #endif
3020 4666397 : CALL mp_timestop(handle)
3021 4666397 : END SUBROUTINE mp_bcast_av
3022 :
3023 : ! **************************************************************************************************
3024 : !> \brief Broadcasts a string.
3025 : !> \param msg ...
3026 : !> \param comm ...
3027 : ! **************************************************************************************************
3028 916 : SUBROUTINE mp_bcast_av_src(msg, comm)
3029 : CHARACTER(LEN=*), INTENT(INOUT) :: msg
3030 : CLASS(mp_comm_type), INTENT(IN) :: comm
3031 :
3032 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_av_src'
3033 :
3034 : INTEGER :: handle
3035 : #if defined(__parallel)
3036 : INTEGER :: ierr, msglen
3037 : #endif
3038 :
3039 916 : CALL mp_timeset(routineN, handle)
3040 :
3041 : #if defined(__parallel)
3042 916 : msglen = LEN(msg)*charlen
3043 916 : IF (.NOT. comm%is_source()) msg = "" ! need to clear msg
3044 916 : CALL mpi_bcast(msg, msglen, MPI_CHARACTER, comm%source, comm%handle, ierr)
3045 916 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
3046 916 : CALL add_perf(perf_id=2, count=1, msg_size=msglen)
3047 : #else
3048 : MARK_USED(msg)
3049 : MARK_USED(comm)
3050 : #endif
3051 916 : CALL mp_timestop(handle)
3052 916 : END SUBROUTINE mp_bcast_av_src
3053 :
3054 : ! **************************************************************************************************
3055 : !> \brief ...
3056 : !> \param msg ...
3057 : !> \param source ...
3058 : !> \param comm ...
3059 : ! **************************************************************************************************
3060 28 : SUBROUTINE mp_bcast_am(msg, source, comm)
3061 : CHARACTER(LEN=*), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3062 : INTEGER, INTENT(IN) :: source
3063 : CLASS(mp_comm_type), INTENT(IN) :: comm
3064 :
3065 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_am'
3066 :
3067 : INTEGER :: handle
3068 : #if defined(__parallel)
3069 : INTEGER :: ierr, msglen
3070 : #endif
3071 :
3072 28 : CALL mp_timeset(routineN, handle)
3073 :
3074 : #if defined(__parallel)
3075 28 : msglen = SIZE(msg)*LEN(msg(1))*charlen
3076 1922 : IF (comm%mepos /= source) msg = "" ! need to clear msg
3077 28 : CALL mpi_bcast(msg, msglen, MPI_CHARACTER, source, comm%handle, ierr)
3078 28 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
3079 28 : CALL add_perf(perf_id=2, count=1, msg_size=msglen)
3080 : #else
3081 : MARK_USED(msg)
3082 : MARK_USED(source)
3083 : MARK_USED(comm)
3084 : #endif
3085 28 : CALL mp_timestop(handle)
3086 28 : END SUBROUTINE mp_bcast_am
3087 :
3088 90714 : SUBROUTINE mp_bcast_am_src(msg, comm)
3089 : CHARACTER(LEN=*), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3090 : CLASS(mp_comm_type), INTENT(IN) :: comm
3091 :
3092 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_bcast_am_src'
3093 :
3094 : INTEGER :: handle
3095 : #if defined(__parallel)
3096 : INTEGER :: ierr, msglen
3097 : #endif
3098 :
3099 90714 : CALL mp_timeset(routineN, handle)
3100 :
3101 : #if defined(__parallel)
3102 90714 : msglen = SIZE(msg)*LEN(msg(1))*charlen
3103 45447714 : IF (.NOT. comm%is_source()) msg = "" ! need to clear msg
3104 90714 : CALL mpi_bcast(msg, msglen, MPI_CHARACTER, comm%source, comm%handle, ierr)
3105 90714 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routineN)
3106 90714 : CALL add_perf(perf_id=2, count=1, msg_size=msglen)
3107 : #else
3108 : MARK_USED(msg)
3109 : MARK_USED(comm)
3110 : #endif
3111 90714 : CALL mp_timestop(handle)
3112 90714 : END SUBROUTINE mp_bcast_am_src
3113 :
3114 : ! **************************************************************************************************
3115 : !> \brief Finds the location of the minimal element in a vector.
3116 : !> \param[in,out] msg Find location of minimum element among these
3117 : !> data (input).
3118 : !> \param[in] comm Message passing environment identifier
3119 : !> \par MPI mapping
3120 : !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3121 : !> \par Invalid data types
3122 : !> This routine is invalid for (int_8) data!
3123 : ! **************************************************************************************************
3124 862 : SUBROUTINE mp_minloc_dv(msg, comm)
3125 : REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3126 : CLASS(mp_comm_type), INTENT(IN) :: comm
3127 :
3128 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_minloc_dv'
3129 :
3130 : INTEGER :: handle
3131 : #if defined(__parallel)
3132 : INTEGER :: ierr, msglen
3133 862 : REAL(kind=real_8), ALLOCATABLE :: res(:)
3134 : #endif
3135 :
3136 : IF ("d" == "l" .AND. real_8 == int_8) THEN
3137 : CPABORT("Minimal location not available with long integers @ "//routineN)
3138 : END IF
3139 862 : CALL mp_timeset(routineN, handle)
3140 :
3141 : #if defined(__parallel)
3142 862 : msglen = SIZE(msg)
3143 2586 : ALLOCATE (res(1:msglen), STAT=ierr)
3144 862 : IF (ierr /= 0) &
3145 0 : CPABORT("allocate @ "//routineN)
3146 862 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2DOUBLE_PRECISION, MPI_MINLOC, comm%handle, ierr)
3147 862 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3148 2586 : msg = res
3149 862 : DEALLOCATE (res)
3150 862 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
3151 : #else
3152 : MARK_USED(msg)
3153 : MARK_USED(comm)
3154 : #endif
3155 862 : CALL mp_timestop(handle)
3156 862 : END SUBROUTINE mp_minloc_dv
3157 :
3158 : ! **************************************************************************************************
3159 : !> \brief Finds the location of the minimal element in a vector.
3160 : !> \param[in,out] msg Find location of minimum element among these
3161 : !> data (input).
3162 : !> \param[in] comm Message passing environment identifier
3163 : !> \par MPI mapping
3164 : !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3165 : !> \par Invalid data types
3166 : !> This routine is invalid for (int_8) data!
3167 : ! **************************************************************************************************
3168 0 : SUBROUTINE mp_minloc_iv(msg, comm)
3169 : INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3170 : CLASS(mp_comm_type), INTENT(IN) :: comm
3171 :
3172 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_minloc_iv'
3173 :
3174 : INTEGER :: handle
3175 : #if defined(__parallel)
3176 : INTEGER :: ierr, msglen
3177 0 : INTEGER(KIND=int_4), ALLOCATABLE :: res(:)
3178 : #endif
3179 :
3180 : IF ("i" == "l" .AND. int_4 == int_8) THEN
3181 : CPABORT("Minimal location not available with long integers @ "//routineN)
3182 : END IF
3183 0 : CALL mp_timeset(routineN, handle)
3184 :
3185 : #if defined(__parallel)
3186 0 : msglen = SIZE(msg)
3187 0 : ALLOCATE (res(1:msglen))
3188 0 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2INTEGER, MPI_MINLOC, comm%handle, ierr)
3189 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3190 0 : msg = res
3191 0 : DEALLOCATE (res)
3192 0 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
3193 : #else
3194 : MARK_USED(msg)
3195 : MARK_USED(comm)
3196 : #endif
3197 0 : CALL mp_timestop(handle)
3198 0 : END SUBROUTINE mp_minloc_iv
3199 :
3200 : ! **************************************************************************************************
3201 : !> \brief Finds the location of the minimal element in a vector.
3202 : !> \param[in,out] msg Find location of minimum element among these
3203 : !> data (input).
3204 : !> \param[in] comm Message passing environment identifier
3205 : !> \par MPI mapping
3206 : !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3207 : !> \par Invalid data types
3208 : !> This routine is invalid for (int_8) data!
3209 : ! **************************************************************************************************
3210 0 : SUBROUTINE mp_minloc_lv(msg, comm)
3211 : INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3212 : CLASS(mp_comm_type), INTENT(IN) :: comm
3213 :
3214 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_minloc_lv'
3215 :
3216 : INTEGER :: handle
3217 : #if defined(__parallel)
3218 : INTEGER :: ierr, msglen
3219 0 : INTEGER(KIND=int_8), ALLOCATABLE :: res(:)
3220 : #endif
3221 :
3222 : IF ("l" == "l" .AND. int_8 == int_8) THEN
3223 0 : CPABORT("Minimal location not available with long integers @ "//routineN)
3224 : END IF
3225 0 : CALL mp_timeset(routineN, handle)
3226 :
3227 : #if defined(__parallel)
3228 0 : msglen = SIZE(msg)
3229 0 : ALLOCATE (res(1:msglen))
3230 0 : CALL mpi_allreduce(msg, res, msglen/2, MPI_INTEGER8, MPI_MINLOC, comm%handle, ierr)
3231 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3232 0 : msg = res
3233 0 : DEALLOCATE (res)
3234 0 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
3235 : #else
3236 : MARK_USED(msg)
3237 : MARK_USED(comm)
3238 : #endif
3239 0 : CALL mp_timestop(handle)
3240 0 : END SUBROUTINE mp_minloc_lv
3241 :
3242 : ! **************************************************************************************************
3243 : !> \brief Finds the location of the minimal element in a vector.
3244 : !> \param[in,out] msg Find location of minimum element among these
3245 : !> data (input).
3246 : !> \param[in] comm Message passing environment identifier
3247 : !> \par MPI mapping
3248 : !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3249 : !> \par Invalid data types
3250 : !> This routine is invalid for (int_8) data!
3251 : ! **************************************************************************************************
3252 0 : SUBROUTINE mp_minloc_rv(msg, comm)
3253 : REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3254 : CLASS(mp_comm_type), INTENT(IN) :: comm
3255 :
3256 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_minloc_rv'
3257 :
3258 : INTEGER :: handle
3259 : #if defined(__parallel)
3260 : INTEGER :: ierr, msglen
3261 0 : REAL(kind=real_4), ALLOCATABLE :: res(:)
3262 : #endif
3263 :
3264 : IF ("r" == "l" .AND. real_4 == int_8) THEN
3265 : CPABORT("Minimal location not available with long integers @ "//routineN)
3266 : END IF
3267 0 : CALL mp_timeset(routineN, handle)
3268 :
3269 : #if defined(__parallel)
3270 0 : msglen = SIZE(msg)
3271 0 : ALLOCATE (res(1:msglen))
3272 0 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2REAL, MPI_MINLOC, comm%handle, ierr)
3273 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3274 0 : msg = res
3275 0 : DEALLOCATE (res)
3276 0 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
3277 : #else
3278 : MARK_USED(msg)
3279 : MARK_USED(comm)
3280 : #endif
3281 0 : CALL mp_timestop(handle)
3282 0 : END SUBROUTINE mp_minloc_rv
3283 :
3284 : ! **************************************************************************************************
3285 : !> \brief Finds the location of the maximal element in a vector.
3286 : !> \param[in,out] msg Find location of maximum element among these
3287 : !> data (input).
3288 : !> \param[in] comm Message passing environment identifier
3289 : !> \par MPI mapping
3290 : !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3291 : !> \par Invalid data types
3292 : !> This routine is invalid for (int_8) data!
3293 : ! **************************************************************************************************
3294 9318457 : SUBROUTINE mp_maxloc_dv(msg, comm)
3295 : REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3296 : CLASS(mp_comm_type), INTENT(IN) :: comm
3297 :
3298 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_maxloc_dv'
3299 :
3300 : INTEGER :: handle
3301 : #if defined(__parallel)
3302 : INTEGER :: ierr, msglen
3303 9318457 : REAL(kind=real_8), ALLOCATABLE :: res(:)
3304 : #endif
3305 :
3306 : IF ("d" == "l" .AND. real_8 == int_8) THEN
3307 : CPABORT("Maximal location not available with long integers @ "//routineN)
3308 : END IF
3309 9318457 : CALL mp_timeset(routineN, handle)
3310 :
3311 : #if defined(__parallel)
3312 9318457 : msglen = SIZE(msg)
3313 27955371 : ALLOCATE (res(1:msglen))
3314 9318457 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2DOUBLE_PRECISION, MPI_MAXLOC, comm%handle, ierr)
3315 9318457 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3316 27955371 : msg = res
3317 9318457 : DEALLOCATE (res)
3318 9318457 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
3319 : #else
3320 : MARK_USED(msg)
3321 : MARK_USED(comm)
3322 : #endif
3323 9318457 : CALL mp_timestop(handle)
3324 9318457 : END SUBROUTINE mp_maxloc_dv
3325 :
3326 : ! **************************************************************************************************
3327 : !> \brief Finds the location of the maximal element in a vector.
3328 : !> \param[in,out] msg Find location of maximum element among these
3329 : !> data (input).
3330 : !> \param[in] comm Message passing environment identifier
3331 : !> \par MPI mapping
3332 : !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3333 : !> \par Invalid data types
3334 : !> This routine is invalid for (int_8) data!
3335 : ! **************************************************************************************************
3336 216 : SUBROUTINE mp_maxloc_iv(msg, comm)
3337 : INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3338 : CLASS(mp_comm_type), INTENT(IN) :: comm
3339 :
3340 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_maxloc_iv'
3341 :
3342 : INTEGER :: handle
3343 : #if defined(__parallel)
3344 : INTEGER :: ierr, msglen
3345 216 : INTEGER(KIND=int_4), ALLOCATABLE :: res(:)
3346 : #endif
3347 :
3348 : IF ("i" == "l" .AND. int_4 == int_8) THEN
3349 : CPABORT("Maximal location not available with long integers @ "//routineN)
3350 : END IF
3351 216 : CALL mp_timeset(routineN, handle)
3352 :
3353 : #if defined(__parallel)
3354 216 : msglen = SIZE(msg)
3355 648 : ALLOCATE (res(1:msglen))
3356 216 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2INTEGER, MPI_MAXLOC, comm%handle, ierr)
3357 216 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3358 648 : msg = res
3359 216 : DEALLOCATE (res)
3360 216 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
3361 : #else
3362 : MARK_USED(msg)
3363 : MARK_USED(comm)
3364 : #endif
3365 216 : CALL mp_timestop(handle)
3366 216 : END SUBROUTINE mp_maxloc_iv
3367 :
3368 : ! **************************************************************************************************
3369 : !> \brief Finds the location of the maximal element in a vector.
3370 : !> \param[in,out] msg Find location of maximum element among these
3371 : !> data (input).
3372 : !> \param[in] comm Message passing environment identifier
3373 : !> \par MPI mapping
3374 : !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3375 : !> \par Invalid data types
3376 : !> This routine is invalid for (int_8) data!
3377 : ! **************************************************************************************************
3378 0 : SUBROUTINE mp_maxloc_lv(msg, comm)
3379 : INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3380 : CLASS(mp_comm_type), INTENT(IN) :: comm
3381 :
3382 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_maxloc_lv'
3383 :
3384 : INTEGER :: handle
3385 : #if defined(__parallel)
3386 : INTEGER :: ierr, msglen
3387 0 : INTEGER(KIND=int_8), ALLOCATABLE :: res(:)
3388 : #endif
3389 :
3390 : IF ("l" == "l" .AND. int_8 == int_8) THEN
3391 0 : CPABORT("Maximal location not available with long integers @ "//routineN)
3392 : END IF
3393 0 : CALL mp_timeset(routineN, handle)
3394 :
3395 : #if defined(__parallel)
3396 0 : msglen = SIZE(msg)
3397 0 : ALLOCATE (res(1:msglen))
3398 0 : CALL mpi_allreduce(msg, res, msglen/2, MPI_INTEGER8, MPI_MAXLOC, comm%handle, ierr)
3399 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3400 0 : msg = res
3401 0 : DEALLOCATE (res)
3402 0 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
3403 : #else
3404 : MARK_USED(msg)
3405 : MARK_USED(comm)
3406 : #endif
3407 0 : CALL mp_timestop(handle)
3408 0 : END SUBROUTINE mp_maxloc_lv
3409 :
3410 : ! **************************************************************************************************
3411 : !> \brief Finds the location of the maximal element in a vector.
3412 : !> \param[in,out] msg Find location of maximum element among these
3413 : !> data (input).
3414 : !> \param[in] comm Message passing environment identifier
3415 : !> \par MPI mapping
3416 : !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3417 : !> \par Invalid data types
3418 : !> This routine is invalid for (int_8) data!
3419 : ! **************************************************************************************************
3420 0 : SUBROUTINE mp_maxloc_rv(msg, comm)
3421 : REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3422 : CLASS(mp_comm_type), INTENT(IN) :: comm
3423 :
3424 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_maxloc_rv'
3425 :
3426 : INTEGER :: handle
3427 : #if defined(__parallel)
3428 : INTEGER :: ierr, msglen
3429 0 : REAL(kind=real_4), ALLOCATABLE :: res(:)
3430 : #endif
3431 :
3432 : IF ("r" == "l" .AND. real_4 == int_8) THEN
3433 : CPABORT("Maximal location not available with long integers @ "//routineN)
3434 : END IF
3435 0 : CALL mp_timeset(routineN, handle)
3436 :
3437 : #if defined(__parallel)
3438 0 : msglen = SIZE(msg)
3439 0 : ALLOCATE (res(1:msglen))
3440 0 : CALL mpi_allreduce(msg, res, msglen/2, MPI_2REAL, MPI_MAXLOC, comm%handle, ierr)
3441 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3442 0 : msg = res
3443 0 : DEALLOCATE (res)
3444 0 : CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
3445 : #else
3446 : MARK_USED(msg)
3447 : MARK_USED(comm)
3448 : #endif
3449 0 : CALL mp_timestop(handle)
3450 0 : END SUBROUTINE mp_maxloc_rv
3451 :
3452 : ! **************************************************************************************************
3453 : !> \brief Logical OR reduction
3454 : !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3455 : !> and resultant inclusive disjunction (output)
3456 : !> \param[in] comm Message passing environment identifier
3457 : !> \par MPI mapping
3458 : !> mpi_allreduce
3459 : ! **************************************************************************************************
3460 58902 : SUBROUTINE mp_sum_b(msg, comm)
3461 : LOGICAL, INTENT(INOUT) :: msg
3462 : CLASS(mp_comm_type), INTENT(IN) :: comm
3463 :
3464 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_sum_b'
3465 :
3466 : INTEGER :: handle
3467 : #if defined(__parallel)
3468 : INTEGER :: ierr, msglen
3469 : #endif
3470 :
3471 58902 : CALL mp_timeset(routineN, handle)
3472 : #if defined(__parallel)
3473 58902 : msglen = 1
3474 58902 : IF (comm%num_pe > 1) THEN
3475 3730 : CALL mpi_allreduce(MPI_IN_PLACE, msg, msglen, MPI_LOGICAL, MPI_LOR, comm%handle, ierr)
3476 3730 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3477 : END IF
3478 : #else
3479 : MARK_USED(msg)
3480 : MARK_USED(comm)
3481 : #endif
3482 58902 : CALL mp_timestop(handle)
3483 58902 : END SUBROUTINE mp_sum_b
3484 :
3485 : ! **************************************************************************************************
3486 : !> \brief Logical OR reduction
3487 : !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3488 : !> and resultant inclusive disjunction (output)
3489 : !> \param[in] comm Message passing environment identifier
3490 : !> \par MPI mapping
3491 : !> mpi_allreduce
3492 : ! **************************************************************************************************
3493 0 : SUBROUTINE mp_sum_bv(msg, comm)
3494 : LOGICAL, DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: msg
3495 : CLASS(mp_comm_type), INTENT(IN) :: comm
3496 :
3497 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_sum_bv'
3498 :
3499 : INTEGER :: handle
3500 : #if defined(__parallel)
3501 : INTEGER :: ierr, msglen
3502 : #endif
3503 :
3504 0 : CALL mp_timeset(routineN, handle)
3505 : #if defined(__parallel)
3506 0 : msglen = SIZE(msg)
3507 0 : IF (msglen > 0 .AND. comm%num_pe > 1) THEN
3508 0 : CALL mpi_allreduce(MPI_IN_PLACE, msg, msglen, MPI_LOGICAL, MPI_LOR, comm%handle, ierr)
3509 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3510 : END IF
3511 : #else
3512 : MARK_USED(msg)
3513 : MARK_USED(comm)
3514 : #endif
3515 0 : CALL mp_timestop(handle)
3516 0 : END SUBROUTINE mp_sum_bv
3517 :
3518 : ! **************************************************************************************************
3519 : !> \brief Logical OR reduction
3520 : !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3521 : !> and resultant inclusive disjunction (output)
3522 : !> \param[in] comm Message passing environment identifier
3523 : !> \param request ...
3524 : !> \par MPI mapping
3525 : !> mpi_allreduce
3526 : ! **************************************************************************************************
3527 0 : SUBROUTINE mp_isum_bv(msg, comm, request)
3528 : LOGICAL, DIMENSION(:), INTENT(INOUT) :: msg
3529 : CLASS(mp_comm_type), INTENT(IN) :: comm
3530 : TYPE(mp_request_type), INTENT(INOUT) :: request
3531 :
3532 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_isum_bv'
3533 :
3534 : INTEGER :: handle
3535 : #if defined(__parallel)
3536 : INTEGER :: ierr, msglen
3537 : #endif
3538 :
3539 0 : CALL mp_timeset(routineN, handle)
3540 : #if defined(__parallel)
3541 0 : msglen = SIZE(msg)
3542 : #if !defined(__GNUC__) || __GNUC__ >= 9
3543 0 : CPASSERT(IS_CONTIGUOUS(msg) .OR. PRODUCT(SHAPE(msg)) == 0)
3544 : #endif
3545 :
3546 0 : IF (msglen > 0 .AND. comm%num_pe > 1) THEN
3547 0 : CALL mpi_iallreduce(MPI_IN_PLACE, msg, msglen, MPI_LOGICAL, MPI_LOR, comm%handle, request%handle, ierr)
3548 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routineN)
3549 : ELSE
3550 0 : request = mp_request_null
3551 : END IF
3552 : #else
3553 : MARK_USED(msg)
3554 : MARK_USED(comm)
3555 : request = mp_request_null
3556 : #endif
3557 0 : CALL mp_timestop(handle)
3558 0 : END SUBROUTINE mp_isum_bv
3559 :
3560 : ! **************************************************************************************************
3561 : !> \brief Get Version of the MPI Library (MPI 3)
3562 : !> \param[out] version Version of the library,
3563 : !> declared as CHARACTER(LEN=mp_max_library_version_string)
3564 : !> \param[out] resultlen Length (in printable characters) of
3565 : !> the result returned in version (integer)
3566 : ! **************************************************************************************************
3567 0 : SUBROUTINE mp_get_library_version(version, resultlen)
3568 : CHARACTER(len=*), INTENT(OUT) :: version
3569 : INTEGER, INTENT(OUT) :: resultlen
3570 :
3571 : #if defined(__parallel)
3572 : INTEGER :: ierr
3573 : #endif
3574 :
3575 0 : version = ''
3576 :
3577 : #if defined(__parallel)
3578 : ierr = 0
3579 0 : CALL mpi_get_library_version(version, resultlen, ierr)
3580 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_get_library_version @ mp_get_library_version")
3581 : #else
3582 : resultlen = 0
3583 : #endif
3584 0 : END SUBROUTINE mp_get_library_version
3585 :
3586 : ! **************************************************************************************************
3587 : !> \brief Opens a file
3588 : !> \param[in] groupid message passing environment identifier
3589 : !> \param[out] fh file handle (file storage unit)
3590 : !> \param[in] filepath path to the file
3591 : !> \param amode_status access mode
3592 : !> \param info ...
3593 : !> \par MPI-I/O mapping mpi_file_open
3594 : !> \par STREAM-I/O mapping OPEN
3595 : !>
3596 : !> \param[in](optional) info info object
3597 : !> \par History
3598 : !> 11.2012 created [Hossein Bani-Hashemian]
3599 : ! **************************************************************************************************
3600 2062 : SUBROUTINE mp_file_open(groupid, fh, filepath, amode_status, info)
3601 : CLASS(mp_comm_type), INTENT(IN) :: groupid
3602 : CLASS(mp_file_type), INTENT(OUT) :: fh
3603 : CHARACTER(len=*), INTENT(IN) :: filepath
3604 : INTEGER, INTENT(IN) :: amode_status
3605 : TYPE(mp_info_type), INTENT(IN), OPTIONAL :: info
3606 :
3607 : #if defined(__parallel)
3608 : INTEGER :: ierr
3609 : MPI_INFO_TYPE :: my_info
3610 : #else
3611 : CHARACTER(LEN=10) :: fstatus, fposition
3612 : INTEGER :: amode, handle, istat
3613 : LOGICAL :: exists, is_open
3614 : #endif
3615 :
3616 : #if defined(__parallel)
3617 : ierr = 0
3618 2062 : my_info = mpi_info_null
3619 2062 : IF (PRESENT(info)) my_info = info%handle
3620 2062 : CALL mpi_file_open(groupid%handle, filepath, amode_status, my_info, fh%handle, ierr)
3621 2062 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
3622 2062 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_open")
3623 : #else
3624 : MARK_USED(groupid)
3625 : MARK_USED(info)
3626 : amode = amode_status
3627 : IF (amode > file_amode_append) THEN
3628 : fposition = "APPEND"
3629 : amode = amode - file_amode_append
3630 : ELSE
3631 : fposition = "REWIND"
3632 : END IF
3633 : IF ((amode == file_amode_create) .OR. &
3634 : (amode == file_amode_create + file_amode_wronly) .OR. &
3635 : (amode == file_amode_create + file_amode_wronly + file_amode_excl)) THEN
3636 : fstatus = "UNKNOWN"
3637 : ELSE
3638 : fstatus = "OLD"
3639 : END IF
3640 : ! Get a new unit number
3641 : DO handle = 1, 999
3642 : INQUIRE (UNIT=handle, EXIST=exists, OPENED=is_open, IOSTAT=istat)
3643 : IF (exists .AND. (.NOT. is_open) .AND. (istat == 0)) EXIT
3644 : END DO
3645 : OPEN (UNIT=handle, FILE=filepath, STATUS=fstatus, ACCESS="STREAM", POSITION=fposition)
3646 : fh%handle = handle
3647 : #endif
3648 2062 : END SUBROUTINE mp_file_open
3649 :
3650 : ! **************************************************************************************************
3651 : !> \brief Deletes a file. Auxiliary routine to emulate 'replace' action for mp_file_open.
3652 : !> Only the master processor should call this routine.
3653 : !> \param[in] filepath path to the file
3654 : !> \param[in](optional) info info object
3655 : !> \par History
3656 : !> 11.2017 created [Nico Holmberg]
3657 : ! **************************************************************************************************
3658 162 : SUBROUTINE mp_file_delete(filepath, info)
3659 : CHARACTER(len=*), INTENT(IN) :: filepath
3660 : TYPE(mp_info_type), INTENT(IN), OPTIONAL :: info
3661 :
3662 : #if defined(__parallel)
3663 : INTEGER :: ierr
3664 : MPI_INFO_TYPE :: my_info
3665 : LOGICAL :: exists
3666 :
3667 162 : ierr = 0
3668 162 : my_info = mpi_info_null
3669 162 : IF (PRESENT(info)) my_info = info%handle
3670 162 : INQUIRE (FILE=filepath, EXIST=exists)
3671 162 : IF (exists) CALL mpi_file_delete(filepath, my_info, ierr)
3672 162 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_delete")
3673 : #else
3674 : MARK_USED(filepath)
3675 : MARK_USED(info)
3676 : ! Explicit file delete not necessary, handled by subsequent call to open_file with action 'replace'
3677 : #endif
3678 :
3679 162 : END SUBROUTINE mp_file_delete
3680 :
3681 : ! **************************************************************************************************
3682 : !> \brief Closes a file
3683 : !> \param[in] fh file handle (file storage unit)
3684 : !> \par MPI-I/O mapping mpi_file_close
3685 : !> \par STREAM-I/O mapping CLOSE
3686 : !>
3687 : !> \par History
3688 : !> 11.2012 created [Hossein Bani-Hashemian]
3689 : ! **************************************************************************************************
3690 4124 : SUBROUTINE mp_file_close(fh)
3691 : CLASS(mp_file_type), INTENT(INOUT) :: fh
3692 :
3693 : #if defined(__parallel)
3694 : INTEGER :: ierr
3695 :
3696 : ierr = 0
3697 2062 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
3698 2062 : CALL mpi_file_close(fh%handle, ierr)
3699 2062 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_close")
3700 : #else
3701 : CLOSE (fh%handle)
3702 : fh%handle = mp_file_null_handle
3703 : #endif
3704 2062 : END SUBROUTINE mp_file_close
3705 :
3706 0 : SUBROUTINE mp_file_assign(fh_new, fh_old)
3707 : CLASS(mp_file_type), INTENT(OUT) :: fh_new
3708 : CLASS(mp_file_type), INTENT(IN) :: fh_old
3709 :
3710 0 : fh_new%handle = fh_old%handle
3711 :
3712 0 : END SUBROUTINE
3713 :
3714 : ! **************************************************************************************************
3715 : !> \brief Returns the file size
3716 : !> \param[in] fh file handle (file storage unit)
3717 : !> \param[out] file_size the file size
3718 : !> \par MPI-I/O mapping mpi_file_get_size
3719 : !> \par STREAM-I/O mapping INQUIRE
3720 : !>
3721 : !> \par History
3722 : !> 12.2012 created [Hossein Bani-Hashemian]
3723 : ! **************************************************************************************************
3724 0 : SUBROUTINE mp_file_get_size(fh, file_size)
3725 : CLASS(mp_file_type), INTENT(IN) :: fh
3726 : INTEGER(kind=file_offset), INTENT(OUT) :: file_size
3727 :
3728 : #if defined(__parallel)
3729 : INTEGER :: ierr
3730 : #endif
3731 :
3732 : #if defined(__parallel)
3733 : ierr = 0
3734 0 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
3735 0 : CALL mpi_file_get_size(fh%handle, file_size, ierr)
3736 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_get_size")
3737 : #else
3738 : INQUIRE (UNIT=fh%handle, SIZE=file_size)
3739 : #endif
3740 0 : END SUBROUTINE mp_file_get_size
3741 :
3742 : ! **************************************************************************************************
3743 : !> \brief Returns the file position
3744 : !> \param[in] fh file handle (file storage unit)
3745 : !> \param[out] file_size the file position
3746 : !> \par MPI-I/O mapping mpi_file_get_position
3747 : !> \par STREAM-I/O mapping INQUIRE
3748 : !>
3749 : !> \par History
3750 : !> 11.2017 created [Nico Holmberg]
3751 : ! **************************************************************************************************
3752 4040 : SUBROUTINE mp_file_get_position(fh, pos)
3753 : CLASS(mp_file_type), INTENT(IN) :: fh
3754 : INTEGER(kind=file_offset), INTENT(OUT) :: pos
3755 :
3756 : #if defined(__parallel)
3757 : INTEGER :: ierr
3758 : #endif
3759 :
3760 : #if defined(__parallel)
3761 : ierr = 0
3762 2020 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
3763 2020 : CALL mpi_file_get_position(fh%handle, pos, ierr)
3764 2020 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_get_position")
3765 : #else
3766 : INQUIRE (UNIT=fh%handle, POS=pos)
3767 : #endif
3768 2020 : END SUBROUTINE mp_file_get_position
3769 :
3770 : ! **************************************************************************************************
3771 : !> \brief (parallel) Blocking individual file write using explicit offsets
3772 : !> (serial) Unformatted stream write
3773 : !> \param[in] fh file handle (file storage unit)
3774 : !> \param[in] offset file offset (position)
3775 : !> \param[in] msg data to be written to the file
3776 : !> \param msglen ...
3777 : !> \par MPI-I/O mapping mpi_file_write_at
3778 : !> \par STREAM-I/O mapping WRITE
3779 : !> \param[in](optional) msglen number of the elements of data
3780 : ! **************************************************************************************************
3781 0 : SUBROUTINE mp_file_write_at_chv(fh, offset, msg, msglen)
3782 : CHARACTER, CONTIGUOUS, INTENT(IN) :: msg(:)
3783 : CLASS(mp_file_type), INTENT(IN) :: fh
3784 : INTEGER, INTENT(IN), OPTIONAL :: msglen
3785 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3786 :
3787 : #if defined(__parallel)
3788 : INTEGER :: ierr, msg_len
3789 : #endif
3790 :
3791 : #if defined(__parallel)
3792 0 : msg_len = SIZE(msg)
3793 0 : IF (PRESENT(msglen)) msg_len = msglen
3794 0 : CALL MPI_FILE_WRITE_AT(fh%handle, offset, msg, msg_len, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3795 0 : IF (ierr /= 0) &
3796 0 : CPABORT("mpi_file_write_at_chv @ mp_file_write_at_chv")
3797 : #else
3798 : MARK_USED(msglen)
3799 : WRITE (UNIT=fh%handle, POS=offset + 1) msg
3800 : #endif
3801 0 : END SUBROUTINE mp_file_write_at_chv
3802 :
3803 : ! **************************************************************************************************
3804 : !> \brief ...
3805 : !> \param fh ...
3806 : !> \param offset ...
3807 : !> \param msg ...
3808 : ! **************************************************************************************************
3809 9581 : SUBROUTINE mp_file_write_at_ch(fh, offset, msg)
3810 : CHARACTER(LEN=*), INTENT(IN) :: msg
3811 : CLASS(mp_file_type), INTENT(IN) :: fh
3812 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3813 :
3814 : #if defined(__parallel)
3815 : INTEGER :: ierr
3816 : #endif
3817 :
3818 : #if defined(__parallel)
3819 9581 : CALL MPI_FILE_WRITE_AT(fh%handle, offset, msg, LEN(msg), MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3820 9581 : IF (ierr /= 0) &
3821 0 : CPABORT("mpi_file_write_at_ch @ mp_file_write_at_ch")
3822 : #else
3823 : WRITE (UNIT=fh%handle, POS=offset + 1) msg
3824 : #endif
3825 9581 : END SUBROUTINE mp_file_write_at_ch
3826 :
3827 : ! **************************************************************************************************
3828 : !> \brief (parallel) Blocking collective file write using explicit offsets
3829 : !> (serial) Unformatted stream write
3830 : !> \param fh ...
3831 : !> \param offset ...
3832 : !> \param msg ...
3833 : !> \param msglen ...
3834 : !> \par MPI-I/O mapping mpi_file_write_at_all
3835 : !> \par STREAM-I/O mapping WRITE
3836 : ! **************************************************************************************************
3837 0 : SUBROUTINE mp_file_write_at_all_chv(fh, offset, msg, msglen)
3838 : CHARACTER, CONTIGUOUS, INTENT(IN) :: msg(:)
3839 : CLASS(mp_file_type), INTENT(IN) :: fh
3840 : INTEGER, INTENT(IN), OPTIONAL :: msglen
3841 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3842 :
3843 : #if defined(__parallel)
3844 : INTEGER :: ierr, msg_len
3845 : #endif
3846 :
3847 : #if defined(__parallel)
3848 0 : msg_len = SIZE(msg)
3849 0 : IF (PRESENT(msglen)) msg_len = msglen
3850 0 : CALL MPI_FILE_WRITE_AT_ALL(fh%handle, offset, msg, msg_len, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3851 0 : IF (ierr /= 0) &
3852 0 : CPABORT("mpi_file_write_at_all_chv @ mp_file_write_at_all_chv")
3853 : #else
3854 : MARK_USED(msglen)
3855 : WRITE (UNIT=fh%handle, POS=offset + 1) msg
3856 : #endif
3857 0 : END SUBROUTINE mp_file_write_at_all_chv
3858 :
3859 : ! **************************************************************************************************
3860 : !> \brief wrapper to MPI_File_write_at_all
3861 : !> \param fh ...
3862 : !> \param offset ...
3863 : !> \param msg ...
3864 : ! **************************************************************************************************
3865 0 : SUBROUTINE mp_file_write_at_all_ch(fh, offset, msg)
3866 : CHARACTER(LEN=*), INTENT(IN) :: msg
3867 : CLASS(mp_file_type), INTENT(IN) :: fh
3868 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3869 :
3870 : #if defined(__parallel)
3871 : INTEGER :: ierr
3872 : #endif
3873 :
3874 : #if defined(__parallel)
3875 0 : CALL MPI_FILE_WRITE_AT_ALL(fh%handle, offset, msg, LEN(msg), MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3876 0 : IF (ierr /= 0) &
3877 0 : CPABORT("mpi_file_write_at_all_ch @ mp_file_write_at_all_ch")
3878 : #else
3879 : WRITE (UNIT=fh%handle, POS=offset + 1) msg
3880 : #endif
3881 0 : END SUBROUTINE mp_file_write_at_all_ch
3882 :
3883 : ! **************************************************************************************************
3884 : !> \brief (parallel) Blocking individual file read using explicit offsets
3885 : !> (serial) Unformatted stream read
3886 : !> \param[in] fh file handle (file storage unit)
3887 : !> \param[in] offset file offset (position)
3888 : !> \param[out] msg data to be read from the file
3889 : !> \param msglen ...
3890 : !> \par MPI-I/O mapping mpi_file_read_at
3891 : !> \par STREAM-I/O mapping READ
3892 : !> \param[in](optional) msglen number of elements of data
3893 : ! **************************************************************************************************
3894 0 : SUBROUTINE mp_file_read_at_chv(fh, offset, msg, msglen)
3895 : CHARACTER, CONTIGUOUS, INTENT(OUT) :: msg(:)
3896 : CLASS(mp_file_type), INTENT(IN) :: fh
3897 : INTEGER, INTENT(IN), OPTIONAL :: msglen
3898 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3899 :
3900 : #if defined(__parallel)
3901 : INTEGER :: ierr, msg_len
3902 : #endif
3903 :
3904 : #if defined(__parallel)
3905 0 : msg_len = SIZE(msg)
3906 0 : IF (PRESENT(msglen)) msg_len = msglen
3907 0 : CALL MPI_FILE_READ_AT(fh%handle, offset, msg, msg_len, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3908 0 : IF (ierr /= 0) &
3909 0 : CPABORT("mpi_file_read_at_chv @ mp_file_read_at_chv")
3910 : #else
3911 : MARK_USED(msglen)
3912 : READ (UNIT=fh%handle, POS=offset + 1) msg
3913 : #endif
3914 0 : END SUBROUTINE mp_file_read_at_chv
3915 :
3916 : ! **************************************************************************************************
3917 : !> \brief wrapper to MPI_File_read_at
3918 : !> \param fh ...
3919 : !> \param offset ...
3920 : !> \param msg ...
3921 : ! **************************************************************************************************
3922 0 : SUBROUTINE mp_file_read_at_ch(fh, offset, msg)
3923 : CHARACTER(LEN=*), INTENT(OUT) :: msg
3924 : CLASS(mp_file_type), INTENT(IN) :: fh
3925 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3926 :
3927 : #if defined(__parallel)
3928 : INTEGER :: ierr
3929 : #endif
3930 :
3931 : #if defined(__parallel)
3932 0 : CALL MPI_FILE_READ_AT(fh%handle, offset, msg, LEN(msg), MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3933 0 : IF (ierr /= 0) &
3934 0 : CPABORT("mpi_file_read_at_ch @ mp_file_read_at_ch")
3935 : #else
3936 : READ (UNIT=fh%handle, POS=offset + 1) msg
3937 : #endif
3938 0 : END SUBROUTINE mp_file_read_at_ch
3939 :
3940 : ! **************************************************************************************************
3941 : !> \brief (parallel) Blocking collective file read using explicit offsets
3942 : !> (serial) Unformatted stream read
3943 : !> \param fh ...
3944 : !> \param offset ...
3945 : !> \param msg ...
3946 : !> \param msglen ...
3947 : !> \par MPI-I/O mapping mpi_file_read_at_all
3948 : !> \par STREAM-I/O mapping READ
3949 : ! **************************************************************************************************
3950 0 : SUBROUTINE mp_file_read_at_all_chv(fh, offset, msg, msglen)
3951 : CHARACTER, INTENT(OUT) :: msg(:)
3952 : CLASS(mp_file_type), INTENT(IN) :: fh
3953 : INTEGER, INTENT(IN), OPTIONAL :: msglen
3954 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3955 :
3956 : #if defined(__parallel)
3957 : INTEGER :: ierr, msg_len
3958 : #endif
3959 :
3960 : #if defined(__parallel)
3961 0 : msg_len = SIZE(msg)
3962 0 : IF (PRESENT(msglen)) msg_len = msglen
3963 0 : CALL MPI_FILE_READ_AT_ALL(fh%handle, offset, msg, msg_len, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3964 0 : IF (ierr /= 0) &
3965 0 : CPABORT("mpi_file_read_at_all_chv @ mp_file_read_at_all_chv")
3966 : #else
3967 : MARK_USED(msglen)
3968 : READ (UNIT=fh%handle, POS=offset + 1) msg
3969 : #endif
3970 0 : END SUBROUTINE mp_file_read_at_all_chv
3971 :
3972 : ! **************************************************************************************************
3973 : !> \brief wrapper to MPI_File_read_at_all
3974 : !> \param fh ...
3975 : !> \param offset ...
3976 : !> \param msg ...
3977 : ! **************************************************************************************************
3978 0 : SUBROUTINE mp_file_read_at_all_ch(fh, offset, msg)
3979 : CHARACTER(LEN=*), INTENT(OUT) :: msg
3980 : CLASS(mp_file_type), INTENT(IN) :: fh
3981 : INTEGER(kind=file_offset), INTENT(IN) :: offset
3982 :
3983 : #if defined(__parallel)
3984 : INTEGER :: ierr
3985 : #endif
3986 :
3987 : #if defined(__parallel)
3988 0 : CALL MPI_FILE_READ_AT_ALL(fh%handle, offset, msg, LEN(msg), MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
3989 0 : IF (ierr /= 0) &
3990 0 : CPABORT("mpi_file_read_at_all_ch @ mp_file_read_at_all_ch")
3991 : #else
3992 : READ (UNIT=fh%handle, POS=offset + 1) msg
3993 : #endif
3994 0 : END SUBROUTINE mp_file_read_at_all_ch
3995 :
3996 : ! **************************************************************************************************
3997 : !> \brief Returns the size of a data type in bytes
3998 : !> \param[in] type_descriptor data type
3999 : !> \param[out] type_size size of the data type
4000 : !> \par MPI mapping
4001 : !> mpi_type_size
4002 : !>
4003 : ! **************************************************************************************************
4004 0 : SUBROUTINE mp_type_size(type_descriptor, type_size)
4005 : TYPE(mp_type_descriptor_type), INTENT(IN) :: type_descriptor
4006 : INTEGER, INTENT(OUT) :: type_size
4007 :
4008 : #if defined(__parallel)
4009 : INTEGER :: ierr
4010 :
4011 : ierr = 0
4012 0 : CALL MPI_TYPE_SIZE(type_descriptor%type_handle, type_size, ierr)
4013 0 : IF (ierr /= 0) &
4014 0 : CPABORT("mpi_type_size failed @ mp_type_size")
4015 : #else
4016 : SELECT CASE (type_descriptor%type_handle)
4017 : CASE (1)
4018 : type_size = real_4_size
4019 : CASE (3)
4020 : type_size = real_8_size
4021 : CASE (5)
4022 : type_size = 2*real_4_size
4023 : CASE (7)
4024 : type_size = 2*real_8_size
4025 : END SELECT
4026 : #endif
4027 0 : END SUBROUTINE mp_type_size
4028 :
4029 : ! **************************************************************************************************
4030 : !> \brief wrapper to MPI_Type_create_struct
4031 : !> \param subtypes ...
4032 : !> \param vector_descriptor ...
4033 : !> \param index_descriptor ...
4034 : !> \return ...
4035 : ! **************************************************************************************************
4036 0 : FUNCTION mp_type_make_struct(subtypes, &
4037 : vector_descriptor, index_descriptor) &
4038 0 : RESULT(type_descriptor)
4039 : TYPE(mp_type_descriptor_type), &
4040 : DIMENSION(:), INTENT(IN) :: subtypes
4041 : INTEGER, DIMENSION(2), INTENT(IN), &
4042 : OPTIONAL :: vector_descriptor
4043 : TYPE(mp_indexing_meta_type), &
4044 : INTENT(IN), OPTIONAL :: index_descriptor
4045 : TYPE(mp_type_descriptor_type) :: type_descriptor
4046 :
4047 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_type_make_struct'
4048 :
4049 : INTEGER :: i, n
4050 0 : INTEGER, ALLOCATABLE, DIMENSION(:) :: lengths
4051 : #if defined(__parallel)
4052 : INTEGER :: ierr
4053 : INTEGER(kind=mpi_address_kind), &
4054 0 : ALLOCATABLE, DIMENSION(:) :: displacements
4055 : #if defined(__MPI_F08)
4056 : ! Even OpenMPI 5.x misses mpi_get_address in the F08 interface
4057 : EXTERNAL :: mpi_get_address
4058 : #endif
4059 : #endif
4060 0 : MPI_DATA_TYPE, ALLOCATABLE, DIMENSION(:) :: old_types
4061 :
4062 0 : n = SIZE(subtypes)
4063 0 : type_descriptor%length = 1
4064 : #if defined(__parallel)
4065 0 : ierr = 0
4066 0 : CALL mpi_get_address(MPI_BOTTOM, type_descriptor%base, ierr)
4067 0 : IF (ierr /= 0) &
4068 0 : CPABORT("MPI_get_address @ "//routineN)
4069 0 : ALLOCATE (displacements(n))
4070 : #endif
4071 0 : type_descriptor%vector_descriptor(1:2) = 1
4072 0 : type_descriptor%has_indexing = .FALSE.
4073 0 : ALLOCATE (type_descriptor%subtype(n))
4074 0 : type_descriptor%subtype(:) = subtypes(:)
4075 0 : ALLOCATE (lengths(n), old_types(n))
4076 0 : DO i = 1, SIZE(subtypes)
4077 : #if defined(__parallel)
4078 0 : displacements(i) = subtypes(i)%base
4079 : #endif
4080 0 : old_types(i) = subtypes(i)%type_handle
4081 0 : lengths(i) = subtypes(i)%length
4082 : END DO
4083 : #if defined(__parallel)
4084 : CALL MPI_Type_create_struct(n, &
4085 : lengths, displacements, old_types, &
4086 0 : type_descriptor%type_handle, ierr)
4087 0 : IF (ierr /= 0) &
4088 0 : CPABORT("MPI_Type_create_struct @ "//routineN)
4089 0 : CALL MPI_Type_commit(type_descriptor%type_handle, ierr)
4090 0 : IF (ierr /= 0) &
4091 0 : CPABORT("MPI_Type_commit @ "//routineN)
4092 : #endif
4093 0 : IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
4094 0 : CPABORT(routineN//" Vectors and indices NYI")
4095 : END IF
4096 0 : END FUNCTION mp_type_make_struct
4097 :
4098 : ! **************************************************************************************************
4099 : !> \brief wrapper to MPI_Type_free
4100 : !> \param type_descriptor ...
4101 : ! **************************************************************************************************
4102 0 : RECURSIVE SUBROUTINE mp_type_free_m(type_descriptor)
4103 : TYPE(mp_type_descriptor_type), INTENT(inout) :: type_descriptor
4104 :
4105 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_type_free_m'
4106 :
4107 : INTEGER :: handle, i
4108 : #if defined(__parallel)
4109 : INTEGER :: ierr
4110 : #endif
4111 :
4112 0 : CALL mp_timeset(routineN, handle)
4113 :
4114 : ! If the subtype is associated, then it's a user-defined data type.
4115 :
4116 0 : IF (ASSOCIATED(type_descriptor%subtype)) THEN
4117 0 : DO i = 1, SIZE(type_descriptor%subtype)
4118 0 : CALL mp_type_free_m(type_descriptor%subtype(i))
4119 : END DO
4120 0 : DEALLOCATE (type_descriptor%subtype)
4121 : END IF
4122 : #if defined(__parallel)
4123 : ierr = 0
4124 0 : CALL MPI_Type_free(type_descriptor%type_handle, ierr)
4125 0 : IF (ierr /= 0) &
4126 0 : CPABORT("MPI_Type_free @ "//routineN)
4127 : #endif
4128 :
4129 0 : CALL mp_timestop(handle)
4130 :
4131 0 : END SUBROUTINE mp_type_free_m
4132 :
4133 : ! **************************************************************************************************
4134 : !> \brief ...
4135 : !> \param type_descriptors ...
4136 : ! **************************************************************************************************
4137 0 : SUBROUTINE mp_type_free_v(type_descriptors)
4138 : TYPE(mp_type_descriptor_type), DIMENSION(:), &
4139 : INTENT(inout) :: type_descriptors
4140 :
4141 : INTEGER :: i
4142 :
4143 0 : DO i = 1, SIZE(type_descriptors)
4144 0 : CALL mp_type_free(type_descriptors(i))
4145 : END DO
4146 :
4147 0 : END SUBROUTINE mp_type_free_v
4148 :
4149 : ! **************************************************************************************************
4150 : !> \brief Creates an indexed MPI type for arrays of strings using bytes for spacing (hindexed type)
4151 : !> \param count number of array blocks to read
4152 : !> \param lengths lengths of each array block
4153 : !> \param displs byte offsets for array blocks
4154 : !> \return container holding the created type
4155 : !> \author Nico Holmberg [05.2017]
4156 : ! **************************************************************************************************
4157 4124 : FUNCTION mp_file_type_hindexed_make_chv(count, lengths, displs) &
4158 : RESULT(type_descriptor)
4159 : INTEGER, INTENT(IN) :: count
4160 : INTEGER, DIMENSION(1:count), &
4161 : INTENT(IN), TARGET :: lengths
4162 : INTEGER(kind=file_offset), &
4163 : DIMENSION(1:count), INTENT(in), TARGET :: displs
4164 : TYPE(mp_file_descriptor_type) :: type_descriptor
4165 :
4166 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_file_hindexed_make_chv'
4167 :
4168 : INTEGER :: ierr, handle
4169 :
4170 : ierr = 0
4171 2062 : CALL mp_timeset(routineN, handle)
4172 :
4173 : #if defined(__parallel)
4174 : CALL MPI_Type_create_hindexed(count, lengths, INT(displs, KIND=address_kind), MPI_CHARACTER, &
4175 416904 : type_descriptor%type_handle, ierr)
4176 2062 : IF (ierr /= 0) &
4177 0 : CPABORT("MPI_Type_create_hindexed @ "//routineN)
4178 2062 : CALL MPI_Type_commit(type_descriptor%type_handle, ierr)
4179 2062 : IF (ierr /= 0) &
4180 0 : CPABORT("MPI_Type_commit @ "//routineN)
4181 : #else
4182 : type_descriptor%type_handle = 68
4183 : #endif
4184 2062 : type_descriptor%length = count
4185 2062 : type_descriptor%has_indexing = .TRUE.
4186 2062 : type_descriptor%index_descriptor%index => lengths
4187 2062 : type_descriptor%index_descriptor%chunks => displs
4188 :
4189 2062 : CALL mp_timestop(handle)
4190 :
4191 2062 : END FUNCTION mp_file_type_hindexed_make_chv
4192 :
4193 : ! **************************************************************************************************
4194 : !> \brief Uses a previously created indexed MPI character type to tell the MPI processes
4195 : !> how to partition (set_view) an opened file
4196 : !> \param fh the file handle associated with the input file
4197 : !> \param offset global offset determining where the relevant data begins
4198 : !> \param type_descriptor container for the MPI type
4199 : !> \author Nico Holmberg [05.2017]
4200 : ! **************************************************************************************************
4201 2062 : SUBROUTINE mp_file_type_set_view_chv(fh, offset, type_descriptor)
4202 : TYPE(mp_file_type), INTENT(IN) :: fh
4203 : INTEGER(kind=file_offset), INTENT(IN) :: offset
4204 : TYPE(mp_file_descriptor_type) :: type_descriptor
4205 :
4206 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_file_set_view_chv'
4207 :
4208 : INTEGER :: handle
4209 : #if defined(__parallel)
4210 : INTEGER :: ierr
4211 : #endif
4212 :
4213 2062 : CALL mp_timeset(routineN, handle)
4214 :
4215 : #if defined(__parallel)
4216 : ierr = 0
4217 2062 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
4218 : CALL MPI_File_set_view(fh%handle, offset, MPI_CHARACTER, &
4219 2062 : type_descriptor%type_handle, "native", MPI_INFO_NULL, ierr)
4220 2062 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_set_view")
4221 : #else
4222 : ! Uses absolute offsets stored in mp_file_descriptor_type
4223 : MARK_USED(fh)
4224 : MARK_USED(offset)
4225 : MARK_USED(type_descriptor)
4226 : #endif
4227 :
4228 2062 : CALL mp_timestop(handle)
4229 :
4230 2062 : END SUBROUTINE mp_file_type_set_view_chv
4231 :
4232 : ! **************************************************************************************************
4233 : !> \brief (parallel) Collective, blocking read of a character array from a file. File access pattern
4234 : ! determined by a previously set file view.
4235 : !> (serial) Unformatted stream read using explicit offsets
4236 : !> \param fh the file handle associated with the input file
4237 : !> \param msglen the message length of an individual vector component
4238 : !> \param ndims the number of vector components
4239 : !> \param buffer the buffer where the data is placed
4240 : !> \param type_descriptor container for the MPI type
4241 : !> \author Nico Holmberg [05.2017]
4242 : ! **************************************************************************************************
4243 42 : SUBROUTINE mp_file_read_all_chv(fh, msglen, ndims, buffer, type_descriptor)
4244 : CLASS(mp_file_type), INTENT(IN) :: fh
4245 : INTEGER, INTENT(IN) :: msglen
4246 : INTEGER, INTENT(IN) :: ndims
4247 : CHARACTER(LEN=msglen), DIMENSION(ndims), INTENT(INOUT) :: buffer
4248 : TYPE(mp_file_descriptor_type), &
4249 : INTENT(IN), OPTIONAL :: type_descriptor
4250 :
4251 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_file_read_all_chv'
4252 :
4253 : INTEGER :: handle
4254 : #if defined(__parallel)
4255 : INTEGER:: ierr
4256 : #else
4257 : INTEGER :: i
4258 : #endif
4259 :
4260 42 : CALL mp_timeset(routineN, handle)
4261 :
4262 : #if defined(__parallel)
4263 : ierr = 0
4264 : MARK_USED(type_descriptor)
4265 42 : CALL MPI_File_read_all(fh%handle, buffer, ndims*msglen, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
4266 42 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_read_all")
4267 42 : CALL add_perf(perf_id=28, count=1, msg_size=ndims*msglen)
4268 : #else
4269 : MARK_USED(msglen)
4270 : MARK_USED(ndims)
4271 : IF (.NOT. PRESENT(type_descriptor)) &
4272 : CALL cp_abort(__LOCATION__, &
4273 : "Container for mp_file_descriptor_type must be present in serial call.")
4274 : IF (.NOT. type_descriptor%has_indexing) &
4275 : CALL cp_abort(__LOCATION__, &
4276 : "File view has not been set in mp_file_descriptor_type.")
4277 : ! Use explicit offsets
4278 : DO i = 1, ndims
4279 : READ (fh%handle, POS=type_descriptor%index_descriptor%chunks(i)) buffer(i)
4280 : END DO
4281 : #endif
4282 :
4283 42 : CALL mp_timestop(handle)
4284 :
4285 42 : END SUBROUTINE mp_file_read_all_chv
4286 :
4287 : ! **************************************************************************************************
4288 : !> \brief (parallel) Collective, blocking write of a character array to a file. File access pattern
4289 : ! determined by a previously set file view.
4290 : !> (serial) Unformatted stream write using explicit offsets
4291 : !> \param fh the file handle associated with the output file
4292 : !> \param msglen the message length of an individual vector component
4293 : !> \param ndims the number of vector components
4294 : !> \param buffer the buffer where the data is placed
4295 : !> \param type_descriptor container for the MPI type
4296 : !> \author Nico Holmberg [05.2017]
4297 : ! **************************************************************************************************
4298 2020 : SUBROUTINE mp_file_write_all_chv(fh, msglen, ndims, buffer, type_descriptor)
4299 : CLASS(mp_file_type), INTENT(IN) :: fh
4300 : INTEGER, INTENT(IN) :: msglen
4301 : INTEGER, INTENT(IN) :: ndims
4302 : CHARACTER(LEN=msglen), DIMENSION(ndims), INTENT(IN) :: buffer
4303 : TYPE(mp_file_descriptor_type), &
4304 : INTENT(IN), OPTIONAL :: type_descriptor
4305 :
4306 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_file_write_all_chv'
4307 :
4308 : INTEGER :: handle
4309 : #if defined(__parallel)
4310 : INTEGER :: ierr
4311 : #else
4312 : INTEGER :: i
4313 : #endif
4314 :
4315 2020 : CALL mp_timeset(routineN, handle)
4316 :
4317 : #if defined(__parallel)
4318 : MARK_USED(type_descriptor)
4319 2020 : CALL mpi_file_set_errhandler(fh%handle, MPI_ERRORS_RETURN, ierr)
4320 2020 : CALL MPI_File_write_all(fh%handle, buffer, ndims*msglen, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
4321 2020 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_write_all")
4322 2020 : CALL add_perf(perf_id=28, count=1, msg_size=ndims*msglen)
4323 : #else
4324 : MARK_USED(msglen)
4325 : MARK_USED(ndims)
4326 : IF (.NOT. PRESENT(type_descriptor)) &
4327 : CALL cp_abort(__LOCATION__, &
4328 : "Container for mp_file_descriptor_type must be present in serial call.")
4329 : IF (.NOT. type_descriptor%has_indexing) &
4330 : CALL cp_abort(__LOCATION__, &
4331 : "File view has not been set in mp_file_descriptor_type.")
4332 : ! Use explicit offsets
4333 : DO i = 1, ndims
4334 : WRITE (fh%handle, POS=type_descriptor%index_descriptor%chunks(i)) buffer(i)
4335 : END DO
4336 : #endif
4337 :
4338 2020 : CALL mp_timestop(handle)
4339 :
4340 2020 : END SUBROUTINE mp_file_write_all_chv
4341 :
4342 : ! **************************************************************************************************
4343 : !> \brief Releases the type used for MPI I/O
4344 : !> \param type_descriptor the container for the MPI type
4345 : !> \author Nico Holmberg [05.2017]
4346 : ! **************************************************************************************************
4347 4124 : SUBROUTINE mp_file_type_free(type_descriptor)
4348 : TYPE(mp_file_descriptor_type) :: type_descriptor
4349 :
4350 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_file_type_free'
4351 :
4352 : INTEGER :: handle
4353 : #if defined(__parallel)
4354 : INTEGER :: ierr
4355 : #endif
4356 :
4357 2062 : CALL mp_timeset(routineN, handle)
4358 :
4359 : #if defined(__parallel)
4360 2062 : CALL MPI_Type_free(type_descriptor%type_handle, ierr)
4361 2062 : IF (ierr /= 0) &
4362 0 : CPABORT("MPI_Type_free @ "//routineN)
4363 : #endif
4364 : #if defined(__parallel) && defined(__MPI_F08)
4365 2062 : type_descriptor%type_handle%mpi_val = -1
4366 : #else
4367 : type_descriptor%type_handle = -1
4368 : #endif
4369 2062 : type_descriptor%length = -1
4370 2062 : IF (type_descriptor%has_indexing) THEN
4371 2062 : NULLIFY (type_descriptor%index_descriptor%index)
4372 2062 : NULLIFY (type_descriptor%index_descriptor%chunks)
4373 2062 : type_descriptor%has_indexing = .FALSE.
4374 : END IF
4375 :
4376 2062 : CALL mp_timestop(handle)
4377 :
4378 2062 : END SUBROUTINE mp_file_type_free
4379 :
4380 : ! **************************************************************************************************
4381 : !> \brief (parallel) Utility routine to determine MPI file access mode based on variables
4382 : ! that in the serial case would get passed to the intrinsic OPEN
4383 : !> (serial) No action
4384 : !> \param mpi_io flag that determines if MPI I/O will actually be used
4385 : !> \param replace flag that indicates whether file needs to be deleted prior to opening it
4386 : !> \param amode the MPI I/O access mode
4387 : !> \param form formatted or unformatted data?
4388 : !> \param action the variable that determines what to do with file
4389 : !> \param status the status flag:
4390 : !> \param position should the file be appended or rewound
4391 : !> \author Nico Holmberg [11.2017]
4392 : ! **************************************************************************************************
4393 2020 : SUBROUTINE mp_file_get_amode(mpi_io, replace, amode, form, action, status, position)
4394 : LOGICAL, INTENT(INOUT) :: mpi_io, replace
4395 : INTEGER, INTENT(OUT) :: amode
4396 : CHARACTER(len=*), INTENT(IN) :: form, action, status, position
4397 :
4398 2020 : amode = -1
4399 : #if defined(__parallel)
4400 : ! Disable mpi io for unformatted access
4401 0 : SELECT CASE (form)
4402 : CASE ("FORMATTED")
4403 : ! Do nothing
4404 : CASE ("UNFORMATTED")
4405 0 : mpi_io = .FALSE.
4406 : CASE DEFAULT
4407 2020 : CPABORT("Unknown MPI file form requested.")
4408 : END SELECT
4409 : ! Determine file access mode (limited set of allowed choices)
4410 2020 : SELECT CASE (action)
4411 : CASE ("WRITE")
4412 2020 : amode = file_amode_wronly
4413 0 : SELECT CASE (status)
4414 : CASE ("NEW")
4415 : ! Try to open new file for writing, crash if file already exists
4416 0 : amode = amode + file_amode_create + file_amode_excl
4417 : CASE ("UNKNOWN")
4418 : ! Open file for writing and create it if file does not exist
4419 1696 : amode = amode + file_amode_create
4420 76 : SELECT CASE (position)
4421 : CASE ("APPEND")
4422 : ! Append existing file
4423 76 : amode = amode + file_amode_append
4424 : CASE ("REWIND", "ASIS")
4425 : ! Do nothing
4426 : CASE DEFAULT
4427 1696 : CPABORT("Unknown MPI file position requested.")
4428 : END SELECT
4429 : CASE ("OLD")
4430 324 : SELECT CASE (position)
4431 : CASE ("APPEND")
4432 : ! Append existing file
4433 0 : amode = amode + file_amode_append
4434 : CASE ("REWIND", "ASIS")
4435 : ! Do nothing
4436 : CASE DEFAULT
4437 0 : CPABORT("Unknown MPI file position requested.")
4438 : END SELECT
4439 : CASE ("REPLACE")
4440 : ! Overwrite existing file. Must delete existing file first
4441 324 : amode = amode + file_amode_create
4442 324 : replace = .TRUE.
4443 : CASE ("SCRATCH")
4444 : ! Disable
4445 0 : mpi_io = .FALSE.
4446 : CASE DEFAULT
4447 2020 : CPABORT("Unknown MPI file status requested.")
4448 : END SELECT
4449 : CASE ("READ")
4450 0 : amode = file_amode_rdonly
4451 0 : SELECT CASE (status)
4452 : CASE ("NEW")
4453 0 : CPABORT("Cannot read from 'NEW' file.")
4454 : CASE ("REPLACE")
4455 0 : CPABORT("Illegal status 'REPLACE' for read.")
4456 : CASE ("UNKNOWN", "OLD")
4457 : ! Do nothing
4458 : CASE ("SCRATCH")
4459 : ! Disable
4460 0 : mpi_io = .FALSE.
4461 : CASE DEFAULT
4462 0 : CPABORT("Unknown MPI file status requested.")
4463 : END SELECT
4464 : CASE ("READWRITE")
4465 0 : amode = file_amode_rdwr
4466 0 : SELECT CASE (status)
4467 : CASE ("NEW")
4468 : ! Try to open new file, crash if file already exists
4469 0 : amode = amode + file_amode_create + file_amode_excl
4470 : CASE ("UNKNOWN")
4471 : ! Open file and create it if file does not exist
4472 0 : amode = amode + file_amode_create
4473 0 : SELECT CASE (position)
4474 : CASE ("APPEND")
4475 : ! Append existing file
4476 0 : amode = amode + file_amode_append
4477 : CASE ("REWIND", "ASIS")
4478 : ! Do nothing
4479 : CASE DEFAULT
4480 0 : CPABORT("Unknown MPI file position requested.")
4481 : END SELECT
4482 : CASE ("OLD")
4483 0 : SELECT CASE (position)
4484 : CASE ("APPEND")
4485 : ! Append existing file
4486 0 : amode = amode + file_amode_append
4487 : CASE ("REWIND", "ASIS")
4488 : ! Do nothing
4489 : CASE DEFAULT
4490 0 : CPABORT("Unknown MPI file position requested.")
4491 : END SELECT
4492 : CASE ("REPLACE")
4493 : ! Overwrite existing file. Must delete existing file first
4494 0 : amode = amode + file_amode_create
4495 0 : replace = .TRUE.
4496 : CASE ("SCRATCH")
4497 : ! Disable
4498 0 : mpi_io = .FALSE.
4499 : CASE DEFAULT
4500 0 : CPABORT("Unknown MPI file status requested.")
4501 : END SELECT
4502 : CASE DEFAULT
4503 2020 : CPABORT("Unknown MPI file action requested.")
4504 : END SELECT
4505 : #else
4506 : MARK_USED(replace)
4507 : MARK_USED(form)
4508 : MARK_USED(position)
4509 : MARK_USED(status)
4510 : MARK_USED(action)
4511 : mpi_io = .FALSE.
4512 : #endif
4513 :
4514 2020 : END SUBROUTINE mp_file_get_amode
4515 :
4516 : ! **************************************************************************************************
4517 : !> \brief Non-blocking send of custom type
4518 : !> \param msgin ...
4519 : !> \param dest ...
4520 : !> \param comm ...
4521 : !> \param request ...
4522 : !> \param tag ...
4523 : ! **************************************************************************************************
4524 0 : SUBROUTINE mp_isend_custom(msgin, dest, comm, request, tag)
4525 : TYPE(mp_type_descriptor_type), INTENT(IN) :: msgin
4526 : INTEGER, INTENT(IN) :: dest
4527 : CLASS(mp_comm_type), INTENT(IN) :: comm
4528 : TYPE(mp_request_type), INTENT(out) :: request
4529 : INTEGER, INTENT(in), OPTIONAL :: tag
4530 :
4531 : INTEGER :: ierr, my_tag
4532 :
4533 : ierr = 0
4534 0 : my_tag = 0
4535 :
4536 : #if defined(__parallel)
4537 0 : IF (PRESENT(tag)) my_tag = tag
4538 :
4539 : CALL mpi_isend(MPI_BOTTOM, 1, msgin%type_handle, dest, my_tag, &
4540 0 : comm%handle, request%handle, ierr)
4541 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ mp_isend_custom")
4542 : #else
4543 : MARK_USED(msgin)
4544 : MARK_USED(dest)
4545 : MARK_USED(comm)
4546 : MARK_USED(tag)
4547 : ierr = 1
4548 : request = mp_request_null
4549 : CALL mp_stop(ierr, "mp_isend called in non parallel case")
4550 : #endif
4551 0 : END SUBROUTINE mp_isend_custom
4552 :
4553 : ! **************************************************************************************************
4554 : !> \brief Non-blocking receive of vector data
4555 : !> \param msgout ...
4556 : !> \param source ...
4557 : !> \param comm ...
4558 : !> \param request ...
4559 : !> \param tag ...
4560 : ! **************************************************************************************************
4561 0 : SUBROUTINE mp_irecv_custom(msgout, source, comm, request, tag)
4562 : TYPE(mp_type_descriptor_type), INTENT(INOUT) :: msgout
4563 : INTEGER, INTENT(IN) :: source
4564 : CLASS(mp_comm_type), INTENT(IN) :: comm
4565 : TYPE(mp_request_type), INTENT(out) :: request
4566 : INTEGER, INTENT(in), OPTIONAL :: tag
4567 :
4568 : INTEGER :: ierr, my_tag
4569 :
4570 : ierr = 0
4571 0 : my_tag = 0
4572 :
4573 : #if defined(__parallel)
4574 0 : IF (PRESENT(tag)) my_tag = tag
4575 :
4576 : CALL mpi_irecv(MPI_BOTTOM, 1, msgout%type_handle, source, my_tag, &
4577 0 : comm%handle, request%handle, ierr)
4578 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ mp_irecv_custom")
4579 : #else
4580 : MARK_USED(msgout)
4581 : MARK_USED(source)
4582 : MARK_USED(comm)
4583 : MARK_USED(tag)
4584 : ierr = 1
4585 : request = mp_request_null
4586 : CPABORT("mp_irecv called in non parallel case")
4587 : #endif
4588 0 : END SUBROUTINE mp_irecv_custom
4589 :
4590 : ! **************************************************************************************************
4591 : !> \brief Window free
4592 : !> \param win ...
4593 : ! **************************************************************************************************
4594 0 : SUBROUTINE mp_win_free(win)
4595 : CLASS(mp_win_type), INTENT(INOUT) :: win
4596 :
4597 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_win_free'
4598 :
4599 : INTEGER :: handle
4600 : #if defined(__parallel)
4601 : INTEGER :: ierr
4602 : #endif
4603 :
4604 0 : CALL mp_timeset(routineN, handle)
4605 :
4606 : #if defined(__parallel)
4607 : ierr = 0
4608 0 : CALL mpi_win_free(win%handle, ierr)
4609 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_free @ "//routineN)
4610 :
4611 0 : CALL add_perf(perf_id=21, count=1)
4612 : #else
4613 : win%handle = mp_win_null_handle
4614 : #endif
4615 0 : CALL mp_timestop(handle)
4616 0 : END SUBROUTINE mp_win_free
4617 :
4618 0 : SUBROUTINE mp_win_assign(win_new, win_old)
4619 : CLASS(mp_win_type), INTENT(OUT) :: win_new
4620 : CLASS(mp_win_type), INTENT(IN) :: win_old
4621 :
4622 0 : win_new%handle = win_old%handle
4623 :
4624 0 : END SUBROUTINE mp_win_assign
4625 :
4626 : ! **************************************************************************************************
4627 : !> \brief Window flush
4628 : !> \param win ...
4629 : ! **************************************************************************************************
4630 0 : SUBROUTINE mp_win_flush_all(win)
4631 : CLASS(mp_win_type), INTENT(IN) :: win
4632 :
4633 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_win_flush_all'
4634 :
4635 : INTEGER :: handle, ierr
4636 :
4637 : ierr = 0
4638 0 : CALL mp_timeset(routineN, handle)
4639 :
4640 : #if defined(__parallel)
4641 0 : CALL mpi_win_flush_all(win%handle, ierr)
4642 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_flush_all @ "//routineN)
4643 : #else
4644 : MARK_USED(win)
4645 : #endif
4646 0 : CALL mp_timestop(handle)
4647 0 : END SUBROUTINE mp_win_flush_all
4648 :
4649 : ! **************************************************************************************************
4650 : !> \brief Window lock
4651 : !> \param win ...
4652 : ! **************************************************************************************************
4653 0 : SUBROUTINE mp_win_lock_all(win)
4654 : CLASS(mp_win_type), INTENT(IN) :: win
4655 :
4656 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_win_lock_all'
4657 :
4658 : INTEGER :: handle, ierr
4659 :
4660 : ierr = 0
4661 0 : CALL mp_timeset(routineN, handle)
4662 :
4663 : #if defined(__parallel)
4664 :
4665 0 : CALL mpi_win_lock_all(MPI_MODE_NOCHECK, win%handle, ierr)
4666 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_lock_all @ "//routineN)
4667 :
4668 0 : CALL add_perf(perf_id=19, count=1)
4669 : #else
4670 : MARK_USED(win)
4671 : #endif
4672 0 : CALL mp_timestop(handle)
4673 0 : END SUBROUTINE mp_win_lock_all
4674 :
4675 : ! **************************************************************************************************
4676 : !> \brief Window lock
4677 : !> \param win ...
4678 : ! **************************************************************************************************
4679 0 : SUBROUTINE mp_win_unlock_all(win)
4680 : CLASS(mp_win_type), INTENT(IN) :: win
4681 :
4682 : CHARACTER(len=*), PARAMETER :: routineN = 'mp_win_unlock_all'
4683 :
4684 : INTEGER :: handle, ierr
4685 :
4686 : ierr = 0
4687 0 : CALL mp_timeset(routineN, handle)
4688 :
4689 : #if defined(__parallel)
4690 :
4691 0 : CALL mpi_win_unlock_all(win%handle, ierr)
4692 0 : IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_unlock_all @ "//routineN)
4693 :
4694 0 : CALL add_perf(perf_id=19, count=1)
4695 : #else
4696 : MARK_USED(win)
4697 : #endif
4698 0 : CALL mp_timestop(handle)
4699 0 : END SUBROUTINE mp_win_unlock_all
4700 :
4701 : ! **************************************************************************************************
4702 : !> \brief Starts a timer region
4703 : !> \param routineN ...
4704 : !> \param handle ...
4705 : ! **************************************************************************************************
4706 207785409 : SUBROUTINE mp_timeset(routineN, handle)
4707 : CHARACTER(len=*), INTENT(IN) :: routineN
4708 : INTEGER, INTENT(OUT) :: handle
4709 :
4710 207785409 : IF (mp_collect_timings) &
4711 207551439 : CALL timeset(routineN, handle)
4712 207785409 : END SUBROUTINE mp_timeset
4713 :
4714 : ! **************************************************************************************************
4715 : !> \brief Ends a timer region
4716 : !> \param handle ...
4717 : ! **************************************************************************************************
4718 207785409 : SUBROUTINE mp_timestop(handle)
4719 : INTEGER, INTENT(IN) :: handle
4720 :
4721 207785409 : IF (mp_collect_timings) &
4722 207551439 : CALL timestop(handle)
4723 207785409 : END SUBROUTINE mp_timestop
4724 :
4725 : #:include 'message_passing.fypp'
4726 :
4727 93347443 : END MODULE message_passing
|