(git:34ef472)
message_passing.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 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 ! **************************************************************************************************
24  USE iso_c_binding, ONLY: c_f_pointer, &
25  c_ptr
26  USE kinds, ONLY: &
29  USE machine, ONLY: m_abort
30  USE mp_perf_env, ONLY: add_perf, &
32 
33 #include "../base/base_uses.f90"
34 
35 ! To simplify the transition between the old MPI module and the F08-style module, we introduce these constants to switch between the required handle types
36 ! Unfortunately, Fortran does not offer something like typedef in C++
37 #if defined(__parallel) && defined(__MPI_F08)
38 #define MPI_DATA_TYPE TYPE(MPI_Datatype)
39 #define MPI_COMM_TYPE TYPE(MPI_Comm)
40 #define MPI_REQUEST_TYPE TYPE(MPI_Request)
41 #define MPI_WIN_TYPE TYPE(MPI_Win)
42 #define MPI_FILE_TYPE TYPE(MPI_File)
43 #define MPI_INFO_TYPE TYPE(MPI_Info)
44 #define MPI_STATUS_TYPE TYPE(MPI_Status)
45 #define MPI_GROUP_TYPE TYPE(MPI_Group)
46 #define MPI_STATUS_EXTRACT(X) %X
47 #define MPI_GET_COMP %mpi_val
48 #else
49 #define MPI_DATA_TYPE INTEGER
50 #define MPI_COMM_TYPE INTEGER
51 #define MPI_REQUEST_TYPE INTEGER
52 #define MPI_WIN_TYPE INTEGER
53 #define MPI_FILE_TYPE INTEGER
54 #define MPI_INFO_TYPE INTEGER
55 #define MPI_STATUS_TYPE INTEGER, DIMENSION(MPI_STATUS_SIZE)
56 #define MPI_GROUP_TYPE INTEGER
57 #define MPI_STATUS_EXTRACT(X) (X)
58 #define MPI_GET_COMP
59 #endif
60 
61 #if defined(__parallel)
62 #if defined(__MPI_F08)
63  USE mpi_f08, ONLY: mpi_allgather, mpi_allgatherv, mpi_alloc_mem, mpi_allreduce, mpi_alltoall, mpi_alltoallv, mpi_bcast, &
64  mpi_cart_coords, mpi_cart_create, mpi_cart_get, mpi_cart_rank, mpi_cart_sub, mpi_dims_create, mpi_file_close, &
65  mpi_file_get_size, mpi_file_open, mpi_file_read_at_all, mpi_file_read_at, mpi_file_write_at_all, &
66  mpi_file_write_at, mpi_free_mem, mpi_gather, mpi_gatherv, mpi_get_address, mpi_group_translate_ranks, mpi_irecv, &
67  mpi_isend, mpi_recv, mpi_reduce, mpi_reduce_scatter, mpi_rget, mpi_scatter, mpi_send, &
68  mpi_sendrecv, mpi_sendrecv_replace, mpi_testany, mpi_waitall, mpi_waitany, mpi_win_create, mpi_comm_get_attr, &
69  mpi_ibcast, mpi_any_tag, mpi_any_source, mpi_address_kind, mpi_thread_serialized, mpi_errors_return, mpi_comm_world, &
70 #if defined(__dlaf)
71  mpi_thread_multiple, &
72 #endif
73  mpi_comm_self, mpi_comm_null, mpi_info_null, mpi_request_null, mpi_request, mpi_comm, mpi_group, &
74  mpi_status_ignore, mpi_info, mpi_file, mpi_success, &
75  mpi_tag_ub, mpi_host, mpi_io, mpi_wtime_is_global, mpi_logical, &
76  mpi_status, mpi_lor, mpi_2real, mpi_real, mpi_maxloc, mpi_integer8, mpi_bottom, &
77  mpi_iscatter, mpi_iscatterv, mpi_gatherv, mpi_igatherv, mpi_iallgather, &
78  mpi_iallgatherv, mpi_status, mpi_comm_type_shared, mpi_integer, mpi_minloc, mpi_2double_precision, &
79  mpi_file, mpi_minloc, mpi_integer, mpi_sum, mpi_scan, &
80  mpi_2integer, mpi_in_place, mpi_max, mpi_min, mpi_prod, mpi_iallreduce, mpi_double_precision, &
81  mpi_error_string, mpi_double_complex, mpi_complex, mpi_type_size, mpi_file_write_all, &
82  mpi_max_error_string, mpi_datatype, mpi_offset_kind, mpi_win, mpi_mode_rdonly, mpi_mode_rdwr, &
83  mpi_mode_wronly, mpi_mode_create, mpi_mode_append, mpi_mode_excl, mpi_max_library_version_string, &
84  mpi_win_null, mpi_file_null, mpi_datatype_null, mpi_character, mpi_mode_nocheck, &
85  mpi_status_size, mpi_proc_null, mpi_unequal, mpi_similar, mpi_ident, mpi_congruent
86 #else
87  USE mpi
88 #endif
89 ! subroutines: unfortunately, mpi implementations do not provide interfaces for all subroutines (problems with types and ranks explosion),
90 ! we do not quite know what is in the module, so we can not include any....
91 ! to nevertheless get checking for what is included, we use the mpi module without use clause, getting all there is
92 ! USE mpi, ONLY: mpi_allgather, mpi_allgatherv, mpi_alloc_mem, mpi_allreduce, mpi_alltoall, mpi_alltoallv, mpi_bcast,&
93 ! mpi_cart_coords, mpi_cart_create, mpi_cart_get, mpi_cart_rank, mpi_cart_sub, mpi_dims_create, mpi_file_close,&
94 ! mpi_file_get_size, mpi_file_open, mpi_file_read_at_all, mpi_file_read_at, mpi_file_write_at_all,&
95 ! mpi_file_write_at, mpi_free_mem, mpi_gather, mpi_gatherv, mpi_get_address, mpi_group_translate_ranks, mpi_irecv,&
96 ! mpi_isend, mpi_recv, mpi_reduce, mpi_reduce_scatter, mpi_rget, mpi_scatter, mpi_send,&
97 ! mpi_sendrecv, mpi_sendrecv_replace, mpi_testany, mpi_waitall, mpi_waitany, mpi_win_create
98 ! functions
99 ! USE mpi, ONLY: mpi_wtime
100 ! constants
101 ! USE mpi, ONLY: MPI_DOUBLE_PRECISION, MPI_DOUBLE_COMPLEX, MPI_REAL, MPI_COMPLEX, MPI_ANY_TAG,&
102 ! MPI_ANY_SOURCE, MPI_COMM_NULL, MPI_REQUEST_NULL, MPI_WIN_NULL, MPI_STATUS_SIZE, MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE, &
103 ! MPI_ADDRESS_KIND, MPI_OFFSET_KIND, MPI_MODE_CREATE, MPI_MODE_RDONLY, MPI_MODE_WRONLY,&
104 ! MPI_MODE_RDWR, MPI_MODE_EXCL, MPI_COMM_SELF, MPI_COMM_WORLD, MPI_THREAD_SERIALIZED,&
105 ! MPI_ERRORS_RETURN, MPI_SUCCESS, MPI_MAX_PROCESSOR_NAME, MPI_MAX_ERROR_STRING, MPI_IDENT,&
106 ! MPI_UNEQUAL, MPI_MAX, MPI_SUM, MPI_INFO_NULL, MPI_IN_PLACE, MPI_CONGRUENT, MPI_SIMILAR, MPI_MIN, MPI_SOURCE,&
107 ! MPI_TAG, MPI_INTEGER8, MPI_INTEGER, MPI_MAXLOC, MPI_2INTEGER, MPI_MINLOC, MPI_LOGICAL, MPI_2DOUBLE_PRECISION,&
108 ! MPI_LOR, MPI_CHARACTER, MPI_BOTTOM, MPI_MODE_NOCHECK, MPI_2REAL
109 #endif
110 
111  IMPLICIT NONE
112  PRIVATE
113 
114  ! parameters that might be needed
115 #if defined(__parallel)
116  LOGICAL, PARAMETER :: cp2k_is_parallel = .true.
117  INTEGER, PARAMETER, PUBLIC :: mp_any_tag = mpi_any_tag
118  INTEGER, PARAMETER, PUBLIC :: mp_any_source = mpi_any_source
119  mpi_comm_type, PARAMETER :: mp_comm_null_handle = mpi_comm_null
120  mpi_comm_type, PARAMETER :: mp_comm_self_handle = mpi_comm_self
121  mpi_comm_type, PARAMETER :: mp_comm_world_handle = mpi_comm_world
122  mpi_request_type, PARAMETER :: mp_request_null_handle = mpi_request_null
123  mpi_win_type, PARAMETER :: mp_win_null_handle = mpi_win_null
124  mpi_file_type, PARAMETER :: mp_file_null_handle = mpi_file_null
125  mpi_info_type, PARAMETER :: mp_info_null_handle = mpi_info_null
126  mpi_data_type, PARAMETER :: mp_datatype_null_handle = mpi_datatype_null
127  INTEGER, PARAMETER, PUBLIC :: mp_status_size = mpi_status_size
128  INTEGER, PARAMETER, PUBLIC :: mp_proc_null = mpi_proc_null
129  ! Set max allocatable memory by MPI to 2 GiByte
130  INTEGER(KIND=MPI_ADDRESS_KIND), PARAMETER, PRIVATE :: mp_max_memory_size = huge(int(1, kind=int_4))
131 
132  INTEGER, PARAMETER, PUBLIC :: mp_max_library_version_string = mpi_max_library_version_string
133 
134  INTEGER, PARAMETER, PUBLIC :: file_offset = mpi_offset_kind
135  INTEGER, PARAMETER, PUBLIC :: address_kind = mpi_address_kind
136  INTEGER, PARAMETER, PUBLIC :: file_amode_create = mpi_mode_create
137  INTEGER, PARAMETER, PUBLIC :: file_amode_rdonly = mpi_mode_rdonly
138  INTEGER, PARAMETER, PUBLIC :: file_amode_wronly = mpi_mode_wronly
139  INTEGER, PARAMETER, PUBLIC :: file_amode_rdwr = mpi_mode_rdwr
140  INTEGER, PARAMETER, PUBLIC :: file_amode_excl = mpi_mode_excl
141  INTEGER, PARAMETER, PUBLIC :: file_amode_append = mpi_mode_append
142 #else
143  LOGICAL, PARAMETER :: cp2k_is_parallel = .false.
144  INTEGER, PARAMETER, PUBLIC :: mp_any_tag = -1
145  INTEGER, PARAMETER, PUBLIC :: mp_any_source = -2
146  mpi_comm_type, PARAMETER :: mp_comm_null_handle = -3
147  mpi_comm_type, PARAMETER :: mp_comm_self_handle = -11
148  mpi_comm_type, PARAMETER :: mp_comm_world_handle = -12
149  mpi_request_type, PARAMETER :: mp_request_null_handle = -4
150  mpi_win_type, PARAMETER :: mp_win_null_handle = -5
151  mpi_file_type, PARAMETER :: mp_file_null_handle = -6
152  mpi_info_type, PARAMETER :: mp_info_null_handle = -7
153  mpi_data_type, PARAMETER :: mp_datatype_null_handle = -8
154  INTEGER, PARAMETER, PUBLIC :: mp_status_size = -9
155  INTEGER, PARAMETER, PUBLIC :: mp_proc_null = -10
156  INTEGER, PARAMETER, PUBLIC :: mp_max_library_version_string = 1
157 
158  INTEGER, PARAMETER, PUBLIC :: file_offset = int_8
159  INTEGER, PARAMETER, PUBLIC :: address_kind = int_8
160  INTEGER, PARAMETER, PUBLIC :: file_amode_create = 1
161  INTEGER, PARAMETER, PUBLIC :: file_amode_rdonly = 2
162  INTEGER, PARAMETER, PUBLIC :: file_amode_wronly = 4
163  INTEGER, PARAMETER, PUBLIC :: file_amode_rdwr = 8
164  INTEGER, PARAMETER, PUBLIC :: file_amode_excl = 64
165  INTEGER, PARAMETER, PUBLIC :: file_amode_append = 128
166 #endif
167 
168  ! we need to fix this to a given number (crossing fingers)
169  ! so that the serial code using Fortran stream IO and the MPI have the same sizes.
170  INTEGER, PARAMETER, PUBLIC :: mpi_character_size = 1
171  INTEGER, PARAMETER, PUBLIC :: mpi_integer_size = 4
172 
173  CHARACTER(LEN=*), PARAMETER, PRIVATE :: modulen = 'message_passing'
174 
175  ! internal reference counter used to debug communicator leaks
176  INTEGER, PRIVATE, SAVE :: debug_comm_count
177 
178  PUBLIC :: mp_comm_type
179  PUBLIC :: mp_request_type
180  PUBLIC :: mp_win_type
181  PUBLIC :: mp_file_type
182  PUBLIC :: mp_info_type
183  PUBLIC :: mp_cart_type
184 
185  PUBLIC :: mp_para_env_type, mp_para_env_p_type, mp_para_cart_type
188 
189  TYPE mp_comm_type
190  PRIVATE
191  mpi_comm_type :: handle = mp_comm_null_handle
192  ! Number of dimensions within a Cartesian topology (useful with mp_cart_type)
193  INTEGER :: ndims = 1
194  ! Meta data to the communicator
195  INTEGER, PUBLIC :: mepos = -1, source = -1, num_pe = -1
196  CONTAINS
197  ! Setters/Getters
198  PROCEDURE, pass, non_overridable :: set_handle => mp_comm_type_set_handle
199  PROCEDURE, pass, non_overridable :: get_handle => mp_comm_type_get_handle
200  ! Comparisons
201  PROCEDURE, PRIVATE, pass, non_overridable :: mp_comm_op_eq
202  PROCEDURE, PRIVATE, pass, non_overridable :: mp_comm_op_neq
203  generic, PUBLIC :: operator(.EQ.) => mp_comm_op_eq
204  generic, PUBLIC :: operator(.NE.) => mp_comm_op_neq
205  ! Communication routines
206  PROCEDURE, PRIVATE, pass(comm), non_overridable :: &
207  mp_sendrecv_i, mp_sendrecv_l, mp_sendrecv_r, mp_sendrecv_d, &
208  mp_sendrecv_c, mp_sendrecv_z, &
209  mp_sendrecv_iv, mp_sendrecv_im2, mp_sendrecv_im3, mp_sendrecv_im4, &
210  mp_sendrecv_lv, mp_sendrecv_lm2, mp_sendrecv_lm3, mp_sendrecv_lm4, &
211  mp_sendrecv_rv, mp_sendrecv_rm2, mp_sendrecv_rm3, mp_sendrecv_rm4, &
212  mp_sendrecv_dv, mp_sendrecv_dm2, mp_sendrecv_dm3, mp_sendrecv_dm4, &
213  mp_sendrecv_cv, mp_sendrecv_cm2, mp_sendrecv_cm3, mp_sendrecv_cm4, &
214  mp_sendrecv_zv, mp_sendrecv_zm2, mp_sendrecv_zm3, mp_sendrecv_zm4
215  generic, PUBLIC :: sendrecv => mp_sendrecv_i, mp_sendrecv_l, &
216  mp_sendrecv_r, mp_sendrecv_d, mp_sendrecv_c, mp_sendrecv_z, &
217  mp_sendrecv_iv, mp_sendrecv_im2, mp_sendrecv_im3, mp_sendrecv_im4, &
218  mp_sendrecv_lv, mp_sendrecv_lm2, mp_sendrecv_lm3, mp_sendrecv_lm4, &
219  mp_sendrecv_rv, mp_sendrecv_rm2, mp_sendrecv_rm3, mp_sendrecv_rm4, &
220  mp_sendrecv_dv, mp_sendrecv_dm2, mp_sendrecv_dm3, mp_sendrecv_dm4, &
221  mp_sendrecv_cv, mp_sendrecv_cm2, mp_sendrecv_cm3, mp_sendrecv_cm4, &
222  mp_sendrecv_zv, mp_sendrecv_zm2, mp_sendrecv_zm3, mp_sendrecv_zm4
223 
224  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_minloc_iv, &
225  mp_minloc_lv, mp_minloc_rv, mp_minloc_dv
226  generic, PUBLIC :: minloc => mp_minloc_iv, &
227  mp_minloc_lv, mp_minloc_rv, mp_minloc_dv
228 
229  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_maxloc_iv, &
230  mp_maxloc_lv, mp_maxloc_rv, mp_maxloc_dv
231  generic, PUBLIC :: maxloc => mp_maxloc_iv, &
232  mp_maxloc_lv, mp_maxloc_rv, mp_maxloc_dv
233 
234  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_shift_im, mp_shift_i, &
235  mp_shift_lm, mp_shift_l, mp_shift_rm, mp_shift_r, &
236  mp_shift_dm, mp_shift_d, mp_shift_cm, mp_shift_c, &
237  mp_shift_zm, mp_shift_z
238  generic, PUBLIC :: shift => mp_shift_im, mp_shift_i, &
239  mp_shift_lm, mp_shift_l, mp_shift_rm, mp_shift_r, &
240  mp_shift_dm, mp_shift_d, mp_shift_cm, mp_shift_c, &
241  mp_shift_zm, mp_shift_z
242 
243  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_bcast_i, mp_bcast_iv, mp_bcast_im, mp_bcast_i3, &
244  mp_bcast_l, mp_bcast_lv, mp_bcast_lm, mp_bcast_l3, &
245  mp_bcast_r, mp_bcast_rv, mp_bcast_rm, mp_bcast_r3, &
246  mp_bcast_d, mp_bcast_dv, mp_bcast_dm, mp_bcast_d3, &
247  mp_bcast_c, mp_bcast_cv, mp_bcast_cm, mp_bcast_c3, &
248  mp_bcast_z, mp_bcast_zv, mp_bcast_zm, mp_bcast_z3, &
249  mp_bcast_b, mp_bcast_bv, mp_bcast_av, mp_bcast_am, &
250  mp_bcast_i_src, mp_bcast_iv_src, mp_bcast_im_src, mp_bcast_i3_src, &
251  mp_bcast_l_src, mp_bcast_lv_src, mp_bcast_lm_src, mp_bcast_l3_src, &
252  mp_bcast_r_src, mp_bcast_rv_src, mp_bcast_rm_src, mp_bcast_r3_src, &
253  mp_bcast_d_src, mp_bcast_dv_src, mp_bcast_dm_src, mp_bcast_d3_src, &
254  mp_bcast_c_src, mp_bcast_cv_src, mp_bcast_cm_src, mp_bcast_c3_src, &
255  mp_bcast_z_src, mp_bcast_zv_src, mp_bcast_zm_src, mp_bcast_z3_src, &
256  mp_bcast_b_src, mp_bcast_bv_src, mp_bcast_av_src, mp_bcast_am_src
257  generic, PUBLIC :: bcast => mp_bcast_i, mp_bcast_iv, mp_bcast_im, mp_bcast_i3, &
258  mp_bcast_l, mp_bcast_lv, mp_bcast_lm, mp_bcast_l3, &
259  mp_bcast_r, mp_bcast_rv, mp_bcast_rm, mp_bcast_r3, &
260  mp_bcast_d, mp_bcast_dv, mp_bcast_dm, mp_bcast_d3, &
261  mp_bcast_c, mp_bcast_cv, mp_bcast_cm, mp_bcast_c3, &
262  mp_bcast_z, mp_bcast_zv, mp_bcast_zm, mp_bcast_z3, &
263  mp_bcast_b, mp_bcast_bv, mp_bcast_av, mp_bcast_am, &
264  mp_bcast_i_src, mp_bcast_iv_src, mp_bcast_im_src, mp_bcast_i3_src, &
265  mp_bcast_l_src, mp_bcast_lv_src, mp_bcast_lm_src, mp_bcast_l3_src, &
266  mp_bcast_r_src, mp_bcast_rv_src, mp_bcast_rm_src, mp_bcast_r3_src, &
267  mp_bcast_d_src, mp_bcast_dv_src, mp_bcast_dm_src, mp_bcast_d3_src, &
268  mp_bcast_c_src, mp_bcast_cv_src, mp_bcast_cm_src, mp_bcast_c3_src, &
269  mp_bcast_z_src, mp_bcast_zv_src, mp_bcast_zm_src, mp_bcast_z3_src, &
270  mp_bcast_b_src, mp_bcast_bv_src, mp_bcast_av_src, mp_bcast_am_src
271 
272  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_ibcast_i, mp_ibcast_iv, &
273  mp_ibcast_l, mp_ibcast_lv, mp_ibcast_r, mp_ibcast_rv, &
274  mp_ibcast_d, mp_ibcast_dv, mp_ibcast_c, mp_ibcast_cv, &
275  mp_ibcast_z, mp_ibcast_zv
276  generic, PUBLIC :: ibcast => mp_ibcast_i, mp_ibcast_iv, &
277  mp_ibcast_l, mp_ibcast_lv, mp_ibcast_r, mp_ibcast_rv, &
278  mp_ibcast_d, mp_ibcast_dv, mp_ibcast_c, mp_ibcast_cv, &
279  mp_ibcast_z, mp_ibcast_zv
280 
281  PROCEDURE, PRIVATE, pass(comm), non_overridable :: &
282  mp_sum_i, mp_sum_iv, mp_sum_im, mp_sum_im3, mp_sum_im4, &
283  mp_sum_l, mp_sum_lv, mp_sum_lm, mp_sum_lm3, mp_sum_lm4, &
284  mp_sum_r, mp_sum_rv, mp_sum_rm, mp_sum_rm3, mp_sum_rm4, &
285  mp_sum_d, mp_sum_dv, mp_sum_dm, mp_sum_dm3, mp_sum_dm4, &
286  mp_sum_c, mp_sum_cv, mp_sum_cm, mp_sum_cm3, mp_sum_cm4, &
287  mp_sum_z, mp_sum_zv, mp_sum_zm, mp_sum_zm3, mp_sum_zm4, &
288  mp_sum_root_iv, mp_sum_root_im, mp_sum_root_lv, mp_sum_root_lm, &
289  mp_sum_root_rv, mp_sum_root_rm, mp_sum_root_dv, mp_sum_root_dm, &
290  mp_sum_root_cv, mp_sum_root_cm, mp_sum_root_zv, mp_sum_root_zm, &
291  mp_sum_b, mp_sum_bv
292  generic, PUBLIC :: sum => mp_sum_i, mp_sum_iv, mp_sum_im, mp_sum_im3, mp_sum_im4, &
293  mp_sum_l, mp_sum_lv, mp_sum_lm, mp_sum_lm3, mp_sum_lm4, &
294  mp_sum_r, mp_sum_rv, mp_sum_rm, mp_sum_rm3, mp_sum_rm4, &
295  mp_sum_d, mp_sum_dv, mp_sum_dm, mp_sum_dm3, mp_sum_dm4, &
296  mp_sum_c, mp_sum_cv, mp_sum_cm, mp_sum_cm3, mp_sum_cm4, &
297  mp_sum_z, mp_sum_zv, mp_sum_zm, mp_sum_zm3, mp_sum_zm4, &
298  mp_sum_root_iv, mp_sum_root_im, mp_sum_root_lv, mp_sum_root_lm, &
299  mp_sum_root_rv, mp_sum_root_rm, mp_sum_root_dv, mp_sum_root_dm, &
300  mp_sum_root_cv, mp_sum_root_cm, mp_sum_root_zv, mp_sum_root_zm, &
301  mp_sum_b, mp_sum_bv
302 
303  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_isum_iv, &
304  mp_isum_lv, mp_isum_rv, mp_isum_dv, mp_isum_cv, &
305  mp_isum_zv, mp_isum_bv
306  generic, PUBLIC :: isum => mp_isum_iv, &
307  mp_isum_lv, mp_isum_rv, mp_isum_dv, mp_isum_cv, &
308  mp_isum_zv, mp_isum_bv
309 
310  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_sum_partial_im, &
311  mp_sum_partial_lm, mp_sum_partial_rm, mp_sum_partial_dm, &
312  mp_sum_partial_cm, mp_sum_partial_zm
313  generic, PUBLIC :: sum_partial => mp_sum_partial_im, &
314  mp_sum_partial_lm, mp_sum_partial_rm, mp_sum_partial_dm, &
315  mp_sum_partial_cm, mp_sum_partial_zm
316 
317  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_max_i, mp_max_iv, &
318  mp_max_l, mp_max_lv, mp_max_r, mp_max_rv, &
319  mp_max_d, mp_max_dv, mp_max_c, mp_max_cv, &
320  mp_max_z, mp_max_zv, mp_max_root_i, mp_max_root_l, &
321  mp_max_root_r, mp_max_root_d, mp_max_root_c, mp_max_root_z, &
322  mp_max_root_im, mp_max_root_lm, mp_max_root_rm, mp_max_root_dm, &
323  mp_max_root_cm, mp_max_root_zm
324  generic, PUBLIC :: max => mp_max_i, mp_max_iv, &
325  mp_max_l, mp_max_lv, mp_max_r, mp_max_rv, &
326  mp_max_d, mp_max_dv, mp_max_c, mp_max_cv, &
327  mp_max_z, mp_max_zv, mp_max_root_i, mp_max_root_l, &
328  mp_max_root_r, mp_max_root_d, mp_max_root_c, mp_max_root_z, &
329  mp_max_root_im, mp_max_root_lm, mp_max_root_rm, mp_max_root_dm, &
330  mp_max_root_cm, mp_max_root_zm
331 
332  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_min_i, mp_min_iv, &
333  mp_min_l, mp_min_lv, mp_min_r, mp_min_rv, &
334  mp_min_d, mp_min_dv, mp_min_c, mp_min_cv, &
335  mp_min_z, mp_min_zv
336  generic, PUBLIC :: min => mp_min_i, mp_min_iv, &
337  mp_min_l, mp_min_lv, mp_min_r, mp_min_rv, &
338  mp_min_d, mp_min_dv, mp_min_c, mp_min_cv, &
339  mp_min_z, mp_min_zv
340 
341  PROCEDURE, PUBLIC, pass(comm), non_overridable :: &
342  mp_sum_scatter_iv, mp_sum_scatter_lv, mp_sum_scatter_rv, &
343  mp_sum_scatter_dv, mp_sum_scatter_cv, mp_sum_scatter_zv
344  generic, PUBLIC :: sum_scatter => &
345  mp_sum_scatter_iv, mp_sum_scatter_lv, mp_sum_scatter_rv, &
346  mp_sum_scatter_dv, mp_sum_scatter_cv, mp_sum_scatter_zv
347 
348  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_prod_r, mp_prod_d, mp_prod_c, mp_prod_z
349  generic, PUBLIC :: prod => mp_prod_r, mp_prod_d, mp_prod_c, mp_prod_z
350 
351  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_gather_i, mp_gather_iv, mp_gather_im, &
352  mp_gather_l, mp_gather_lv, mp_gather_lm, &
353  mp_gather_r, mp_gather_rv, mp_gather_rm, &
354  mp_gather_d, mp_gather_dv, mp_gather_dm, &
355  mp_gather_c, mp_gather_cv, mp_gather_cm, &
356  mp_gather_z, mp_gather_zv, mp_gather_zm, &
357  mp_gather_i_src, mp_gather_iv_src, mp_gather_im_src, &
358  mp_gather_l_src, mp_gather_lv_src, mp_gather_lm_src, &
359  mp_gather_r_src, mp_gather_rv_src, mp_gather_rm_src, &
360  mp_gather_d_src, mp_gather_dv_src, mp_gather_dm_src, &
361  mp_gather_c_src, mp_gather_cv_src, mp_gather_cm_src, &
362  mp_gather_z_src, mp_gather_zv_src, mp_gather_zm_src
363  generic, PUBLIC :: gather => mp_gather_i, mp_gather_iv, mp_gather_im, &
364  mp_gather_l, mp_gather_lv, mp_gather_lm, &
365  mp_gather_r, mp_gather_rv, mp_gather_rm, &
366  mp_gather_d, mp_gather_dv, mp_gather_dm, &
367  mp_gather_c, mp_gather_cv, mp_gather_cm, &
368  mp_gather_z, mp_gather_zv, mp_gather_zm, &
369  mp_gather_i_src, mp_gather_iv_src, mp_gather_im_src, &
370  mp_gather_l_src, mp_gather_lv_src, mp_gather_lm_src, &
371  mp_gather_r_src, mp_gather_rv_src, mp_gather_rm_src, &
372  mp_gather_d_src, mp_gather_dv_src, mp_gather_dm_src, &
373  mp_gather_c_src, mp_gather_cv_src, mp_gather_cm_src, &
374  mp_gather_z_src, mp_gather_zv_src, mp_gather_zm_src
375 
376  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_gatherv_iv, &
377  mp_gatherv_lv, mp_gatherv_rv, mp_gatherv_dv, &
378  mp_gatherv_cv, mp_gatherv_zv, mp_gatherv_lm2, mp_gatherv_rm2, &
379  mp_gatherv_dm2, mp_gatherv_cm2, mp_gatherv_zm2, mp_gatherv_iv_src, &
380  mp_gatherv_lv_src, mp_gatherv_rv_src, mp_gatherv_dv_src, &
381  mp_gatherv_cv_src, mp_gatherv_zv_src, mp_gatherv_lm2_src, mp_gatherv_rm2_src, &
382  mp_gatherv_dm2_src, mp_gatherv_cm2_src, mp_gatherv_zm2_src
383  generic, PUBLIC :: gatherv => mp_gatherv_iv, &
384  mp_gatherv_lv, mp_gatherv_rv, mp_gatherv_dv, &
385  mp_gatherv_cv, mp_gatherv_zv, mp_gatherv_lm2, mp_gatherv_rm2, &
386  mp_gatherv_dm2, mp_gatherv_cm2, mp_gatherv_zm2, mp_gatherv_iv_src, &
387  mp_gatherv_lv_src, mp_gatherv_rv_src, mp_gatherv_dv_src, &
388  mp_gatherv_cv_src, mp_gatherv_zv_src, mp_gatherv_lm2_src, mp_gatherv_rm2_src, &
389  mp_gatherv_dm2_src, mp_gatherv_cm2_src, mp_gatherv_zm2_src
390 
391  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_igatherv_iv, &
392  mp_igatherv_lv, mp_igatherv_rv, mp_igatherv_dv, &
393  mp_igatherv_cv, mp_igatherv_zv
394  generic, PUBLIC :: igatherv => mp_igatherv_iv, &
395  mp_igatherv_lv, mp_igatherv_rv, mp_igatherv_dv, &
396  mp_igatherv_cv, mp_igatherv_zv
397 
398  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_allgather_i, mp_allgather_i2, &
399  mp_allgather_i12, mp_allgather_i23, mp_allgather_i34, &
400  mp_allgather_i22, mp_allgather_l, mp_allgather_l2, &
401  mp_allgather_l12, mp_allgather_l23, mp_allgather_l34, &
402  mp_allgather_l22, mp_allgather_r, mp_allgather_r2, &
403  mp_allgather_r12, mp_allgather_r23, mp_allgather_r34, &
404  mp_allgather_r22, mp_allgather_d, mp_allgather_d2, &
405  mp_allgather_d12, mp_allgather_d23, mp_allgather_d34, &
406  mp_allgather_d22, mp_allgather_c, mp_allgather_c2, &
407  mp_allgather_c12, mp_allgather_c23, mp_allgather_c34, &
408  mp_allgather_c22, mp_allgather_z, mp_allgather_z2, &
409  mp_allgather_z12, mp_allgather_z23, mp_allgather_z34, &
410  mp_allgather_z22
411  generic, PUBLIC :: allgather => mp_allgather_i, mp_allgather_i2, &
412  mp_allgather_i12, mp_allgather_i23, mp_allgather_i34, &
413  mp_allgather_i22, mp_allgather_l, mp_allgather_l2, &
414  mp_allgather_l12, mp_allgather_l23, mp_allgather_l34, &
415  mp_allgather_l22, mp_allgather_r, mp_allgather_r2, &
416  mp_allgather_r12, mp_allgather_r23, mp_allgather_r34, &
417  mp_allgather_r22, mp_allgather_d, mp_allgather_d2, &
418  mp_allgather_d12, mp_allgather_d23, mp_allgather_d34, &
419  mp_allgather_d22, mp_allgather_c, mp_allgather_c2, &
420  mp_allgather_c12, mp_allgather_c23, mp_allgather_c34, &
421  mp_allgather_c22, mp_allgather_z, mp_allgather_z2, &
422  mp_allgather_z12, mp_allgather_z23, mp_allgather_z34, &
423  mp_allgather_z22
424 
425  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_allgatherv_iv, mp_allgatherv_lv, &
426  mp_allgatherv_rv, mp_allgatherv_dv, mp_allgatherv_cv, mp_allgatherv_zv, &
427  mp_allgatherv_im2, mp_allgatherv_lm2, mp_allgatherv_rm2, &
428  mp_allgatherv_dm2, mp_allgatherv_cm2, mp_allgatherv_zm2
429  generic, PUBLIC :: allgatherv => mp_allgatherv_iv, mp_allgatherv_lv, &
430  mp_allgatherv_rv, mp_allgatherv_dv, mp_allgatherv_cv, mp_allgatherv_zv, &
431  mp_allgatherv_im2, mp_allgatherv_lm2, mp_allgatherv_rm2, &
432  mp_allgatherv_dm2, mp_allgatherv_cm2, mp_allgatherv_zm2
433 
434  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_iallgather_i, mp_iallgather_l, &
435  mp_iallgather_r, mp_iallgather_d, mp_iallgather_c, mp_iallgather_z, &
436  mp_iallgather_i11, mp_iallgather_l11, mp_iallgather_r11, mp_iallgather_d11, &
437  mp_iallgather_c11, mp_iallgather_z11, mp_iallgather_i13, mp_iallgather_l13, &
438  mp_iallgather_r13, mp_iallgather_d13, mp_iallgather_c13, mp_iallgather_z13, &
439  mp_iallgather_i22, mp_iallgather_l22, mp_iallgather_r22, mp_iallgather_d22, &
440  mp_iallgather_c22, mp_iallgather_z22, mp_iallgather_i24, mp_iallgather_l24, &
441  mp_iallgather_r24, mp_iallgather_d24, mp_iallgather_c24, mp_iallgather_z24, &
442  mp_iallgather_i33, mp_iallgather_l33, mp_iallgather_r33, mp_iallgather_d33, &
443  mp_iallgather_c33, mp_iallgather_z33
444  generic, PUBLIC :: iallgather => mp_iallgather_i, mp_iallgather_l, &
445  mp_iallgather_r, mp_iallgather_d, mp_iallgather_c, mp_iallgather_z, &
446  mp_iallgather_i11, mp_iallgather_l11, mp_iallgather_r11, mp_iallgather_d11, &
447  mp_iallgather_c11, mp_iallgather_z11, mp_iallgather_i13, mp_iallgather_l13, &
448  mp_iallgather_r13, mp_iallgather_d13, mp_iallgather_c13, mp_iallgather_z13, &
449  mp_iallgather_i22, mp_iallgather_l22, mp_iallgather_r22, mp_iallgather_d22, &
450  mp_iallgather_c22, mp_iallgather_z22, mp_iallgather_i24, mp_iallgather_l24, &
451  mp_iallgather_r24, mp_iallgather_d24, mp_iallgather_c24, mp_iallgather_z24, &
452  mp_iallgather_i33, mp_iallgather_l33, mp_iallgather_r33, mp_iallgather_d33, &
453  mp_iallgather_c33, mp_iallgather_z33
454 
455  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_iallgatherv_iv, mp_iallgatherv_iv2, &
456  mp_iallgatherv_lv, mp_iallgatherv_lv2, mp_iallgatherv_rv, mp_iallgatherv_rv2, &
457  mp_iallgatherv_dv, mp_iallgatherv_dv2, mp_iallgatherv_cv, mp_iallgatherv_cv2, &
458  mp_iallgatherv_zv, mp_iallgatherv_zv2
459  generic, PUBLIC :: iallgatherv => mp_iallgatherv_iv, mp_iallgatherv_iv2, &
460  mp_iallgatherv_lv, mp_iallgatherv_lv2, mp_iallgatherv_rv, mp_iallgatherv_rv2, &
461  mp_iallgatherv_dv, mp_iallgatherv_dv2, mp_iallgatherv_cv, mp_iallgatherv_cv2, &
462  mp_iallgatherv_zv, mp_iallgatherv_zv2
463 
464  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_scatter_iv, mp_scatter_lv, &
465  mp_scatter_rv, mp_scatter_dv, mp_scatter_cv, mp_scatter_zv
466  generic, PUBLIC :: scatter => mp_scatter_iv, mp_scatter_lv, &
467  mp_scatter_rv, mp_scatter_dv, mp_scatter_cv, mp_scatter_zv
468 
469  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_iscatter_i, mp_iscatter_l, &
470  mp_iscatter_r, mp_iscatter_d, mp_iscatter_c, mp_iscatter_z, &
471  mp_iscatter_iv2, mp_iscatter_lv2, mp_iscatter_rv2, mp_iscatter_dv2, &
472  mp_iscatter_cv2, mp_iscatter_zv2
473  generic, PUBLIC :: iscatter => mp_iscatter_i, mp_iscatter_l, &
474  mp_iscatter_r, mp_iscatter_d, mp_iscatter_c, mp_iscatter_z, &
475  mp_iscatter_iv2, mp_iscatter_lv2, mp_iscatter_rv2, mp_iscatter_dv2, &
476  mp_iscatter_cv2, mp_iscatter_zv2
477 
478  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_iscatterv_iv, mp_iscatterv_lv, &
479  mp_iscatterv_rv, mp_iscatterv_dv, mp_iscatterv_cv, mp_iscatterv_zv
480  generic, PUBLIC :: iscatterv => mp_iscatterv_iv, mp_iscatterv_lv, &
481  mp_iscatterv_rv, mp_iscatterv_dv, mp_iscatterv_cv, mp_iscatterv_zv
482 
483  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_alltoall_i, mp_alltoall_i22, mp_alltoall_i33, &
484  mp_alltoall_i44, mp_alltoall_i55, mp_alltoall_i45, mp_alltoall_i34, &
485  mp_alltoall_i11v, mp_alltoall_i22v, mp_alltoall_i54, &
486  mp_alltoall_l, mp_alltoall_l22, mp_alltoall_l33, &
487  mp_alltoall_l44, mp_alltoall_l55, mp_alltoall_l45, mp_alltoall_l34, &
488  mp_alltoall_l11v, mp_alltoall_l22v, mp_alltoall_l54, &
489  mp_alltoall_r, mp_alltoall_r22, mp_alltoall_r33, &
490  mp_alltoall_r44, mp_alltoall_r55, mp_alltoall_r45, mp_alltoall_r34, &
491  mp_alltoall_r11v, mp_alltoall_r22v, mp_alltoall_r54, &
492  mp_alltoall_d, mp_alltoall_d22, mp_alltoall_d33, &
493  mp_alltoall_d44, mp_alltoall_d55, mp_alltoall_d45, mp_alltoall_d34, &
494  mp_alltoall_d11v, mp_alltoall_d22v, mp_alltoall_d54, &
495  mp_alltoall_c, mp_alltoall_c22, mp_alltoall_c33, &
496  mp_alltoall_c44, mp_alltoall_c55, mp_alltoall_c45, mp_alltoall_c34, &
497  mp_alltoall_c11v, mp_alltoall_c22v, mp_alltoall_c54, &
498  mp_alltoall_z, mp_alltoall_z22, mp_alltoall_z33, &
499  mp_alltoall_z44, mp_alltoall_z55, mp_alltoall_z45, mp_alltoall_z34, &
500  mp_alltoall_z11v, mp_alltoall_z22v, mp_alltoall_z54
501  generic, PUBLIC :: alltoall => mp_alltoall_i, mp_alltoall_i22, mp_alltoall_i33, &
502  mp_alltoall_i44, mp_alltoall_i55, mp_alltoall_i45, mp_alltoall_i34, &
503  mp_alltoall_i11v, mp_alltoall_i22v, mp_alltoall_i54, &
504  mp_alltoall_l, mp_alltoall_l22, mp_alltoall_l33, &
505  mp_alltoall_l44, mp_alltoall_l55, mp_alltoall_l45, mp_alltoall_l34, &
506  mp_alltoall_l11v, mp_alltoall_l22v, mp_alltoall_l54, &
507  mp_alltoall_r, mp_alltoall_r22, mp_alltoall_r33, &
508  mp_alltoall_r44, mp_alltoall_r55, mp_alltoall_r45, mp_alltoall_r34, &
509  mp_alltoall_r11v, mp_alltoall_r22v, mp_alltoall_r54, &
510  mp_alltoall_d, mp_alltoall_d22, mp_alltoall_d33, &
511  mp_alltoall_d44, mp_alltoall_d55, mp_alltoall_d45, mp_alltoall_d34, &
512  mp_alltoall_d11v, mp_alltoall_d22v, mp_alltoall_d54, &
513  mp_alltoall_c, mp_alltoall_c22, mp_alltoall_c33, &
514  mp_alltoall_c44, mp_alltoall_c55, mp_alltoall_c45, mp_alltoall_c34, &
515  mp_alltoall_c11v, mp_alltoall_c22v, mp_alltoall_c54, &
516  mp_alltoall_z, mp_alltoall_z22, mp_alltoall_z33, &
517  mp_alltoall_z44, mp_alltoall_z55, mp_alltoall_z45, mp_alltoall_z34, &
518  mp_alltoall_z11v, mp_alltoall_z22v, mp_alltoall_z54
519 
520  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_send_i, mp_send_iv, mp_send_im2, mp_send_im3, &
521  mp_send_l, mp_send_lv, mp_send_lm2, mp_send_lm3, &
522  mp_send_r, mp_send_rv, mp_send_rm2, mp_send_rm3, &
523  mp_send_d, mp_send_dv, mp_send_dm2, mp_send_dm3, &
524  mp_send_c, mp_send_cv, mp_send_cm2, mp_send_cm3, &
525  mp_send_z, mp_send_zv, mp_send_zm2, mp_send_zm3
526  generic, PUBLIC :: send => mp_send_i, mp_send_iv, mp_send_im2, mp_send_im3, &
527  mp_send_l, mp_send_lv, mp_send_lm2, mp_send_lm3, &
528  mp_send_r, mp_send_rv, mp_send_rm2, mp_send_rm3, &
529  mp_send_d, mp_send_dv, mp_send_dm2, mp_send_dm3, &
530  mp_send_c, mp_send_cv, mp_send_cm2, mp_send_cm3, &
531  mp_send_z, mp_send_zv, mp_send_zm2, mp_send_zm3
532 
533  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_recv_i, mp_recv_iv, mp_recv_im2, mp_recv_im3, &
534  mp_recv_l, mp_recv_lv, mp_recv_lm2, mp_recv_lm3, &
535  mp_recv_r, mp_recv_rv, mp_recv_rm2, mp_recv_rm3, &
536  mp_recv_d, mp_recv_dv, mp_recv_dm2, mp_recv_dm3, &
537  mp_recv_c, mp_recv_cv, mp_recv_cm2, mp_recv_cm3, &
538  mp_recv_z, mp_recv_zv, mp_recv_zm2, mp_recv_zm3
539  generic, PUBLIC :: recv => mp_recv_i, mp_recv_iv, mp_recv_im2, mp_recv_im3, &
540  mp_recv_l, mp_recv_lv, mp_recv_lm2, mp_recv_lm3, &
541  mp_recv_r, mp_recv_rv, mp_recv_rm2, mp_recv_rm3, &
542  mp_recv_d, mp_recv_dv, mp_recv_dm2, mp_recv_dm3, &
543  mp_recv_c, mp_recv_cv, mp_recv_cm2, mp_recv_cm3, &
544  mp_recv_z, mp_recv_zv, mp_recv_zm2, mp_recv_zm3
545 
546  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_isendrecv_i, mp_isendrecv_iv, &
547  mp_isendrecv_l, mp_isendrecv_lv, mp_isendrecv_r, mp_isendrecv_rv, &
548  mp_isendrecv_d, mp_isendrecv_dv, mp_isendrecv_c, mp_isendrecv_cv, &
549  mp_isendrecv_z, mp_isendrecv_zv
550  generic, PUBLIC :: isendrecv => mp_isendrecv_i, mp_isendrecv_iv, &
551  mp_isendrecv_l, mp_isendrecv_lv, mp_isendrecv_r, mp_isendrecv_rv, &
552  mp_isendrecv_d, mp_isendrecv_dv, mp_isendrecv_c, mp_isendrecv_cv, &
553  mp_isendrecv_z, mp_isendrecv_zv
554 
555  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_isend_iv, mp_isend_im2, mp_isend_im3, mp_isend_im4, &
556  mp_isend_lv, mp_isend_lm2, mp_isend_lm3, mp_isend_lm4, &
557  mp_isend_rv, mp_isend_rm2, mp_isend_rm3, mp_isend_rm4, &
558  mp_isend_dv, mp_isend_dm2, mp_isend_dm3, mp_isend_dm4, &
559  mp_isend_cv, mp_isend_cm2, mp_isend_cm3, mp_isend_cm4, &
560  mp_isend_zv, mp_isend_zm2, mp_isend_zm3, mp_isend_zm4, &
561  mp_isend_bv, mp_isend_bm3, mp_isend_custom
562  generic, PUBLIC :: isend => mp_isend_iv, mp_isend_im2, mp_isend_im3, mp_isend_im4, &
563  mp_isend_lv, mp_isend_lm2, mp_isend_lm3, mp_isend_lm4, &
564  mp_isend_rv, mp_isend_rm2, mp_isend_rm3, mp_isend_rm4, &
565  mp_isend_dv, mp_isend_dm2, mp_isend_dm3, mp_isend_dm4, &
566  mp_isend_cv, mp_isend_cm2, mp_isend_cm3, mp_isend_cm4, &
567  mp_isend_zv, mp_isend_zm2, mp_isend_zm3, mp_isend_zm4, &
568  mp_isend_bv, mp_isend_bm3, mp_isend_custom
569 
570  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_irecv_iv, mp_irecv_im2, mp_irecv_im3, mp_irecv_im4, &
571  mp_irecv_lv, mp_irecv_lm2, mp_irecv_lm3, mp_irecv_lm4, &
572  mp_irecv_rv, mp_irecv_rm2, mp_irecv_rm3, mp_irecv_rm4, &
573  mp_irecv_dv, mp_irecv_dm2, mp_irecv_dm3, mp_irecv_dm4, &
574  mp_irecv_cv, mp_irecv_cm2, mp_irecv_cm3, mp_irecv_cm4, &
575  mp_irecv_zv, mp_irecv_zm2, mp_irecv_zm3, mp_irecv_zm4, &
576  mp_irecv_bv, mp_irecv_bm3, mp_irecv_custom
577  generic, PUBLIC :: irecv => mp_irecv_iv, mp_irecv_im2, mp_irecv_im3, mp_irecv_im4, &
578  mp_irecv_lv, mp_irecv_lm2, mp_irecv_lm3, mp_irecv_lm4, &
579  mp_irecv_rv, mp_irecv_rm2, mp_irecv_rm3, mp_irecv_rm4, &
580  mp_irecv_dv, mp_irecv_dm2, mp_irecv_dm3, mp_irecv_dm4, &
581  mp_irecv_cv, mp_irecv_cm2, mp_irecv_cm3, mp_irecv_cm4, &
582  mp_irecv_zv, mp_irecv_zm2, mp_irecv_zm3, mp_irecv_zm4, &
583  mp_irecv_bv, mp_irecv_bm3, mp_irecv_custom
584 
585  PROCEDURE, PUBLIC, pass(comm), non_overridable :: probe => mp_probe
586 
587  PROCEDURE, PUBLIC, pass(comm), non_overridable :: sync => mp_sync
588  PROCEDURE, PUBLIC, pass(comm), non_overridable :: isync => mp_isync
589 
590  PROCEDURE, PUBLIC, pass(comm1), non_overridable :: compare => mp_comm_compare
591  PROCEDURE, PUBLIC, pass(comm1), non_overridable :: rank_compare => mp_rank_compare
592 
593  PROCEDURE, PUBLIC, pass(comm2), non_overridable :: from_dup => mp_comm_dup
594  PROCEDURE, PUBLIC, pass(comm), non_overridable :: mp_comm_free
595  generic, PUBLIC :: free => mp_comm_free
596 
597  PROCEDURE, PUBLIC, pass(comm), non_overridable :: mp_comm_init
598  generic, PUBLIC :: init => mp_comm_init
599 
600  PROCEDURE, PUBLIC, pass(comm), non_overridable :: get_size => mp_comm_size
601  PROCEDURE, PUBLIC, pass(comm), non_overridable :: get_rank => mp_comm_rank
602  PROCEDURE, PUBLIC, pass(comm), non_overridable :: get_ndims => mp_comm_get_ndims
603  PROCEDURE, PUBLIC, pass(comm), non_overridable :: is_source => mp_comm_is_source
604 
605  ! Creation routines
606  PROCEDURE, PRIVATE, pass(sub_comm), non_overridable :: mp_comm_split, mp_comm_split_direct
607  generic, PUBLIC :: from_split => mp_comm_split, mp_comm_split_direct
608  PROCEDURE, PUBLIC, pass(mp_new_comm), non_overridable :: from_reordering => mp_reordering
609  PROCEDURE, PUBLIC, pass(comm_new), non_overridable :: mp_comm_assign
610  generic, PUBLIC :: ASSIGNMENT(=) => mp_comm_assign
611 
612  ! Other Getters
613  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_comm_get_tag_ub
614  generic, PUBLIC :: get_tag_ub => mp_comm_get_tag_ub
615  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_comm_get_host_rank
616  generic, PUBLIC :: get_host_rank => mp_comm_get_host_rank
617  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_comm_get_io_rank
618  generic, PUBLIC :: get_io_rank => mp_comm_get_io_rank
619  PROCEDURE, PRIVATE, pass(comm), non_overridable :: mp_comm_get_wtime_is_global
620  generic, PUBLIC :: get_wtime_is_global => mp_comm_get_wtime_is_global
621  END TYPE
622 
623  TYPE mp_request_type
624  PRIVATE
625  mpi_request_type :: handle = mp_request_null_handle
626  CONTAINS
627  PROCEDURE, PUBLIC, non_overridable :: set_handle => mp_request_type_set_handle
628  PROCEDURE, PUBLIC, non_overridable :: get_handle => mp_request_type_get_handle
629  PROCEDURE, PRIVATE, non_overridable :: mp_request_op_eq
630  PROCEDURE, PRIVATE, non_overridable :: mp_request_op_neq
631  generic, PUBLIC :: OPERATOR(.EQ.) => mp_request_op_eq
632  generic, PUBLIC :: OPERATOR(.NE.) => mp_request_op_neq
633 
634  PROCEDURE, PUBLIC, pass(request), non_overridable :: test => mp_test_1
635 
636  PROCEDURE, PUBLIC, pass(request), non_overridable :: wait => mp_wait
637  END TYPE
638 
639  TYPE mp_win_type
640  PRIVATE
641  mpi_win_type :: handle = mp_win_null_handle
642  CONTAINS
643  PROCEDURE, PUBLIC, non_overridable :: set_handle => mp_win_type_set_handle
644  PROCEDURE, PUBLIC, non_overridable :: get_handle => mp_win_type_get_handle
645  PROCEDURE, PRIVATE, non_overridable :: mp_win_op_eq
646  PROCEDURE, PRIVATE, non_overridable :: mp_win_op_neq
647  generic, PUBLIC :: OPERATOR(.EQ.) => mp_win_op_eq
648  generic, PUBLIC :: OPERATOR(.NE.) => mp_win_op_neq
649 
650  PROCEDURE, PRIVATE, pass(win), non_overridable :: mp_win_create_iv, mp_win_create_lv, &
651  mp_win_create_rv, mp_win_create_dv, mp_win_create_cv, mp_win_create_zv
652  generic, PUBLIC :: create => mp_win_create_iv, mp_win_create_lv, &
653  mp_win_create_rv, mp_win_create_dv, mp_win_create_cv, mp_win_create_zv
654 
655  PROCEDURE, PRIVATE, pass(win), non_overridable :: mp_rget_iv, mp_rget_lv, &
656  mp_rget_rv, mp_rget_dv, mp_rget_cv, mp_rget_zv
657  generic, PUBLIC :: rget => mp_rget_iv, mp_rget_lv, &
658  mp_rget_rv, mp_rget_dv, mp_rget_cv, mp_rget_zv
659 
660  PROCEDURE, PUBLIC, pass(win), non_overridable :: free => mp_win_free
661  PROCEDURE, PUBLIC, pass(win_new), non_overridable :: mp_win_assign
662  generic, PUBLIC :: ASSIGNMENT(=) => mp_win_assign
663 
664  PROCEDURE, PUBLIC, pass(win), non_overridable :: lock_all => mp_win_lock_all
665  PROCEDURE, PUBLIC, pass(win), non_overridable :: unlock_all => mp_win_unlock_all
666  PROCEDURE, PUBLIC, pass(win), non_overridable :: flush_all => mp_win_flush_all
667  END TYPE
668 
669  TYPE mp_file_type
670  PRIVATE
671  mpi_file_type :: handle = mp_file_null_handle
672  CONTAINS
673  PROCEDURE, PUBLIC, non_overridable :: set_handle => mp_file_type_set_handle
674  PROCEDURE, PUBLIC, non_overridable :: get_handle => mp_file_type_get_handle
675  PROCEDURE, PRIVATE, non_overridable :: mp_file_op_eq
676  PROCEDURE, PRIVATE, non_overridable :: mp_file_op_neq
677  generic, PUBLIC :: OPERATOR(.EQ.) => mp_file_op_eq
678  generic, PUBLIC :: OPERATOR(.NE.) => mp_file_op_neq
679 
680  PROCEDURE, PRIVATE, pass(fh), non_overridable :: mp_file_write_at_ch, mp_file_write_at_chv, &
681  mp_file_write_at_i, mp_file_write_at_iv, mp_file_write_at_r, mp_file_write_at_rv, &
682  mp_file_write_at_d, mp_file_write_at_dv, mp_file_write_at_c, mp_file_write_at_cv, &
683  mp_file_write_at_z, mp_file_write_at_zv, mp_file_write_at_l, mp_file_write_at_lv
684  generic, PUBLIC :: write_at => mp_file_write_at_ch, mp_file_write_at_chv, &
685  mp_file_write_at_i, mp_file_write_at_iv, mp_file_write_at_r, mp_file_write_at_rv, &
686  mp_file_write_at_d, mp_file_write_at_dv, mp_file_write_at_c, mp_file_write_at_cv, &
687  mp_file_write_at_z, mp_file_write_at_zv, mp_file_write_at_l, mp_file_write_at_lv
688 
689  PROCEDURE, PRIVATE, pass(fh), non_overridable :: mp_file_write_at_all_ch, mp_file_write_at_all_chv, &
690  mp_file_write_at_all_i, mp_file_write_at_all_iv, mp_file_write_at_all_l, mp_file_write_at_all_lv, &
691  mp_file_write_at_all_r, mp_file_write_at_all_rv, mp_file_write_at_all_d, mp_file_write_at_all_dv, &
692  mp_file_write_at_all_c, mp_file_write_at_all_cv, mp_file_write_at_all_z, mp_file_write_at_all_zv
693  generic, PUBLIC :: write_at_all => mp_file_write_at_all_ch, mp_file_write_at_all_chv, &
694  mp_file_write_at_all_i, mp_file_write_at_all_iv, mp_file_write_at_all_l, mp_file_write_at_all_lv, &
695  mp_file_write_at_all_r, mp_file_write_at_all_rv, mp_file_write_at_all_d, mp_file_write_at_all_dv, &
696  mp_file_write_at_all_c, mp_file_write_at_all_cv, mp_file_write_at_all_z, mp_file_write_at_all_zv
697 
698  PROCEDURE, PRIVATE, pass(fh), non_overridable :: mp_file_read_at_ch, mp_file_read_at_chv, &
699  mp_file_read_at_i, mp_file_read_at_iv, mp_file_read_at_r, mp_file_read_at_rv, &
700  mp_file_read_at_d, mp_file_read_at_dv, mp_file_read_at_c, mp_file_read_at_cv, &
701  mp_file_read_at_z, mp_file_read_at_zv, mp_file_read_at_l, mp_file_read_at_lv
702  generic, PUBLIC :: read_at => mp_file_read_at_ch, mp_file_read_at_chv, &
703  mp_file_read_at_i, mp_file_read_at_iv, mp_file_read_at_r, mp_file_read_at_rv, &
704  mp_file_read_at_d, mp_file_read_at_dv, mp_file_read_at_c, mp_file_read_at_cv, &
705  mp_file_read_at_z, mp_file_read_at_zv, mp_file_read_at_l, mp_file_read_at_lv
706 
707  PROCEDURE, PRIVATE, pass(fh), non_overridable :: mp_file_read_at_all_ch, mp_file_read_at_all_chv, &
708  mp_file_read_at_all_i, mp_file_read_at_all_iv, mp_file_read_at_all_l, mp_file_read_at_all_lv, &
709  mp_file_read_at_all_r, mp_file_read_at_all_rv, mp_file_read_at_all_d, mp_file_read_at_all_dv, &
710  mp_file_read_at_all_c, mp_file_read_at_all_cv, mp_file_read_at_all_z, mp_file_read_at_all_zv
711  generic, PUBLIC :: read_at_all => mp_file_read_at_all_ch, mp_file_read_at_all_chv, &
712  mp_file_read_at_all_i, mp_file_read_at_all_iv, mp_file_read_at_all_l, mp_file_read_at_all_lv, &
713  mp_file_read_at_all_r, mp_file_read_at_all_rv, mp_file_read_at_all_d, mp_file_read_at_all_dv, &
714  mp_file_read_at_all_c, mp_file_read_at_all_cv, mp_file_read_at_all_z, mp_file_read_at_all_zv
715 
716  PROCEDURE, PUBLIC, pass(fh), non_overridable :: open => mp_file_open
717  PROCEDURE, PUBLIC, pass(fh), non_overridable :: close => mp_file_close
718  PROCEDURE, PRIVATE, pass(fh_new), non_overridable :: mp_file_assign
719  generic, PUBLIC :: ASSIGNMENT(=) => mp_file_assign
720 
721  PROCEDURE, PUBLIC, pass(fh), non_overridable :: get_size => mp_file_get_size
722  PROCEDURE, PUBLIC, pass(fh), non_overridable :: get_position => mp_file_get_position
723 
724  PROCEDURE, PUBLIC, pass(fh), non_overridable :: read_all => mp_file_read_all_chv
725  PROCEDURE, PUBLIC, pass(fh), non_overridable :: write_all => mp_file_write_all_chv
726  END TYPE
727 
728  TYPE mp_info_type
729  PRIVATE
730  mpi_info_type :: handle = mp_info_null_handle
731  CONTAINS
732  PROCEDURE, non_overridable :: set_handle => mp_info_type_set_handle
733  PROCEDURE, non_overridable :: get_handle => mp_info_type_get_handle
734  PROCEDURE, PRIVATE, non_overridable :: mp_info_op_eq
735  PROCEDURE, PRIVATE, non_overridable :: mp_info_op_neq
736  generic, PUBLIC :: OPERATOR(.EQ.) => mp_info_op_eq
737  generic, PUBLIC :: OPERATOR(.NE.) => mp_info_op_neq
738  END TYPE
739 
740  TYPE, EXTENDS(mp_comm_type) :: mp_cart_type
741  INTEGER, DIMENSION(:), ALLOCATABLE, PUBLIC :: mepos_cart, num_pe_cart
742  LOGICAL, DIMENSION(:), ALLOCATABLE, PUBLIC :: periodic
743  CONTAINS
744  PROCEDURE, PUBLIC, pass(comm_cart), non_overridable :: create => mp_cart_create
745  PROCEDURE, PUBLIC, pass(sub_comm), non_overridable :: from_sub => mp_cart_sub
746 
747  PROCEDURE, PRIVATE, pass(comm), non_overridable :: get_info_cart => mp_cart_get
748 
749  PROCEDURE, PUBLIC, pass(comm), non_overridable :: coords => mp_cart_coords
750  PROCEDURE, PUBLIC, pass(comm), non_overridable :: rank_cart => mp_cart_rank
751  END TYPE
752 
753 ! **************************************************************************************************
754 !> \brief stores all the informations relevant to an mpi environment
755 !> \param owns_group if it owns the group (and thus should free it when
756 !> this object is deallocated)
757 !> \param ref_count the reference count, when it is zero this object gets
758 !> deallocated
759 !> \par History
760 !> 08.2002 created [fawzi]
761 !> \author Fawzi Mohamed
762 ! **************************************************************************************************
763  TYPE, EXTENDS(mp_comm_type) :: mp_para_env_type
764  PRIVATE
765  ! We set it to true to have less initialization steps in case we create a new communicator
766  LOGICAL :: owns_group = .true.
767  INTEGER :: ref_count = -1
768  CONTAINS
769  PROCEDURE, PUBLIC, pass(para_env), non_overridable :: retain => mp_para_env_retain
770  PROCEDURE, PUBLIC, pass(para_env), non_overridable :: is_valid => mp_para_env_is_valid
771  END TYPE mp_para_env_type
772 
773 ! **************************************************************************************************
774 !> \brief represent a pointer to a para env (to build arrays)
775 !> \param para_env the pointer to the para_env
776 !> \par History
777 !> 07.2003 created [fawzi]
778 !> \author Fawzi Mohamed
779 ! **************************************************************************************************
780  TYPE mp_para_env_p_type
781  TYPE(mp_para_env_type), POINTER :: para_env => null()
782  END TYPE mp_para_env_p_type
783 
784 ! **************************************************************************************************
785 !> \brief represent a multidimensional parallel environment
786 !> \param mepos_cart the position of the actual processor
787 !> \param num_pe_cart number of processors in the group in each dimension
788 !> \param source_cart id of a special processor (for example the one for i-o,
789 !> or the master
790 !> \param owns_group if it owns the group (and thus should free it when
791 !> this object is deallocated)
792 !> \param ref_count the reference count, when it is zero this object gets
793 !> deallocated
794 !> \note
795 !> not yet implemented for mpi
796 !> \par History
797 !> 08.2002 created [fawzi]
798 !> \author Fawzi Mohamed
799 ! **************************************************************************************************
800  TYPE, EXTENDS(mp_cart_type) :: mp_para_cart_type
801  PRIVATE
802  ! We set it to true to have less initialization steps in case we create a new communicator
803  LOGICAL :: owns_group = .true.
804  INTEGER :: ref_count = -1
805  CONTAINS
806  PROCEDURE, PUBLIC, pass(cart), non_overridable :: retain => mp_para_cart_retain
807  PROCEDURE, PUBLIC, pass(cart), non_overridable :: is_valid => mp_para_cart_is_valid
808  END TYPE mp_para_cart_type
809 
810  ! Create the constants from the corresponding handles
811  TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_null = mp_comm_type(mp_comm_null_handle)
812  TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_self = mp_comm_type(mp_comm_self_handle)
813  TYPE(mp_comm_type), PARAMETER, PUBLIC :: mp_comm_world = mp_comm_type(mp_comm_world_handle)
814  TYPE(mp_request_type), PARAMETER, PUBLIC :: mp_request_null = mp_request_type(mp_request_null_handle)
815  TYPE(mp_win_type), PARAMETER, PUBLIC :: mp_win_null = mp_win_type(mp_win_null_handle)
816  TYPE(mp_file_type), PARAMETER, PUBLIC :: mp_file_null = mp_file_type(mp_file_null_handle)
817  TYPE(mp_info_type), PARAMETER, PUBLIC :: mp_info_null = mp_info_type(mp_info_null_handle)
818 
819 #if !defined(__parallel)
820  ! This communicator is to be used in serial mode to emulate a valid communicator which is not a compiler constant
821  INTEGER, PARAMETER, PRIVATE :: mp_comm_default_handle = 1
822  TYPE(mp_comm_type), PARAMETER, PRIVATE :: mp_comm_default = mp_comm_type(mp_comm_default_handle)
823 #endif
824 
825  ! Constants to compare communicators
826  INTEGER, PARAMETER, PUBLIC :: mp_comm_ident = 0
827  INTEGER, PARAMETER, PUBLIC :: mp_comm_congruent = 1
828  INTEGER, PARAMETER, PUBLIC :: mp_comm_similar = 2
829  INTEGER, PARAMETER, PUBLIC :: mp_comm_unequal = 3
830  INTEGER, PARAMETER, PUBLIC :: mp_comm_compare_default = -1
831 
832  ! init and error
834  PUBLIC :: mp_abort
835 
836  ! informational / generation of sub comms
837  PUBLIC :: mp_dims_create
838  PUBLIC :: cp2k_is_parallel
839  PUBLIC :: mp_get_node_global_rank
840 
841  ! message passing
842  PUBLIC :: mp_waitall, mp_waitany
843  PUBLIC :: mp_testall, mp_testany
844 
845  ! Memory management
846  PUBLIC :: mp_allocate, mp_deallocate
847 
848  ! I/O
849  PUBLIC :: mp_file_delete
850  PUBLIC :: mp_file_get_amode
851 
852  ! some 'advanced types' currently only used for dbcsr
853  PUBLIC :: mp_type_descriptor_type
854  PUBLIC :: mp_type_make
855  PUBLIC :: mp_type_size
856 
857  ! vector types
860 
861  ! More I/O types and routines: variable spaced data using bytes for spacings
862  PUBLIC :: mp_file_descriptor_type
863  PUBLIC :: mp_file_type_free
865  PUBLIC :: mp_file_type_set_view_chv
866 
867  PUBLIC :: mp_get_library_version
868 
869  ! assumed to be private
870 
871  INTERFACE mp_waitall
872  MODULE PROCEDURE mp_waitall_1, mp_waitall_2
873  END INTERFACE
874 
875  INTERFACE mp_testall
876  MODULE PROCEDURE mp_testall_tv
877  END INTERFACE
878 
879  INTERFACE mp_testany
880  MODULE PROCEDURE mp_testany_1, mp_testany_2
881  END INTERFACE
882 
883  INTERFACE mp_type_free
884  MODULE PROCEDURE mp_type_free_m, mp_type_free_v
885  END INTERFACE
886 
887  !
888  ! interfaces to deal easily with scalars / vectors / matrices / ...
889  ! of the different types (integers, doubles, logicals, characters)
890  !
891  INTERFACE mp_allocate
892  MODULE PROCEDURE mp_allocate_i, &
893  mp_allocate_l, &
894  mp_allocate_r, &
895  mp_allocate_d, &
896  mp_allocate_c, &
897  mp_allocate_z
898  END INTERFACE
899 
900  INTERFACE mp_deallocate
901  MODULE PROCEDURE mp_deallocate_i, &
902  mp_deallocate_l, &
903  mp_deallocate_r, &
904  mp_deallocate_d, &
905  mp_deallocate_c, &
906  mp_deallocate_z
907  END INTERFACE
908 
909  INTERFACE mp_type_make
910  MODULE PROCEDURE mp_type_make_struct
911  MODULE PROCEDURE mp_type_make_i, mp_type_make_l, &
912  mp_type_make_r, mp_type_make_d, &
913  mp_type_make_c, mp_type_make_z
914  END INTERFACE
915 
916  INTERFACE mp_alloc_mem
917  MODULE PROCEDURE mp_alloc_mem_i, mp_alloc_mem_l, &
918  mp_alloc_mem_d, mp_alloc_mem_z, &
919  mp_alloc_mem_r, mp_alloc_mem_c
920  END INTERFACE
921 
922  INTERFACE mp_free_mem
923  MODULE PROCEDURE mp_free_mem_i, mp_free_mem_l, &
924  mp_free_mem_d, mp_free_mem_z, &
925  mp_free_mem_r, mp_free_mem_c
926  END INTERFACE
927 
928 ! Type declarations
929  TYPE mp_indexing_meta_type
930  INTEGER, DIMENSION(:), POINTER :: index => null(), chunks => null()
931  END TYPE mp_indexing_meta_type
932 
933  TYPE mp_type_descriptor_type
934  mpi_data_type :: type_handle = mp_datatype_null_handle
935  INTEGER :: length = -1
936 #if defined(__parallel)
937  INTEGER(kind=mpi_address_kind) :: base = -1
938 #endif
939  INTEGER(kind=int_4), DIMENSION(:), POINTER :: data_i => null()
940  INTEGER(kind=int_8), DIMENSION(:), POINTER :: data_l => null()
941  REAL(kind=real_4), DIMENSION(:), POINTER :: data_r => null()
942  REAL(kind=real_8), DIMENSION(:), POINTER :: data_d => null()
943  COMPLEX(kind=real_4), DIMENSION(:), POINTER :: data_c => null()
944  COMPLEX(kind=real_8), DIMENSION(:), POINTER :: data_z => null()
945  TYPE(mp_type_descriptor_type), DIMENSION(:), POINTER :: subtype => null()
946  INTEGER :: vector_descriptor(2) = -1
947  LOGICAL :: has_indexing = .false.
948  TYPE(mp_indexing_meta_type) :: index_descriptor = mp_indexing_meta_type()
949  END TYPE mp_type_descriptor_type
950 
951  TYPE mp_file_indexing_meta_type
952  INTEGER, DIMENSION(:), POINTER :: index => null()
953  INTEGER(kind=file_offset), &
954  DIMENSION(:), POINTER :: chunks => null()
955  END TYPE mp_file_indexing_meta_type
956 
957  TYPE mp_file_descriptor_type
958  mpi_data_type :: type_handle = mp_datatype_null_handle
959  INTEGER :: length = -1
960  LOGICAL :: has_indexing = .false.
961  TYPE(mp_file_indexing_meta_type) :: index_descriptor = mp_file_indexing_meta_type()
962  END TYPE
963 
964  ! we make some assumptions on the length of INTEGERS, REALS and LOGICALS
965  INTEGER, PARAMETER :: intlen = bit_size(0)/8
966  INTEGER, PARAMETER :: reallen = 8
967  INTEGER, PARAMETER :: loglen = bit_size(0)/8
968  INTEGER, PARAMETER :: charlen = 1
969 
970  LOGICAL, PUBLIC, SAVE :: mp_collect_timings = .false.
971 
972 CONTAINS
973 
974  LOGICAL FUNCTION mp_comm_op_eq(comm1, comm2)
975  CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
976 #if defined(__parallel) && defined(__MPI_F08)
977  mp_comm_op_eq = (comm1%handle%mpi_val .EQ. comm2%handle%mpi_val)
978 #else
979  mp_comm_op_eq = (comm1%handle .EQ. comm2%handle)
980 #endif
981  END FUNCTION mp_comm_op_eq
982 
983  LOGICAL FUNCTION mp_comm_op_neq(comm1, comm2)
984  CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
985 #if defined(__parallel) && defined(__MPI_F08)
986  mp_comm_op_neq = (comm1%handle%mpi_val .NE. comm2%handle%mpi_val)
987 #else
988  mp_comm_op_neq = (comm1%handle .NE. comm2%handle)
989 #endif
990  END FUNCTION mp_comm_op_neq
991 
992  ELEMENTAL IMPURE SUBROUTINE mp_comm_type_set_handle(this, handle , ndims)
993  CLASS(mp_comm_type), INTENT(INOUT) :: this
994  INTEGER, INTENT(IN) :: handle
995  INTEGER, INTENT(IN), OPTIONAL :: ndims
996 
997 #if defined(__parallel) && defined(__MPI_F08)
998  this%handle%mpi_val = handle
999 #else
1000  this%handle = handle
1001 #endif
1002 
1003  SELECT TYPE (this)
1004  CLASS IS (mp_cart_type)
1005  IF (.NOT. PRESENT(ndims)) &
1006  CALL cp_abort(__location__, &
1007  "Setup of a cartesian communicator requires information on the number of dimensions!")
1008  END SELECT
1009  IF (PRESENT(ndims)) this%ndims = ndims
1010  CALL this%init()
1011 
1012  END SUBROUTINE mp_comm_type_set_handle
1013 
1014  ELEMENTAL FUNCTION mp_comm_type_get_handle(this) RESULT(handle)
1015  CLASS(mp_comm_type), INTENT(IN) :: this
1016  INTEGER :: handle
1017 
1018 #if defined(__parallel) && defined(__MPI_F08)
1019  handle = this%handle%mpi_val
1020 #else
1021  handle = this%handle
1022 #endif
1023  END FUNCTION mp_comm_type_get_handle
1024  LOGICAL FUNCTION mp_request_op_eq(request1, request2)
1025  CLASS(mp_request_type), INTENT(IN) :: request1, request2
1026 #if defined(__parallel) && defined(__MPI_F08)
1027  mp_request_op_eq = (request1%handle%mpi_val .EQ. request2%handle%mpi_val)
1028 #else
1029  mp_request_op_eq = (request1%handle .EQ. request2%handle)
1030 #endif
1031  END FUNCTION mp_request_op_eq
1032 
1033  LOGICAL FUNCTION mp_request_op_neq(request1, request2)
1034  CLASS(mp_request_type), INTENT(IN) :: request1, request2
1035 #if defined(__parallel) && defined(__MPI_F08)
1036  mp_request_op_neq = (request1%handle%mpi_val .NE. request2%handle%mpi_val)
1037 #else
1038  mp_request_op_neq = (request1%handle .NE. request2%handle)
1039 #endif
1040  END FUNCTION mp_request_op_neq
1041 
1042  ELEMENTAL SUBROUTINE mp_request_type_set_handle(this, handle )
1043  CLASS(mp_request_type), INTENT(INOUT) :: this
1044  INTEGER, INTENT(IN) :: handle
1045 
1046 #if defined(__parallel) && defined(__MPI_F08)
1047  this%handle%mpi_val = handle
1048 #else
1049  this%handle = handle
1050 #endif
1051 
1052 
1053  END SUBROUTINE mp_request_type_set_handle
1054 
1055  ELEMENTAL FUNCTION mp_request_type_get_handle(this) RESULT(handle)
1056  CLASS(mp_request_type), INTENT(IN) :: this
1057  INTEGER :: handle
1058 
1059 #if defined(__parallel) && defined(__MPI_F08)
1060  handle = this%handle%mpi_val
1061 #else
1062  handle = this%handle
1063 #endif
1064  END FUNCTION mp_request_type_get_handle
1065  LOGICAL FUNCTION mp_win_op_eq(win1, win2)
1066  CLASS(mp_win_type), INTENT(IN) :: win1, win2
1067 #if defined(__parallel) && defined(__MPI_F08)
1068  mp_win_op_eq = (win1%handle%mpi_val .EQ. win2%handle%mpi_val)
1069 #else
1070  mp_win_op_eq = (win1%handle .EQ. win2%handle)
1071 #endif
1072  END FUNCTION mp_win_op_eq
1073 
1074  LOGICAL FUNCTION mp_win_op_neq(win1, win2)
1075  CLASS(mp_win_type), INTENT(IN) :: win1, win2
1076 #if defined(__parallel) && defined(__MPI_F08)
1077  mp_win_op_neq = (win1%handle%mpi_val .NE. win2%handle%mpi_val)
1078 #else
1079  mp_win_op_neq = (win1%handle .NE. win2%handle)
1080 #endif
1081  END FUNCTION mp_win_op_neq
1082 
1083  ELEMENTAL SUBROUTINE mp_win_type_set_handle(this, handle )
1084  CLASS(mp_win_type), INTENT(INOUT) :: this
1085  INTEGER, INTENT(IN) :: handle
1086 
1087 #if defined(__parallel) && defined(__MPI_F08)
1088  this%handle%mpi_val = handle
1089 #else
1090  this%handle = handle
1091 #endif
1092 
1093 
1094  END SUBROUTINE mp_win_type_set_handle
1095 
1096  ELEMENTAL FUNCTION mp_win_type_get_handle(this) RESULT(handle)
1097  CLASS(mp_win_type), INTENT(IN) :: this
1098  INTEGER :: handle
1099 
1100 #if defined(__parallel) && defined(__MPI_F08)
1101  handle = this%handle%mpi_val
1102 #else
1103  handle = this%handle
1104 #endif
1105  END FUNCTION mp_win_type_get_handle
1106  LOGICAL FUNCTION mp_file_op_eq(file1, file2)
1107  CLASS(mp_file_type), INTENT(IN) :: file1, file2
1108 #if defined(__parallel) && defined(__MPI_F08)
1109  mp_file_op_eq = (file1%handle%mpi_val .EQ. file2%handle%mpi_val)
1110 #else
1111  mp_file_op_eq = (file1%handle .EQ. file2%handle)
1112 #endif
1113  END FUNCTION mp_file_op_eq
1114 
1115  LOGICAL FUNCTION mp_file_op_neq(file1, file2)
1116  CLASS(mp_file_type), INTENT(IN) :: file1, file2
1117 #if defined(__parallel) && defined(__MPI_F08)
1118  mp_file_op_neq = (file1%handle%mpi_val .NE. file2%handle%mpi_val)
1119 #else
1120  mp_file_op_neq = (file1%handle .NE. file2%handle)
1121 #endif
1122  END FUNCTION mp_file_op_neq
1123 
1124  ELEMENTAL SUBROUTINE mp_file_type_set_handle(this, handle )
1125  CLASS(mp_file_type), INTENT(INOUT) :: this
1126  INTEGER, INTENT(IN) :: handle
1127 
1128 #if defined(__parallel) && defined(__MPI_F08)
1129  this%handle%mpi_val = handle
1130 #else
1131  this%handle = handle
1132 #endif
1133 
1134 
1135  END SUBROUTINE mp_file_type_set_handle
1136 
1137  ELEMENTAL FUNCTION mp_file_type_get_handle(this) RESULT(handle)
1138  CLASS(mp_file_type), INTENT(IN) :: this
1139  INTEGER :: handle
1140 
1141 #if defined(__parallel) && defined(__MPI_F08)
1142  handle = this%handle%mpi_val
1143 #else
1144  handle = this%handle
1145 #endif
1146  END FUNCTION mp_file_type_get_handle
1147  LOGICAL FUNCTION mp_info_op_eq(info1, info2)
1148  CLASS(mp_info_type), INTENT(IN) :: info1, info2
1149 #if defined(__parallel) && defined(__MPI_F08)
1150  mp_info_op_eq = (info1%handle%mpi_val .EQ. info2%handle%mpi_val)
1151 #else
1152  mp_info_op_eq = (info1%handle .EQ. info2%handle)
1153 #endif
1154  END FUNCTION mp_info_op_eq
1155 
1156  LOGICAL FUNCTION mp_info_op_neq(info1, info2)
1157  CLASS(mp_info_type), INTENT(IN) :: info1, info2
1158 #if defined(__parallel) && defined(__MPI_F08)
1159  mp_info_op_neq = (info1%handle%mpi_val .NE. info2%handle%mpi_val)
1160 #else
1161  mp_info_op_neq = (info1%handle .NE. info2%handle)
1162 #endif
1163  END FUNCTION mp_info_op_neq
1164 
1165  ELEMENTAL SUBROUTINE mp_info_type_set_handle(this, handle )
1166  CLASS(mp_info_type), INTENT(INOUT) :: this
1167  INTEGER, INTENT(IN) :: handle
1168 
1169 #if defined(__parallel) && defined(__MPI_F08)
1170  this%handle%mpi_val = handle
1171 #else
1172  this%handle = handle
1173 #endif
1174 
1175 
1176  END SUBROUTINE mp_info_type_set_handle
1177 
1178  ELEMENTAL FUNCTION mp_info_type_get_handle(this) RESULT(handle)
1179  CLASS(mp_info_type), INTENT(IN) :: this
1180  INTEGER :: handle
1181 
1182 #if defined(__parallel) && defined(__MPI_F08)
1183  handle = this%handle%mpi_val
1184 #else
1185  handle = this%handle
1186 #endif
1187  END FUNCTION mp_info_type_get_handle
1188 
1189  FUNCTION mp_comm_get_tag_ub(comm) RESULT(tag_ub)
1190  CLASS(mp_comm_type), INTENT(IN) :: comm
1191  INTEGER :: tag_ub
1192 
1193 #if defined(__parallel)
1194  INTEGER :: ierr
1195  LOGICAL :: flag
1196  INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1197 
1198  CALL mpi_comm_get_attr(comm%handle, mpi_tag_ub, attrval, flag, ierr)
1199  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_tag_ub")
1200  IF (.NOT. flag) cpabort("Upper bound of tags not available!")
1201  tag_ub = int(attrval, kind=kind(tag_ub))
1202 #else
1203  mark_used(comm)
1204  tag_ub = huge(1)
1205 #endif
1206  END FUNCTION mp_comm_get_tag_ub
1207 
1208  FUNCTION mp_comm_get_host_rank(comm) RESULT(host_rank)
1209  CLASS(mp_comm_type), INTENT(IN) :: comm
1210  INTEGER :: host_rank
1211 
1212 #if defined(__parallel)
1213  INTEGER :: ierr
1214  LOGICAL :: flag
1215  INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1216 
1217  CALL mpi_comm_get_attr(comm%handle, mpi_host, attrval, flag, ierr)
1218  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_host_rank")
1219  IF (.NOT. flag) cpabort("Host process rank not available!")
1220  host_rank = int(attrval, kind=kind(host_rank))
1221 #else
1222  mark_used(comm)
1223  host_rank = 0
1224 #endif
1225  END FUNCTION mp_comm_get_host_rank
1226 
1227  FUNCTION mp_comm_get_io_rank(comm) RESULT(io_rank)
1228  CLASS(mp_comm_type), INTENT(IN) :: comm
1229  INTEGER :: io_rank
1230 
1231 #if defined(__parallel)
1232  INTEGER :: ierr
1233  LOGICAL :: flag
1234  INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1235 
1236  CALL mpi_comm_get_attr(comm%handle, mpi_io, attrval, flag, ierr)
1237  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_io_rank")
1238  IF (.NOT. flag) cpabort("IO rank not available!")
1239  io_rank = int(attrval, kind=kind(io_rank))
1240 #else
1241  mark_used(comm)
1242  io_rank = 0
1243 #endif
1244  END FUNCTION mp_comm_get_io_rank
1245 
1246  FUNCTION mp_comm_get_wtime_is_global(comm) RESULT(wtime_is_global)
1247  CLASS(mp_comm_type), INTENT(IN) :: comm
1248  LOGICAL :: wtime_is_global
1249 
1250 #if defined(__parallel)
1251  INTEGER :: ierr
1252  LOGICAL :: flag
1253  INTEGER(KIND=MPI_ADDRESS_KIND) :: attrval
1254 
1255  CALL mpi_comm_get_attr(comm%handle, mpi_tag_ub, attrval, flag, ierr)
1256  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_get_attr @ mp_comm_get_wtime_is_global")
1257  IF (.NOT. flag) cpabort("Synchronization state of WTIME not available!")
1258  wtime_is_global = (attrval == 1_mpi_address_kind)
1259 #else
1260  mark_used(comm)
1261  wtime_is_global = .true.
1262 #endif
1263  END FUNCTION mp_comm_get_wtime_is_global
1264 
1265 ! **************************************************************************************************
1266 !> \brief initializes the system default communicator
1267 !> \param mp_comm [output] : handle of the default communicator
1268 !> \par History
1269 !> 2.2004 created [Joost VandeVondele ]
1270 !> \note
1271 !> should only be called once
1272 ! **************************************************************************************************
1273  SUBROUTINE mp_world_init(mp_comm)
1274  CLASS(mp_comm_type), INTENT(OUT) :: mp_comm
1275 #if defined(__parallel)
1276  INTEGER :: ierr
1277 !$ INTEGER :: provided_tsl
1278 !$ LOGICAL :: no_threading_support
1279 
1280 #if defined(__NO_MPI_THREAD_SUPPORT_CHECK)
1281  ! Hack that does not request or check MPI thread support level.
1282  ! User asserts that the MPI library will work correctly with
1283  ! threads.
1284 !
1285 !$ no_threading_support = .TRUE.
1286 #else
1287  ! Does the right thing when using OpenMP: requests that the MPI
1288  ! library supports serialized mode and verifies that the MPI library
1289  ! provides that support.
1290  !
1291  ! Developers: Only the master thread will ever make calls to the
1292  ! MPI library.
1293 !
1294 !$ no_threading_support = .FALSE.
1295 #endif
1296 !$ IF (no_threading_support) THEN
1297  CALL mpi_init(ierr)
1298  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_init @ mp_world_init")
1299 !$ ELSE
1300 !$OMP MASTER
1301 #if defined(__DLAF)
1302  ! DLA-Future requires that the MPI library supports
1303  ! THREAD_MULTIPLE mode
1304 !$ CALL mpi_init_thread(MPI_THREAD_MULTIPLE, provided_tsl, ierr)
1305 #else
1306 !$ CALL mpi_init_thread(MPI_THREAD_SERIALIZED, provided_tsl, ierr)
1307 #endif
1308 !$ IF (ierr /= 0) CALL mp_stop(ierr, "mpi_init_thread @ mp_world_init")
1309 #if defined(__DLAF)
1310 !$ IF (provided_tsl .LT. MPI_THREAD_MULTIPLE) THEN
1311 !$ CALL mp_stop(0, "MPI library does not support the requested level of threading (MPI_THREAD_MULTIPLE), required by DLA-Future. Build CP2K without DLA-Future.")
1312 !$ END IF
1313 #else
1314 !$ IF (provided_tsl .LT. MPI_THREAD_SERIALIZED) THEN
1315 !$ CALL mp_stop(0, "MPI library does not support the requested level of threading (MPI_THREAD_SERIALIZED).")
1316 !$ END IF
1317 #endif
1318 !$OMP END MASTER
1319 !$ END IF
1320  CALL mpi_comm_set_errhandler(mpi_comm_world, mpi_errors_return, ierr)
1321  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_set_errhandler @ mp_world_init")
1322 #endif
1323  debug_comm_count = 1
1324  mp_comm = mp_comm_world
1325  CALL mp_comm%init()
1326  CALL add_mp_perf_env()
1327  END SUBROUTINE mp_world_init
1328 
1329 ! **************************************************************************************************
1330 !> \brief re-create the system default communicator with a different MPI
1331 !> rank order
1332 !> \param mp_comm [output] : handle of the default communicator
1333 !> \param mp_new_comm ...
1334 !> \param ranks_order ...
1335 !> \par History
1336 !> 1.2012 created [ Christiane Pousa ]
1337 !> \note
1338 !> should only be called once, at very beginning of CP2K run
1339 ! **************************************************************************************************
1340  SUBROUTINE mp_reordering(mp_comm, mp_new_comm, ranks_order)
1341  CLASS(mp_comm_type), INTENT(IN) :: mp_comm
1342  CLASS(mp_comm_type), INTENT(out) :: mp_new_comm
1343  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: ranks_order
1344 
1345  CHARACTER(len=*), PARAMETER :: routinen = 'mp_reordering'
1346 
1347  INTEGER :: handle, ierr
1348 #if defined(__parallel)
1349  mpi_group_type :: newgroup, oldgroup
1350 #endif
1351 
1352  CALL mp_timeset(routinen, handle)
1353  ierr = 0
1354 #if defined(__parallel)
1355 
1356  CALL mpi_comm_group(mp_comm%handle, oldgroup, ierr)
1357  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_reordering")
1358  CALL mpi_group_incl(oldgroup, SIZE(ranks_order), ranks_order, newgroup, ierr)
1359  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_incl @ mp_reordering")
1360 
1361  CALL mpi_comm_create(mp_comm%handle, newgroup, mp_new_comm%handle, ierr)
1362  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_create @ mp_reordering")
1363 
1364  CALL mpi_group_free(oldgroup, ierr)
1365  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_free @ mp_reordering")
1366  CALL mpi_group_free(newgroup, ierr)
1367  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_group_free @ mp_reordering")
1368 
1369  CALL add_perf(perf_id=1, count=1)
1370 #else
1371  mark_used(mp_comm)
1372  mark_used(ranks_order)
1373  mp_new_comm%handle = mp_comm_default_handle
1374 #endif
1375  debug_comm_count = debug_comm_count + 1
1376  CALL mp_new_comm%init()
1377  CALL mp_timestop(handle)
1378  END SUBROUTINE mp_reordering
1379 
1380 ! **************************************************************************************************
1381 !> \brief finalizes the system default communicator
1382 !> \par History
1383 !> 2.2004 created [Joost VandeVondele]
1384 ! **************************************************************************************************
1385  SUBROUTINE mp_world_finalize()
1386 
1387  CHARACTER(LEN=default_string_length) :: debug_comm_count_char
1388 #if defined(__parallel)
1389  INTEGER :: ierr
1390  CALL mpi_barrier(mpi_comm_world, ierr) ! call mpi directly to avoid 0 stack pointer
1391 #endif
1392  CALL rm_mp_perf_env()
1393 
1394  debug_comm_count = debug_comm_count - 1
1395 #if defined(__parallel)
1396  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_barrier @ mp_world_finalize")
1397 #endif
1398  IF (debug_comm_count .NE. 0) THEN
1399  ! A bug, we're leaking or double-freeing communicators. Needs to be fixed where the leak happens.
1400  ! Memory leak checking might be helpful to locate the culprit
1401  WRITE (unit=debug_comm_count_char, fmt='(I0)')
1402  CALL cp_abort(__location__, "mp_world_finalize: assert failed:"// &
1403  " leaking communicators "//trim(debug_comm_count_char))
1404  END IF
1405 #if defined(__parallel)
1406  CALL mpi_finalize(ierr)
1407  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_finalize @ mp_world_finalize")
1408 #endif
1409 
1410  END SUBROUTINE mp_world_finalize
1411 
1412 ! all the following routines should work for a given communicator, not MPI_WORLD
1413 
1414 ! **************************************************************************************************
1415 !> \brief globally stops all tasks
1416 !> this is intended to be low level, most of CP2K should call cp_abort()
1417 ! **************************************************************************************************
1418  SUBROUTINE mp_abort()
1419  INTEGER :: ierr
1420 
1421  ierr = 0
1422 
1423 #if !defined(__NO_ABORT)
1424 #if defined(__parallel)
1425  CALL mpi_abort(mpi_comm_world, 1, ierr)
1426 #else
1427  CALL m_abort()
1428 #endif
1429 #endif
1430  ! this routine never returns and levels with non-zero exit code
1431  stop 1
1432  END SUBROUTINE mp_abort
1433 
1434 ! **************************************************************************************************
1435 !> \brief stops *after an mpi error* translating the error code
1436 !> \param ierr an error code * returned by an mpi call *
1437 !> \param prg_code ...
1438 !> \note
1439 !> this function is private to message_passing.F
1440 ! **************************************************************************************************
1441  SUBROUTINE mp_stop(ierr, prg_code)
1442  INTEGER, INTENT(IN) :: ierr
1443  CHARACTER(LEN=*), INTENT(IN) :: prg_code
1444 
1445 #if defined(__parallel)
1446  INTEGER :: istat, len
1447  CHARACTER(LEN=MPI_MAX_ERROR_STRING) :: error_string
1448  CHARACTER(LEN=MPI_MAX_ERROR_STRING + 512) :: full_error
1449 #else
1450  CHARACTER(LEN=512) :: full_error
1451 #endif
1452 
1453 #if defined(__parallel)
1454  CALL mpi_error_string(ierr, error_string, len, istat)
1455  WRITE (full_error, '(A,I0,A)') ' MPI error ', ierr, ' in '//trim(prg_code)//' : '//error_string(1:len)
1456 #else
1457  WRITE (full_error, '(A,I0,A)') ' MPI error (!?) ', ierr, ' in '//trim(prg_code)
1458 #endif
1459 
1460  cpabort(full_error)
1461 
1462  END SUBROUTINE mp_stop
1463 
1464 ! **************************************************************************************************
1465 !> \brief synchronizes with a barrier a given group of mpi tasks
1466 !> \param group mpi communicator
1467 ! **************************************************************************************************
1468  SUBROUTINE mp_sync(comm)
1469  CLASS(mp_comm_type), INTENT(IN) :: comm
1470 
1471  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sync'
1472 
1473  INTEGER :: handle, ierr
1474 
1475  ierr = 0
1476  CALL mp_timeset(routinen, handle)
1477 
1478 #if defined(__parallel)
1479  CALL mpi_barrier(comm%handle, ierr)
1480  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_barrier @ mp_sync")
1481  CALL add_perf(perf_id=5, count=1)
1482 #else
1483  mark_used(comm)
1484 #endif
1485  CALL mp_timestop(handle)
1486 
1487  END SUBROUTINE mp_sync
1488 
1489 ! **************************************************************************************************
1490 !> \brief synchronizes with a barrier a given group of mpi tasks
1491 !> \param comm mpi communicator
1492 !> \param request ...
1493 ! **************************************************************************************************
1494  SUBROUTINE mp_isync(comm, request)
1495  CLASS(mp_comm_type), INTENT(IN) :: comm
1496  TYPE(mp_request_type), INTENT(OUT) :: request
1497 
1498  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isync'
1499 
1500  INTEGER :: handle, ierr
1501 
1502  ierr = 0
1503  CALL mp_timeset(routinen, handle)
1504 
1505 #if defined(__parallel)
1506  CALL mpi_ibarrier(comm%handle, request%handle, ierr)
1507  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibarrier @ mp_isync")
1508  CALL add_perf(perf_id=26, count=1)
1509 #else
1510  mark_used(comm)
1511  request = mp_request_null
1512 #endif
1513  CALL mp_timestop(handle)
1514 
1515  END SUBROUTINE mp_isync
1516 
1517 ! **************************************************************************************************
1518 !> \brief returns task id for a given mpi communicator
1519 !> \param taskid The ID of the communicator
1520 !> \param comm mpi communicator
1521 ! **************************************************************************************************
1522  SUBROUTINE mp_comm_rank(taskid, comm)
1523 
1524  INTEGER, INTENT(OUT) :: taskid
1525  CLASS(mp_comm_type), INTENT(IN) :: comm
1526 
1527  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_rank'
1528 
1529  INTEGER :: handle
1530 #if defined(__parallel)
1531  INTEGER :: ierr
1532 #endif
1533 
1534  CALL mp_timeset(routinen, handle)
1535 
1536 #if defined(__parallel)
1537  CALL mpi_comm_rank(comm%handle, taskid, ierr)
1538  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ mp_comm_rank")
1539 #else
1540  mark_used(comm)
1541  taskid = 0
1542 #endif
1543  CALL mp_timestop(handle)
1544 
1545  END SUBROUTINE mp_comm_rank
1546 
1547 ! **************************************************************************************************
1548 !> \brief returns number of tasks for a given mpi communicator
1549 !> \param numtask ...
1550 !> \param comm mpi communicator
1551 ! **************************************************************************************************
1552  SUBROUTINE mp_comm_size(numtask, comm)
1553 
1554  INTEGER, INTENT(OUT) :: numtask
1555  CLASS(mp_comm_type), INTENT(IN) :: comm
1556 
1557  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_size'
1558 
1559  INTEGER :: handle
1560 #if defined(__parallel)
1561  INTEGER :: ierr
1562 #endif
1563 
1564  CALL mp_timeset(routinen, handle)
1565 
1566 #if defined(__parallel)
1567  CALL mpi_comm_size(comm%handle, numtask, ierr)
1568  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ mp_comm_size")
1569 #else
1570  mark_used(comm)
1571  numtask = 1
1572 #endif
1573  CALL mp_timestop(handle)
1574 
1575  END SUBROUTINE mp_comm_size
1576 
1577 ! **************************************************************************************************
1578 !> \brief returns info for a given Cartesian MPI communicator
1579 !> \param comm ...
1580 !> \param ndims ...
1581 !> \param dims ...
1582 !> \param task_coor ...
1583 !> \param periods ...
1584 ! **************************************************************************************************
1585  SUBROUTINE mp_cart_get(comm, dims, task_coor, periods)
1586 
1587  CLASS(mp_cart_type), INTENT(IN) :: comm
1588  INTEGER, INTENT(OUT), OPTIONAL :: dims(comm%ndims), task_coor(comm%ndims)
1589  LOGICAL, INTENT(out), OPTIONAL :: periods(comm%ndims)
1590 
1591  CHARACTER(len=*), PARAMETER :: routinen = 'mp_cart_get'
1592 
1593  INTEGER :: handle
1594 #if defined(__parallel)
1595  INTEGER :: ierr
1596  INTEGER :: my_dims(comm%ndims), my_task_coor(comm%ndims)
1597  LOGICAL :: my_periods(comm%ndims)
1598 #endif
1599 
1600  CALL mp_timeset(routinen, handle)
1601 
1602 #if defined(__parallel)
1603  CALL mpi_cart_get(comm%handle, comm%ndims, my_dims, my_periods, my_task_coor, ierr)
1604  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_get @ mp_cart_get")
1605  IF (PRESENT(dims)) dims = my_dims
1606  IF (PRESENT(task_coor)) task_coor = my_task_coor
1607  IF (PRESENT(periods)) periods = my_periods
1608 #else
1609  mark_used(comm)
1610  IF (PRESENT(task_coor)) task_coor = 0
1611  IF (PRESENT(dims)) dims = 1
1612  IF (PRESENT(periods)) periods = .false.
1613 #endif
1614  CALL mp_timestop(handle)
1615 
1616  END SUBROUTINE mp_cart_get
1617 
1618  INTEGER ELEMENTAL function mp_comm_get_ndims(comm)
1619  CLASS(mp_comm_type), INTENT(IN) :: comm
1620 
1621  mp_comm_get_ndims = comm%ndims
1622 
1623  END FUNCTION
1624 
1625 ! **************************************************************************************************
1626 !> \brief creates a cartesian communicator from any communicator
1627 !> \param comm_old ...
1628 !> \param ndims ...
1629 !> \param dims ...
1630 !> \param pos ...
1631 !> \param comm_cart ...
1632 ! **************************************************************************************************
1633  SUBROUTINE mp_cart_create(comm_old, ndims, dims, comm_cart)
1634 
1635  CLASS(mp_comm_type), INTENT(IN) :: comm_old
1636  INTEGER, INTENT(IN) :: ndims
1637  INTEGER, INTENT(INOUT) :: dims(ndims)
1638  CLASS(mp_cart_type), INTENT(OUT) :: comm_cart
1639 
1640  CHARACTER(len=*), PARAMETER :: routinen = 'mp_cart_create'
1641 
1642  INTEGER :: handle, ierr
1643 #if defined(__parallel)
1644  LOGICAL, DIMENSION(1:ndims) :: period
1645  LOGICAL :: reorder
1646 #endif
1647 
1648  ierr = 0
1649  CALL mp_timeset(routinen, handle)
1650 
1651  comm_cart%handle = comm_old%handle
1652 #if defined(__parallel)
1653 
1654  IF (any(dims == 0)) CALL mpi_dims_create(comm_old%num_pe, ndims, dims, ierr)
1655  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_dims_create @ mp_cart_create")
1656 
1657  ! FIX ME. Quick hack to avoid problems with realspace grids for compilers
1658  ! like IBM that actually reorder the processors when creating the new
1659  ! communicator
1660  reorder = .false.
1661  period = .true.
1662  CALL mpi_cart_create(comm_old%handle, ndims, dims, period, reorder, comm_cart%handle, &
1663  ierr)
1664  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_create @ mp_cart_create")
1665  CALL add_perf(perf_id=1, count=1)
1666 #else
1667  dims = 1
1668  comm_cart%handle = mp_comm_default_handle
1669 #endif
1670  comm_cart%ndims = ndims
1671  debug_comm_count = debug_comm_count + 1
1672  CALL comm_cart%init()
1673  CALL mp_timestop(handle)
1674 
1675  END SUBROUTINE mp_cart_create
1676 
1677 ! **************************************************************************************************
1678 !> \brief wrapper to MPI_Cart_coords
1679 !> \param comm ...
1680 !> \param rank ...
1681 !> \param coords ...
1682 ! **************************************************************************************************
1683  SUBROUTINE mp_cart_coords(comm, rank, coords)
1684 
1685  CLASS(mp_cart_type), INTENT(IN) :: comm
1686  INTEGER, INTENT(IN) :: rank
1687  INTEGER, DIMENSION(:), INTENT(OUT) :: coords
1688 
1689  CHARACTER(len=*), PARAMETER :: routinen = 'mp_cart_coords'
1690 
1691  INTEGER :: handle, ierr, m
1692 
1693  ierr = 0
1694  CALL mp_timeset(routinen, handle)
1695 
1696  m = SIZE(coords)
1697 #if defined(__parallel)
1698  CALL mpi_cart_coords(comm%handle, rank, m, coords, ierr)
1699  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_coords @ mp_cart_coords")
1700 #else
1701  coords = 0
1702  mark_used(rank)
1703  mark_used(comm)
1704 #endif
1705  CALL mp_timestop(handle)
1706 
1707  END SUBROUTINE mp_cart_coords
1708 
1709 ! **************************************************************************************************
1710 !> \brief wrapper to MPI_Comm_compare
1711 !> \param comm1 ...
1712 !> \param comm2 ...
1713 !> \param res ...
1714 ! **************************************************************************************************
1715  FUNCTION mp_comm_compare(comm1, comm2) RESULT(res)
1716 
1717  CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
1718  INTEGER :: res
1719 
1720  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_compare'
1721 
1722  INTEGER :: handle
1723 #if defined(__parallel)
1724  INTEGER :: ierr, iout
1725 #endif
1726 
1727  CALL mp_timeset(routinen, handle)
1728 
1729  res = 0
1730 #if defined(__parallel)
1731  CALL mpi_comm_compare(comm1%handle, comm2%handle, iout, ierr)
1732  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_compare @ mp_comm_compare")
1733  SELECT CASE (iout)
1734  CASE (mpi_ident)
1735  res = mp_comm_ident
1736  CASE (mpi_congruent)
1737  res = mp_comm_congruent
1738  CASE (mpi_similar)
1739  res = mp_comm_similar
1740  CASE (mpi_unequal)
1741  res = mp_comm_unequal
1742  CASE default
1743  cpabort("Unknown comparison state of the communicators!")
1744  END SELECT
1745 #else
1746  mark_used(comm1)
1747  mark_used(comm2)
1748 #endif
1749  CALL mp_timestop(handle)
1750 
1751  END FUNCTION mp_comm_compare
1752 
1753 ! **************************************************************************************************
1754 !> \brief wrapper to MPI_Cart_sub
1755 !> \param comm ...
1756 !> \param rdim ...
1757 !> \param sub_comm ...
1758 ! **************************************************************************************************
1759  SUBROUTINE mp_cart_sub(comm, rdim, sub_comm)
1760 
1761  CLASS(mp_cart_type), INTENT(IN) :: comm
1762  LOGICAL, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: rdim
1763  CLASS(mp_cart_type), INTENT(OUT) :: sub_comm
1764 
1765  CHARACTER(len=*), PARAMETER :: routinen = 'mp_cart_sub'
1766 
1767  INTEGER :: handle
1768 #if defined(__parallel)
1769  INTEGER :: ierr
1770 #endif
1771 
1772  CALL mp_timeset(routinen, handle)
1773 
1774 #if defined(__parallel)
1775  CALL mpi_cart_sub(comm%handle, rdim, sub_comm%handle, ierr)
1776  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_sub @ mp_cart_sub")
1777 #else
1778  mark_used(comm)
1779  mark_used(rdim)
1780  sub_comm%handle = mp_comm_default_handle
1781 #endif
1782  sub_comm%ndims = count(rdim)
1783  debug_comm_count = debug_comm_count + 1
1784  CALL sub_comm%init()
1785  CALL mp_timestop(handle)
1786 
1787  END SUBROUTINE mp_cart_sub
1788 
1789 ! **************************************************************************************************
1790 !> \brief wrapper to MPI_Comm_free
1791 !> \param comm ...
1792 ! **************************************************************************************************
1793  SUBROUTINE mp_comm_free(comm)
1794 
1795  CLASS(mp_comm_type), INTENT(INOUT) :: comm
1796 
1797  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_free'
1798 
1799  INTEGER :: handle
1800  LOGICAL :: free_comm
1801 #if defined(__parallel)
1802  INTEGER :: ierr
1803 #endif
1804 
1805  free_comm = .true.
1806  SELECT TYPE (comm)
1807  CLASS IS (mp_para_env_type)
1808  free_comm = .false.
1809  IF (comm%ref_count <= 0) &
1810  cpabort("para_env%ref_count <= 0")
1811  comm%ref_count = comm%ref_count - 1
1812  IF (comm%ref_count <= 0) THEN
1813  free_comm = comm%owns_group
1814  END IF
1815  CLASS IS (mp_para_cart_type)
1816  free_comm = .false.
1817  IF (comm%ref_count <= 0) &
1818  cpabort("para_cart%ref_count <= 0")
1819  comm%ref_count = comm%ref_count - 1
1820  IF (comm%ref_count <= 0) THEN
1821  free_comm = comm%owns_group
1822  END IF
1823  END SELECT
1824 
1825  CALL mp_timeset(routinen, handle)
1826 
1827  IF (free_comm) THEN
1828 #if defined(__parallel)
1829  CALL mpi_comm_free(comm%handle, ierr)
1830  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_free @ mp_comm_free")
1831 #else
1832  comm%handle = mp_comm_null_handle
1833 #endif
1834  debug_comm_count = debug_comm_count - 1
1835  END IF
1836 
1837  SELECT TYPE (comm)
1838  CLASS IS (mp_cart_type)
1839  DEALLOCATE (comm%periodic, comm%mepos_cart, comm%num_pe_cart)
1840  END SELECT
1841 
1842  CALL mp_timestop(handle)
1843 
1844  END SUBROUTINE mp_comm_free
1845 
1846 ! **************************************************************************************************
1847 !> \brief check whether the environment exists
1848 !> \param para_env ...
1849 !> \return ...
1850 ! **************************************************************************************************
1851  ELEMENTAL LOGICAL FUNCTION mp_para_env_is_valid(para_env)
1852  CLASS(mp_para_env_type), INTENT(IN) :: para_env
1853 
1854  mp_para_env_is_valid = para_env%ref_count > 0
1855 
1856  END FUNCTION mp_para_env_is_valid
1857 
1858 ! **************************************************************************************************
1859 !> \brief increase the reference counter but ensure that you free it later
1860 !> \param para_env ...
1861 ! **************************************************************************************************
1862  ELEMENTAL SUBROUTINE mp_para_env_retain(para_env)
1863  CLASS(mp_para_env_type), INTENT(INOUT) :: para_env
1864 
1865  para_env%ref_count = para_env%ref_count + 1
1866 
1867  END SUBROUTINE mp_para_env_retain
1868 
1869 ! **************************************************************************************************
1870 !> \brief check whether the given environment is valid, i.e. existent
1871 !> \param cart ...
1872 !> \return ...
1873 ! **************************************************************************************************
1874  ELEMENTAL LOGICAL FUNCTION mp_para_cart_is_valid(cart)
1875  CLASS(mp_para_cart_type), INTENT(IN) :: cart
1876 
1877  mp_para_cart_is_valid = cart%ref_count > 0
1878 
1879  END FUNCTION mp_para_cart_is_valid
1880 
1881 ! **************************************************************************************************
1882 !> \brief increase the reference counter, don't forget to free it later
1883 !> \param cart ...
1884 ! **************************************************************************************************
1885  ELEMENTAL SUBROUTINE mp_para_cart_retain(cart)
1886  CLASS(mp_para_cart_type), INTENT(INOUT) :: cart
1887 
1888  cart%ref_count = cart%ref_count + 1
1889 
1890  END SUBROUTINE mp_para_cart_retain
1891 
1892 ! **************************************************************************************************
1893 !> \brief wrapper to MPI_Comm_dup
1894 !> \param comm1 ...
1895 !> \param comm2 ...
1896 ! **************************************************************************************************
1897  SUBROUTINE mp_comm_dup(comm1, comm2)
1898 
1899  CLASS(mp_comm_type), INTENT(IN) :: comm1
1900  CLASS(mp_comm_type), INTENT(OUT) :: comm2
1901 
1902  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_dup'
1903 
1904  INTEGER :: handle
1905 #if defined(__parallel)
1906  INTEGER :: ierr
1907 #endif
1908 
1909  CALL mp_timeset(routinen, handle)
1910 
1911 #if defined(__parallel)
1912  CALL mpi_comm_dup(comm1%handle, comm2%handle, ierr)
1913  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_dup @ mp_comm_dup")
1914 #else
1915  mark_used(comm1)
1916  comm2%handle = mp_comm_default_handle
1917 #endif
1918  comm2%ndims = comm1%ndims
1919  debug_comm_count = debug_comm_count + 1
1920  CALL comm2%init()
1921  CALL mp_timestop(handle)
1922 
1923  END SUBROUTINE mp_comm_dup
1924 
1925 ! **************************************************************************************************
1926 !> \brief Implements a simple assignment function to overload the assignment operator
1927 !> \param comm_new communicator on the r.h.s. of the assignment operator
1928 !> \param comm_old communicator on the l.h.s. of the assignment operator
1929 ! **************************************************************************************************
1930  ELEMENTAL IMPURE SUBROUTINE mp_comm_assign(comm_new, comm_old)
1931  CLASS(mp_comm_type), INTENT(IN) :: comm_old
1932  CLASS(mp_comm_type), INTENT(OUT) :: comm_new
1933 
1934  comm_new%handle = comm_old%handle
1935  comm_new%ndims = comm_old%ndims
1936  CALL comm_new%init(.false.)
1937  END SUBROUTINE
1938 
1939 ! **************************************************************************************************
1940 !> \brief check whether the local process is the source process
1941 !> \param para_env ...
1942 !> \return ...
1943 ! **************************************************************************************************
1944  ELEMENTAL LOGICAL FUNCTION mp_comm_is_source(comm)
1945  CLASS(mp_comm_type), INTENT(IN) :: comm
1946 
1947  mp_comm_is_source = comm%source == comm%mepos
1948 
1949  END FUNCTION mp_comm_is_source
1950 
1951 ! **************************************************************************************************
1952 !> \brief Initializes the communicator (mostly relevant for its derived classes)
1953 !> \param comm ...
1954 ! **************************************************************************************************
1955  ELEMENTAL IMPURE SUBROUTINE mp_comm_init(comm, owns_group)
1956  CLASS(mp_comm_type), INTENT(INOUT) :: comm
1957  LOGICAL, INTENT(IN), OPTIONAL :: owns_group
1958 
1959  IF (comm%handle mpi_get_comp .NE. mp_comm_null_handle mpi_get_comp) THEN
1960  comm%source = 0
1961  CALL comm%get_size(comm%num_pe)
1962  CALL comm%get_rank(comm%mepos)
1963  END IF
1964 
1965  SELECT TYPE (comm)
1966  CLASS IS (mp_cart_type)
1967  IF (ALLOCATED(comm%periodic)) DEALLOCATE (comm%periodic)
1968  IF (ALLOCATED(comm%mepos_cart)) DEALLOCATE (comm%mepos_cart)
1969  IF (ALLOCATED(comm%num_pe_cart)) DEALLOCATE (comm%num_pe_cart)
1970 
1971  associate(ndims => comm%ndims)
1972 
1973  ALLOCATE (comm%periodic(ndims), comm%mepos_cart(ndims), &
1974  comm%num_pe_cart(ndims))
1975  END associate
1976 
1977  comm%mepos_cart = 0
1978  comm%periodic = .false.
1979  IF (comm%handle mpi_get_comp .NE. mp_comm_null_handle mpi_get_comp) THEN
1980  CALL comm%get_info_cart(comm%num_pe_cart, comm%mepos_cart, &
1981  comm%periodic)
1982  END IF
1983  END SELECT
1984 
1985  SELECT TYPE (comm)
1986  CLASS IS (mp_para_env_type)
1987  IF (PRESENT(owns_group)) comm%owns_group = owns_group
1988  comm%ref_count = 1
1989  CLASS IS (mp_para_cart_type)
1990  IF (PRESENT(owns_group)) comm%owns_group = owns_group
1991  comm%ref_count = 1
1992  END SELECT
1993 
1994  END SUBROUTINE
1995 
1996 ! **************************************************************************************************
1997 !> \brief creates a new para environment
1998 !> \param para_env the new parallel environment
1999 !> \param group the id of the actual mpi_group
2000 !> \par History
2001 !> 08.2002 created [fawzi]
2002 !> \author Fawzi Mohamed
2003 ! **************************************************************************************************
2004  SUBROUTINE mp_para_env_create(para_env, group)
2005  TYPE(mp_para_env_type), POINTER :: para_env
2006  CLASS(mp_comm_type), INTENT(in) :: group
2007 
2008  IF (ASSOCIATED(para_env)) &
2009  cpabort("The passed para_env must not be associated!")
2010  ALLOCATE (para_env)
2011  para_env%mp_comm_type = group
2012  CALL para_env%init()
2013  END SUBROUTINE mp_para_env_create
2014 
2015 ! **************************************************************************************************
2016 !> \brief releases the para object (to be called when you don't want anymore
2017 !> the shared copy of this object)
2018 !> \param para_env the new group
2019 !> \par History
2020 !> 08.2002 created [fawzi]
2021 !> \author Fawzi Mohamed
2022 !> \note
2023 !> to avoid circular dependencies cp_log_handling has a private copy
2024 !> of this method (see cp_log_handling:my_mp_para_env_release)!
2025 ! **************************************************************************************************
2026  SUBROUTINE mp_para_env_release(para_env)
2027  TYPE(mp_para_env_type), POINTER :: para_env
2028 
2029  IF (ASSOCIATED(para_env)) THEN
2030  CALL para_env%free()
2031  IF (.NOT. para_env%is_valid()) DEALLOCATE (para_env)
2032  END IF
2033  NULLIFY (para_env)
2034  END SUBROUTINE mp_para_env_release
2035 
2036 ! **************************************************************************************************
2037 !> \brief creates a cart (multidimensional parallel environment)
2038 !> \param cart the cart environment to create
2039 !> \param group the mpi communicator
2040 !> \author fawzi
2041 ! **************************************************************************************************
2042  SUBROUTINE mp_para_cart_create(cart, group)
2043  TYPE(mp_para_cart_type), POINTER, INTENT(OUT) :: cart
2044  CLASS(mp_comm_type), INTENT(in) :: group
2045 
2046  IF (ASSOCIATED(cart)) &
2047  cpabort("The passed para_cart must not be associated!")
2048  ALLOCATE (cart)
2049  cart%mp_cart_type = group
2050  CALL cart%init()
2051 
2052  END SUBROUTINE mp_para_cart_create
2053 
2054 ! **************************************************************************************************
2055 !> \brief releases the given cart
2056 !> \param cart the cart to release
2057 !> \author fawzi
2058 ! **************************************************************************************************
2059  SUBROUTINE mp_para_cart_release(cart)
2060  TYPE(mp_para_cart_type), POINTER :: cart
2061 
2062  IF (ASSOCIATED(cart)) THEN
2063  CALL cart%free()
2064  IF (.NOT. cart%is_valid()) DEALLOCATE (cart)
2065  END IF
2066  NULLIFY (cart)
2067  END SUBROUTINE mp_para_cart_release
2068 
2069 ! **************************************************************************************************
2070 !> \brief wrapper to MPI_Group_translate_ranks
2071 !> \param comm1 ...
2072 !> \param comm2 ...
2073 !> \param rank ...
2074 ! **************************************************************************************************
2075  SUBROUTINE mp_rank_compare(comm1, comm2, rank)
2076 
2077  CLASS(mp_comm_type), INTENT(IN) :: comm1, comm2
2078  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rank
2079 
2080  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rank_compare'
2081 
2082  INTEGER :: handle
2083 #if defined(__parallel)
2084  INTEGER :: i, ierr, n, n1, n2
2085  INTEGER, ALLOCATABLE, DIMENSION(:) :: rin
2086  mpi_group_type :: g1, g2
2087 #endif
2088 
2089  CALL mp_timeset(routinen, handle)
2090 
2091  rank = 0
2092 #if defined(__parallel)
2093  CALL mpi_comm_size(comm1%handle, n1, ierr)
2094  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ mp_rank_compare")
2095  CALL mpi_comm_size(comm2%handle, n2, ierr)
2096  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ mp_rank_compare")
2097  n = max(n1, n2)
2098  CALL mpi_comm_group(comm1%handle, g1, ierr)
2099  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_rank_compare")
2100  CALL mpi_comm_group(comm2%handle, g2, ierr)
2101  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_group @ mp_rank_compare")
2102  ALLOCATE (rin(0:n - 1), stat=ierr)
2103  IF (ierr /= 0) &
2104  cpabort("allocate @ mp_rank_compare")
2105  DO i = 0, n - 1
2106  rin(i) = i
2107  END DO
2108  CALL mpi_group_translate_ranks(g1, n, rin, g2, rank, ierr)
2109  IF (ierr /= 0) CALL mp_stop(ierr, &
2110  "mpi_group_translate_rank @ mp_rank_compare")
2111  CALL mpi_group_free(g1, ierr)
2112  IF (ierr /= 0) &
2113  cpabort("group_free @ mp_rank_compare")
2114  CALL mpi_group_free(g2, ierr)
2115  IF (ierr /= 0) &
2116  cpabort("group_free @ mp_rank_compare")
2117  DEALLOCATE (rin)
2118 #else
2119  mark_used(comm1)
2120  mark_used(comm2)
2121 #endif
2122  CALL mp_timestop(handle)
2123 
2124  END SUBROUTINE mp_rank_compare
2125 
2126 ! **************************************************************************************************
2127 !> \brief wrapper to MPI_Dims_create
2128 !> \param nodes ...
2129 !> \param dims ...
2130 ! **************************************************************************************************
2131  SUBROUTINE mp_dims_create(nodes, dims)
2132 
2133  INTEGER, INTENT(IN) :: nodes
2134  INTEGER, DIMENSION(:), INTENT(INOUT) :: dims
2135 
2136  CHARACTER(len=*), PARAMETER :: routinen = 'mp_dims_create'
2137 
2138  INTEGER :: handle, ndim
2139 #if defined(__parallel)
2140  INTEGER :: ierr
2141 #endif
2142 
2143  CALL mp_timeset(routinen, handle)
2144 
2145  ndim = SIZE(dims)
2146 #if defined(__parallel)
2147  IF (any(dims == 0)) CALL mpi_dims_create(nodes, ndim, dims, ierr)
2148  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_dims_create @ mp_dims_create")
2149 #else
2150  dims = 1
2151  mark_used(nodes)
2152 #endif
2153  CALL mp_timestop(handle)
2154 
2155  END SUBROUTINE mp_dims_create
2156 
2157 ! **************************************************************************************************
2158 !> \brief wrapper to MPI_Cart_rank
2159 !> \param comm ...
2160 !> \param pos ...
2161 !> \param rank ...
2162 ! **************************************************************************************************
2163  SUBROUTINE mp_cart_rank(comm, pos, rank)
2164  CLASS(mp_cart_type), INTENT(IN) :: comm
2165  INTEGER, DIMENSION(:), INTENT(IN) :: pos
2166  INTEGER, INTENT(OUT) :: rank
2167 
2168  CHARACTER(len=*), PARAMETER :: routinen = 'mp_cart_rank'
2169 
2170  INTEGER :: handle
2171 #if defined(__parallel)
2172  INTEGER :: ierr
2173 #endif
2174 
2175  CALL mp_timeset(routinen, handle)
2176 
2177 #if defined(__parallel)
2178  CALL mpi_cart_rank(comm%handle, pos, rank, ierr)
2179  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_cart_rank @ mp_cart_rank")
2180 #else
2181  rank = 0
2182  mark_used(comm)
2183  mark_used(pos)
2184 #endif
2185  CALL mp_timestop(handle)
2186 
2187  END SUBROUTINE mp_cart_rank
2188 
2189 ! **************************************************************************************************
2190 !> \brief waits for completion of the given request
2191 !> \param request ...
2192 !> \par History
2193 !> 08.2003 created [f&j]
2194 !> \author joost & fawzi
2195 !> \note
2196 !> see isendrecv
2197 ! **************************************************************************************************
2198  SUBROUTINE mp_wait(request)
2199  CLASS(mp_request_type), INTENT(inout) :: request
2200 
2201  CHARACTER(len=*), PARAMETER :: routinen = 'mp_wait'
2202 
2203  INTEGER :: handle
2204 #if defined(__parallel)
2205  INTEGER :: ierr
2206 #endif
2207 
2208  CALL mp_timeset(routinen, handle)
2209 
2210 #if defined(__parallel)
2211 
2212  CALL mpi_wait(request%handle, mpi_status_ignore, ierr)
2213  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_wait @ mp_wait")
2214 
2215  CALL add_perf(perf_id=9, count=1)
2216 #else
2217  request%handle = mp_request_null_handle
2218 #endif
2219  CALL mp_timestop(handle)
2220  END SUBROUTINE mp_wait
2221 
2222 ! **************************************************************************************************
2223 !> \brief waits for completion of the given requests
2224 !> \param requests ...
2225 !> \par History
2226 !> 08.2003 created [f&j]
2227 !> \author joost & fawzi
2228 !> \note
2229 !> see isendrecv
2230 ! **************************************************************************************************
2231  SUBROUTINE mp_waitall_1(requests)
2232  TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2233 
2234  CHARACTER(len=*), PARAMETER :: routinen = 'mp_waitall_1'
2235 
2236  INTEGER :: handle
2237 #if defined(__parallel)
2238  INTEGER :: count, ierr
2239 #if !defined(__MPI_F08)
2240  INTEGER, ALLOCATABLE, DIMENSION(:, :) :: status
2241 #else
2242  TYPE(mpi_status), ALLOCATABLE, DIMENSION(:) :: status
2243 #endif
2244 #endif
2245 
2246  CALL mp_timeset(routinen, handle)
2247 
2248 #if defined(__parallel)
2249  count = SIZE(requests)
2250 #if !defined(__MPI_F08)
2251  ALLOCATE (status(mpi_status_size, count))
2252 #else
2253  ALLOCATE (status(count))
2254 #endif
2255  CALL mpi_waitall_internal(count, requests, status, ierr) ! MPI_STATUSES_IGNORE openmpi workaround
2256  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitall @ mp_waitall_1")
2257  DEALLOCATE (status)
2258  CALL add_perf(perf_id=9, count=1)
2259 #else
2260  requests = mp_request_null
2261 #endif
2262  CALL mp_timestop(handle)
2263  END SUBROUTINE mp_waitall_1
2264 
2265 ! **************************************************************************************************
2266 !> \brief waits for completion of the given requests
2267 !> \param requests ...
2268 !> \par History
2269 !> 08.2003 created [f&j]
2270 !> \author joost & fawzi
2271 ! **************************************************************************************************
2272  SUBROUTINE mp_waitall_2(requests)
2273  TYPE(mp_request_type), DIMENSION(:, :), INTENT(inout) :: requests
2274 
2275  CHARACTER(len=*), PARAMETER :: routinen = 'mp_waitall_2'
2276 
2277  INTEGER :: handle
2278 #if defined(__parallel)
2279  INTEGER :: count, ierr
2280 #if !defined(__MPI_F08)
2281  INTEGER, ALLOCATABLE, DIMENSION(:, :) :: status
2282 #else
2283  TYPE(mpi_status), ALLOCATABLE, DIMENSION(:) :: status
2284 #endif
2285 #endif
2286 
2287  CALL mp_timeset(routinen, handle)
2288 
2289 #if defined(__parallel)
2290  count = SIZE(requests)
2291 #if !defined(__MPI_F08)
2292  ALLOCATE (status(mpi_status_size, count))
2293 #else
2294  ALLOCATE (status(count))
2295 #endif
2296 
2297  CALL mpi_waitall_internal(count, requests, status, ierr) ! MPI_STATUSES_IGNORE openmpi workaround
2298  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitall @ mp_waitall_2")
2299  DEALLOCATE (status)
2300 
2301  CALL add_perf(perf_id=9, count=1)
2302 #else
2303  requests = mp_request_null
2304 #endif
2305  CALL mp_timestop(handle)
2306  END SUBROUTINE mp_waitall_2
2307 
2308 ! **************************************************************************************************
2309 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
2310 !> the issue is with the rank or requests
2311 !> \param count ...
2312 !> \param array_of_requests ...
2313 !> \param array_of_statuses ...
2314 !> \param ierr ...
2315 !> \author Joost VandeVondele
2316 ! **************************************************************************************************
2317 #if defined(__parallel)
2318  SUBROUTINE mpi_waitall_internal(count, array_of_requests, array_of_statuses, ierr)
2319  INTEGER, INTENT(in) :: count
2320  TYPE(mp_request_type), DIMENSION(count), INTENT(inout) :: array_of_requests
2321 #if !defined(__MPI_F08)
2322  INTEGER, DIMENSION(MPI_STATUS_SIZE, count), &
2323  INTENT(out) :: array_of_statuses
2324 #else
2325  TYPE(mpi_status), DIMENSION(count), &
2326  INTENT(out) :: array_of_statuses
2327 #endif
2328  INTEGER, INTENT(out) :: ierr
2329 
2330  INTEGER :: i
2331  mpi_request_type, ALLOCATABLE, DIMENSION(:) :: request_handles
2332 
2333  ALLOCATE (request_handles(count))
2334  DO i = 1, count
2335  request_handles(i) = array_of_requests(i)%handle
2336  END DO
2337 
2338  CALL mpi_waitall(count, request_handles, array_of_statuses, ierr)
2339 
2340  DO i = 1, count
2341  array_of_requests(i)%handle = request_handles(i)
2342  END DO
2343 
2344  END SUBROUTINE mpi_waitall_internal
2345 #endif
2346 
2347 ! **************************************************************************************************
2348 !> \brief waits for completion of any of the given requests
2349 !> \param requests ...
2350 !> \param completed ...
2351 !> \par History
2352 !> 09.2008 created
2353 !> \author Iain Bethune (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
2354 ! **************************************************************************************************
2355  SUBROUTINE mp_waitany(requests, completed)
2356  TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2357  INTEGER, INTENT(out) :: completed
2358 
2359  CHARACTER(len=*), PARAMETER :: routinen = 'mp_waitany'
2360 
2361  INTEGER :: handle
2362 #if defined(__parallel)
2363  INTEGER :: count, i, ierr
2364  mpi_request_type, ALLOCATABLE, DIMENSION(:) :: request_handles
2365 #endif
2366 
2367  CALL mp_timeset(routinen, handle)
2368 
2369 #if defined(__parallel)
2370  count = SIZE(requests)
2371 ! Convert CP2K's request_handles to the plane handle for the library
2372 ! (Maybe, the compiler optimizes it away)
2373  ALLOCATE (request_handles(count))
2374  DO i = 1, count
2375  request_handles(i) = requests(i)%handle
2376  END DO
2377  CALL mpi_waitany(count, request_handles, completed, mpi_status_ignore, ierr)
2378  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_waitany @ mp_waitany")
2379 ! Convert the plane handles to CP2K handles
2380  DO i = 1, count
2381  requests(i)%handle = request_handles(i)
2382  END DO
2383  CALL add_perf(perf_id=9, count=1)
2384 #else
2385  requests = mp_request_null
2386  completed = 1
2387 #endif
2388  CALL mp_timestop(handle)
2389  END SUBROUTINE mp_waitany
2390 
2391 ! **************************************************************************************************
2392 !> \brief Tests for completion of the given requests.
2393 !> \brief We use mpi_test so that we can use a single status.
2394 !> \param requests the list of requests to test
2395 !> \return logical which determines if requests are complete
2396 !> \par History
2397 !> 3.2016 adapted to any shape [Nico Holmberg]
2398 !> \author Alfio Lazzaro
2399 ! **************************************************************************************************
2400  FUNCTION mp_testall_tv(requests) RESULT(flag)
2401  TYPE(mp_request_type), DIMENSION(:), INTENT(INOUT) :: requests
2402  LOGICAL :: flag
2403 
2404 #if defined(__parallel)
2405  INTEGER :: i, ierr
2406  LOGICAL, DIMENSION(:), POINTER :: flags
2407 #endif
2408 
2409  flag = .true.
2410 
2411 #if defined(__parallel)
2412  ALLOCATE (flags(SIZE(requests)))
2413  DO i = 1, SIZE(requests)
2414  CALL mpi_test(requests(i)%handle, flags(i), mpi_status_ignore, ierr)
2415  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testall @ mp_testall_tv")
2416  flag = flag .AND. flags(i)
2417  END DO
2418  DEALLOCATE (flags)
2419 #else
2420  requests = mp_request_null
2421 #endif
2422  END FUNCTION mp_testall_tv
2423 
2424 ! **************************************************************************************************
2425 !> \brief Tests for completion of the given request.
2426 !> \param request the request
2427 !> \param flag logical which determines if the request is completed
2428 !> \par History
2429 !> 3.2016 created
2430 !> \author Nico Holmberg
2431 ! **************************************************************************************************
2432  FUNCTION mp_test_1(request) RESULT(flag)
2433  CLASS(mp_request_type), INTENT(inout) :: request
2434  LOGICAL :: flag
2435 
2436 #if defined(__parallel)
2437  INTEGER :: ierr
2438 
2439  CALL mpi_test(request%handle, flag, mpi_status_ignore, ierr)
2440  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_test @ mp_test_1")
2441 #else
2442  mark_used(request)
2443  flag = .true.
2444 #endif
2445  END FUNCTION mp_test_1
2446 
2447 ! **************************************************************************************************
2448 !> \brief tests for completion of the given requests
2449 !> \param requests ...
2450 !> \param completed ...
2451 !> \param flag ...
2452 !> \par History
2453 !> 08.2011 created
2454 !> \author Iain Bethune
2455 ! **************************************************************************************************
2456  SUBROUTINE mp_testany_1(requests, completed, flag)
2457  TYPE(mp_request_type), DIMENSION(:), INTENT(inout) :: requests
2458  INTEGER, INTENT(out), OPTIONAL :: completed
2459  LOGICAL, INTENT(out), OPTIONAL :: flag
2460 
2461 #if defined(__parallel)
2462  INTEGER :: completed_l, count, ierr
2463  LOGICAL :: flag_l
2464 
2465  count = SIZE(requests)
2466 
2467  CALL mpi_testany_internal(count, requests, completed_l, flag_l, mpi_status_ignore, ierr)
2468  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testany_1 @ mp_testany")
2469 
2470  IF (PRESENT(completed)) completed = completed_l
2471  IF (PRESENT(flag)) flag = flag_l
2472 #else
2473  mark_used(requests)
2474  IF (PRESENT(completed)) completed = 1
2475  IF (PRESENT(flag)) flag = .true.
2476 #endif
2477  END SUBROUTINE mp_testany_1
2478 
2479 ! **************************************************************************************************
2480 !> \brief tests for completion of the given requests
2481 !> \param requests ...
2482 !> \param completed ...
2483 !> \param flag ...
2484 !> \par History
2485 !> 08.2011 created
2486 !> \author Iain Bethune
2487 ! **************************************************************************************************
2488  SUBROUTINE mp_testany_2(requests, completed, flag)
2489  TYPE(mp_request_type), DIMENSION(:, :), INTENT(inout) :: requests
2490  INTEGER, INTENT(out), OPTIONAL :: completed
2491  LOGICAL, INTENT(out), OPTIONAL :: flag
2492 
2493 #if defined(__parallel)
2494  INTEGER :: completed_l, count, ierr
2495  LOGICAL :: flag_l
2496 
2497  count = SIZE(requests)
2498 
2499  CALL mpi_testany_internal(count, requests, completed_l, flag_l, mpi_status_ignore, ierr)
2500  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_testany_2 @ mp_testany")
2501 
2502  IF (PRESENT(completed)) completed = completed_l
2503  IF (PRESENT(flag)) flag = flag_l
2504 #else
2505  mark_used(requests)
2506  IF (PRESENT(completed)) completed = 1
2507  IF (PRESENT(flag)) flag = .true.
2508 #endif
2509  END SUBROUTINE mp_testany_2
2510 
2511 ! **************************************************************************************************
2512 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
2513 !> the issue is with the rank or requests
2514 !> \param count ...
2515 !> \param array_of_requests ...
2516 !> \param index ...
2517 !> \param flag ...
2518 !> \param status ...
2519 !> \param ierr ...
2520 !> \author Joost VandeVondele
2521 ! **************************************************************************************************
2522 #if defined(__parallel)
2523  SUBROUTINE mpi_testany_internal(count, array_of_requests, index, flag, status, ierr)
2524  INTEGER, INTENT(in) :: count
2525  TYPE(mp_request_type), DIMENSION(count), INTENT(inout) :: array_of_requests
2526  INTEGER, INTENT(out) :: index
2527  LOGICAL, INTENT(out) :: flag
2528  mpi_status_type, INTENT(out) :: status
2529  INTEGER, INTENT(out) :: ierr
2530 
2531  INTEGER :: i
2532  mpi_request_type, ALLOCATABLE, DIMENSION(:) :: request_handles
2533 
2534  ALLOCATE (request_handles(count))
2535  DO i = 1, count
2536  request_handles(i) = array_of_requests(i)%handle
2537  END DO
2538 
2539  CALL mpi_testany(count, request_handles, index, flag, status, ierr)
2540 
2541  DO i = 1, count
2542  array_of_requests(i)%handle = request_handles(i)
2543  END DO
2544 
2545  END SUBROUTINE mpi_testany_internal
2546 #endif
2547 
2548 ! **************************************************************************************************
2549 !> \brief the direct way to split a communicator each color is a sub_comm,
2550 !> the rank order is according to the order in the orig comm
2551 !> \param comm ...
2552 !> \param sub_comm ...
2553 !> \param color ...
2554 !> \param key ...
2555 !> \author Joost VandeVondele
2556 ! **************************************************************************************************
2557  SUBROUTINE mp_comm_split_direct(comm, sub_comm, color, key)
2558  CLASS(mp_comm_type), INTENT(in) :: comm
2559  CLASS(mp_comm_type), INTENT(OUT) :: sub_comm
2560  INTEGER, INTENT(in) :: color
2561  INTEGER, INTENT(in), OPTIONAL :: key
2562 
2563  CHARACTER(len=*), PARAMETER :: routinen = 'mp_comm_split_direct'
2564 
2565  INTEGER :: handle
2566 #if defined(__parallel)
2567  INTEGER :: ierr, my_key
2568 #endif
2569 
2570  CALL mp_timeset(routinen, handle)
2571 
2572 #if defined(__parallel)
2573  my_key = 0
2574  IF (PRESENT(key)) my_key = key
2575  CALL mpi_comm_split(comm%handle, color, my_key, sub_comm%handle, ierr)
2576  IF (ierr /= mpi_success) CALL mp_stop(ierr, routinen)
2577  CALL add_perf(perf_id=10, count=1)
2578 #else
2579  sub_comm%handle = mp_comm_default_handle
2580  mark_used(comm)
2581  mark_used(color)
2582  mark_used(key)
2583 #endif
2584  debug_comm_count = debug_comm_count + 1
2585  CALL sub_comm%init()
2586  CALL mp_timestop(handle)
2587 
2588  END SUBROUTINE mp_comm_split_direct
2589 ! **************************************************************************************************
2590 !> \brief splits the given communicator in group in subgroups trying to organize
2591 !> them in a way that the communication within each subgroup is
2592 !> efficient (but not necessarily the communication between subgroups)
2593 !> \param comm the mpi communicator that you want to split
2594 !> \param sub_comm the communicator for the subgroup (created, needs to be freed later)
2595 !> \param ngroups actual number of groups
2596 !> \param group_distribution input : allocated with array with the nprocs entries (0 .. nprocs-1)
2597 !> \param subgroup_min_size the minimum size of the subgroup
2598 !> \param n_subgroups the number of subgroups wanted
2599 !> \param group_partition n_subgroups sized array containing the number of cpus wanted per group.
2600 !> should match the total number of cpus (only used if present and associated) (0..ngroups-1)
2601 !> \param stride create groups using a stride (default=1) through the ranks of the comm to be split.
2602 !> \par History
2603 !> 10.2003 created [fawzi]
2604 !> 02.2004 modified [Joost VandeVondele]
2605 !> \author Fawzi Mohamed
2606 !> \note
2607 !> at least one of subgroup_min_size and n_subgroups is needed,
2608 !> the other default to the value needed to use most processors.
2609 !> if less cpus are present than needed for subgroup min size, n_subgroups,
2610 !> just one comm is created that contains all cpus
2611 ! **************************************************************************************************
2612  SUBROUTINE mp_comm_split(comm, sub_comm, ngroups, group_distribution, &
2613  subgroup_min_size, n_subgroups, group_partition, stride)
2614  CLASS(mp_comm_type), INTENT(in) :: comm
2615  CLASS(mp_comm_type), INTENT(out) :: sub_comm
2616  INTEGER, INTENT(out) :: ngroups
2617  INTEGER, DIMENSION(0:), INTENT(INOUT) :: group_distribution
2618  INTEGER, INTENT(in), OPTIONAL :: subgroup_min_size, n_subgroups
2619  INTEGER, DIMENSION(0:), INTENT(IN), OPTIONAL :: group_partition
2620  INTEGER, OPTIONAL, INTENT(IN) :: stride
2621 
2622  CHARACTER(LEN=*), PARAMETER :: routinen = 'mp_comm_split', &
2623  routinep = modulen//':'//routinen
2624 
2625  INTEGER :: handle, mepos, nnodes
2626 #if defined(__parallel)
2627  INTEGER :: color, i, ierr, j, k, &
2628  my_subgroup_min_size, &
2629  istride, local_stride, irank
2630  INTEGER, DIMENSION(:), ALLOCATABLE :: rank_permutation
2631 #endif
2632 
2633  CALL mp_timeset(routinen, handle)
2634 
2635  ! actual number of groups
2636 
2637  IF (.NOT. PRESENT(subgroup_min_size) .AND. .NOT. PRESENT(n_subgroups)) THEN
2638  cpabort(routinep//" missing arguments")
2639  END IF
2640  IF (PRESENT(subgroup_min_size) .AND. PRESENT(n_subgroups)) THEN
2641  cpabort(routinep//" too many arguments")
2642  END IF
2643 
2644  CALL comm%get_size(nnodes)
2645  CALL comm%get_rank(mepos)
2646 
2647  IF (ubound(group_distribution, 1) .NE. nnodes - 1) THEN
2648  cpabort(routinep//" group_distribution wrong bounds")
2649  END IF
2650 
2651 #if defined(__parallel)
2652  IF (PRESENT(subgroup_min_size)) THEN
2653  IF (subgroup_min_size < 0 .OR. subgroup_min_size > nnodes) THEN
2654  cpabort(routinep//" subgroup_min_size too small or too large")
2655  END IF
2656  ngroups = nnodes/subgroup_min_size
2657  my_subgroup_min_size = subgroup_min_size
2658  ELSE ! n_subgroups
2659  IF (n_subgroups <= 0) THEN
2660  cpabort(routinep//" n_subgroups too small")
2661  END IF
2662  IF (nnodes/n_subgroups > 0) THEN ! we have a least one cpu per group
2663  ngroups = n_subgroups
2664  ELSE ! well, only one group then
2665  ngroups = 1
2666  END IF
2667  my_subgroup_min_size = nnodes/ngroups
2668  END IF
2669 
2670  ! rank_permutation: is a permutation of ranks, so that groups are not necessarily continuous in rank of the master group
2671  ! 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
2672  ! (by setting stride equal to the number of mpi ranks per node), or by sharing a node between two groups (stride 2).
2673  ALLOCATE (rank_permutation(0:nnodes - 1))
2674  local_stride = 1
2675  IF (PRESENT(stride)) local_stride = stride
2676  k = 0
2677  DO istride = 1, local_stride
2678  DO irank = istride - 1, nnodes - 1, local_stride
2679  rank_permutation(k) = irank
2680  k = k + 1
2681  END DO
2682  END DO
2683 
2684  DO i = 0, nnodes - 1
2685  group_distribution(rank_permutation(i)) = min(i/my_subgroup_min_size, ngroups - 1)
2686  END DO
2687  ! even the user gave a partition, see if we can use it to overwrite this choice
2688  IF (PRESENT(group_partition)) THEN
2689  IF (all(group_partition > 0) .AND. (sum(group_partition) .EQ. nnodes) .AND. (ngroups == SIZE(group_partition))) THEN
2690  k = 0
2691  DO i = 0, SIZE(group_partition) - 1
2692  DO j = 1, group_partition(i)
2693  group_distribution(rank_permutation(k)) = i
2694  k = k + 1
2695  END DO
2696  END DO
2697  ELSE
2698  ! just ignore silently as we have reasonable defaults. Probably a warning would not be to bad
2699  END IF
2700  END IF
2701  color = group_distribution(mepos)
2702  CALL mpi_comm_split(comm%handle, color, 0, sub_comm%handle, ierr)
2703  IF (ierr /= mpi_success) CALL mp_stop(ierr, "in "//routinep//" split")
2704 
2705  CALL add_perf(perf_id=10, count=1)
2706 #else
2707  sub_comm%handle = mp_comm_default_handle
2708  group_distribution(0) = 0
2709  ngroups = 1
2710  mark_used(comm)
2711  mark_used(stride)
2712  mark_used(group_partition)
2713 #endif
2714  debug_comm_count = debug_comm_count + 1
2715  CALL sub_comm%init()
2716  CALL mp_timestop(handle)
2717 
2718  END SUBROUTINE mp_comm_split
2719 
2720 ! **************************************************************************************************
2721 !> \brief Get the local rank on the node according to the global communicator
2722 !> \return Node Rank id
2723 !> \author Alfio Lazzaro
2724 ! **************************************************************************************************
2726  result(node_rank)
2727 
2728  INTEGER :: node_rank
2729 
2730  CHARACTER(len=*), PARAMETER :: routinen = 'mp_get_node_global_rank'
2731  INTEGER :: handle
2732 #if defined(__parallel)
2733  INTEGER :: ierr, rank
2734  TYPE(mp_comm_type) :: comm
2735 #endif
2736 
2737  CALL mp_timeset(routinen, handle)
2738 
2739 #if defined(__parallel)
2740  CALL mpi_comm_rank(mpi_comm_world, rank, ierr)
2741  IF (ierr /= mpi_success) CALL mp_stop(ierr, routinen)
2742  CALL mpi_comm_split_type(mpi_comm_world, mpi_comm_type_shared, rank, mpi_info_null, comm%handle, ierr)
2743  IF (ierr /= mpi_success) CALL mp_stop(ierr, routinen)
2744  CALL mpi_comm_rank(comm%handle, node_rank, ierr)
2745  IF (ierr /= mpi_success) CALL mp_stop(ierr, routinen)
2746  CALL mpi_comm_free(comm%handle, ierr)
2747  IF (ierr /= mpi_success) CALL mp_stop(ierr, routinen)
2748 #else
2749  node_rank = 0
2750 #endif
2751  CALL mp_timestop(handle)
2752 
2753  END FUNCTION mp_get_node_global_rank
2754 
2755 ! **************************************************************************************************
2756 !> \brief probes for an incoming message with any tag
2757 !> \param[inout] source the source of the possible incoming message,
2758 !> if MP_ANY_SOURCE it is a blocking one and return value is the source
2759 !> of the next incoming message
2760 !> if source is a different value it is a non-blocking probe returning
2761 !> MP_ANY_SOURCE if there is no incoming message
2762 !> \param[in] comm the communicator
2763 !> \param[out] tag the tag of the incoming message
2764 !> \author Mandes
2765 ! **************************************************************************************************
2766  SUBROUTINE mp_probe(source, comm, tag)
2767  INTEGER, INTENT(INOUT) :: source
2768  CLASS(mp_comm_type), INTENT(IN) :: comm
2769  INTEGER, INTENT(OUT) :: tag
2770 
2771  CHARACTER(len=*), PARAMETER :: routinen = 'mp_probe'
2772 
2773  INTEGER :: handle
2774 #if defined(__parallel)
2775  INTEGER :: ierr
2776  mpi_status_type :: status_single
2777  LOGICAL :: flag
2778 #endif
2779 
2780 ! ---------------------------------------------------------------------------
2781 
2782  CALL mp_timeset(routinen, handle)
2783 
2784 #if defined(__parallel)
2785  IF (source .EQ. mp_any_source) THEN
2786  CALL mpi_probe(mp_any_source, mp_any_tag, comm%handle, status_single, ierr)
2787  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_probe @ mp_probe")
2788  source = status_single mpi_status_extract(mpi_source)
2789  tag = status_single mpi_status_extract(mpi_tag)
2790  ELSE
2791  flag = .false.
2792  CALL mpi_iprobe(source, mp_any_tag, comm%handle, flag, status_single, ierr)
2793  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iprobe @ mp_probe")
2794  IF (flag .EQV. .false.) THEN
2795  source = mp_any_source
2796  tag = -1 !status_single(MPI_TAG) ! in case of flag==false status is undefined
2797  ELSE
2798  tag = status_single mpi_status_extract(mpi_tag)
2799  END IF
2800  END IF
2801 #else
2802  tag = -1
2803  mark_used(comm)
2804  mark_used(source)
2805 #endif
2806  CALL mp_timestop(handle)
2807  END SUBROUTINE mp_probe
2808 
2809 ! **************************************************************************************************
2810 ! Here come the data routines with none of the standard data types.
2811 ! **************************************************************************************************
2812 
2813 ! **************************************************************************************************
2814 !> \brief ...
2815 !> \param msg ...
2816 !> \param source ...
2817 !> \param comm ...
2818 ! **************************************************************************************************
2819  SUBROUTINE mp_bcast_b(msg, source, comm)
2820  LOGICAL, INTENT(INOUT) :: msg
2821  INTEGER, INTENT(IN) :: source
2822  CLASS(mp_comm_type), INTENT(IN) :: comm
2823 
2824  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_b'
2825 
2826  INTEGER :: handle
2827 #if defined(__parallel)
2828  INTEGER :: ierr, msglen
2829 #endif
2830 
2831  CALL mp_timeset(routinen, handle)
2832 
2833 #if defined(__parallel)
2834  msglen = 1
2835  CALL mpi_bcast(msg, msglen, mpi_logical, source, comm%handle, ierr)
2836  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
2837  CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2838 #else
2839  mark_used(msg)
2840  mark_used(source)
2841  mark_used(comm)
2842 #endif
2843  CALL mp_timestop(handle)
2844  END SUBROUTINE mp_bcast_b
2845 
2846 ! **************************************************************************************************
2847 !> \brief ...
2848 !> \param msg ...
2849 !> \param source ...
2850 !> \param comm ...
2851 ! **************************************************************************************************
2852  SUBROUTINE mp_bcast_b_src(msg, comm)
2853  LOGICAL, INTENT(INOUT) :: msg
2854  CLASS(mp_comm_type), INTENT(IN) :: comm
2855 
2856  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_b_src'
2857 
2858  INTEGER :: handle
2859 #if defined(__parallel)
2860  INTEGER :: ierr, msglen
2861 #endif
2862 
2863  CALL mp_timeset(routinen, handle)
2864 
2865 #if defined(__parallel)
2866  msglen = 1
2867  CALL mpi_bcast(msg, msglen, mpi_logical, comm%source, comm%handle, ierr)
2868  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
2869  CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2870 #else
2871  mark_used(msg)
2872  mark_used(comm)
2873 #endif
2874  CALL mp_timestop(handle)
2875  END SUBROUTINE mp_bcast_b_src
2876 
2877 ! **************************************************************************************************
2878 !> \brief ...
2879 !> \param msg ...
2880 !> \param source ...
2881 !> \param comm ...
2882 ! **************************************************************************************************
2883  SUBROUTINE mp_bcast_bv(msg, source, comm)
2884  LOGICAL, CONTIGUOUS, INTENT(INOUT) :: msg(:)
2885  INTEGER, INTENT(IN) :: source
2886  CLASS(mp_comm_type), INTENT(IN) :: comm
2887 
2888  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_bv'
2889 
2890  INTEGER :: handle
2891 #if defined(__parallel)
2892  INTEGER :: ierr, msglen
2893 #endif
2894 
2895  CALL mp_timeset(routinen, handle)
2896 
2897 #if defined(__parallel)
2898  msglen = SIZE(msg)
2899  CALL mpi_bcast(msg, msglen, mpi_logical, source, comm%handle, ierr)
2900  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
2901  CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2902 #else
2903  mark_used(msg)
2904  mark_used(source)
2905  mark_used(comm)
2906 #endif
2907  CALL mp_timestop(handle)
2908  END SUBROUTINE mp_bcast_bv
2909 
2910 ! **************************************************************************************************
2911 !> \brief ...
2912 !> \param msg ...
2913 !> \param comm ...
2914 ! **************************************************************************************************
2915  SUBROUTINE mp_bcast_bv_src(msg, comm)
2916  LOGICAL, CONTIGUOUS, INTENT(INOUT) :: msg(:)
2917  CLASS(mp_comm_type), INTENT(IN) :: comm
2918 
2919  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_bv_src'
2920 
2921  INTEGER :: handle
2922 #if defined(__parallel)
2923  INTEGER :: ierr, msglen
2924 #endif
2925 
2926  CALL mp_timeset(routinen, handle)
2927 
2928 #if defined(__parallel)
2929  msglen = SIZE(msg)
2930  CALL mpi_bcast(msg, msglen, mpi_logical, comm%source, comm%handle, ierr)
2931  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
2932  CALL add_perf(perf_id=2, count=1, msg_size=msglen*loglen)
2933 #else
2934  mark_used(msg)
2935  mark_used(comm)
2936 #endif
2937  CALL mp_timestop(handle)
2938  END SUBROUTINE mp_bcast_bv_src
2939 
2940 ! **************************************************************************************************
2941 !> \brief Non-blocking send of logical vector data
2942 !> \param msgin the input message
2943 !> \param dest the destination processor
2944 !> \param comm the communicator object
2945 !> \param request communication request index
2946 !> \param tag message tag
2947 !> \par History
2948 !> 3.2016 added _bv subroutine [Nico Holmberg]
2949 !> \author fawzi
2950 !> \note see mp_irecv_iv
2951 !> \note
2952 !> arrays can be pointers or assumed shape, but they must be contiguous!
2953 ! **************************************************************************************************
2954  SUBROUTINE mp_isend_bv(msgin, dest, comm, request, tag)
2955  LOGICAL, DIMENSION(:), INTENT(IN) :: msgin
2956  INTEGER, INTENT(IN) :: dest
2957  CLASS(mp_comm_type), INTENT(IN) :: comm
2958  TYPE(mp_request_type), INTENT(out) :: request
2959  INTEGER, INTENT(in), OPTIONAL :: tag
2960 
2961  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_bv'
2962 
2963  INTEGER :: handle
2964 #if defined(__parallel)
2965  INTEGER :: ierr, msglen, my_tag
2966  LOGICAL :: foo(1)
2967 #endif
2968 
2969  CALL mp_timeset(routinen, handle)
2970 
2971 #if defined(__parallel)
2972 #if !defined(__GNUC__) || __GNUC__ >= 9
2973  cpassert(is_contiguous(msgin))
2974 #endif
2975 
2976  my_tag = 0
2977  IF (PRESENT(tag)) my_tag = tag
2978 
2979  msglen = SIZE(msgin, 1)
2980  IF (msglen > 0) THEN
2981  CALL mpi_isend(msgin(1), msglen, mpi_logical, dest, my_tag, &
2982  comm%handle, request%handle, ierr)
2983  ELSE
2984  CALL mpi_isend(foo, msglen, mpi_logical, dest, my_tag, &
2985  comm%handle, request%handle, ierr)
2986  END IF
2987  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
2988 
2989  CALL add_perf(perf_id=11, count=1, msg_size=msglen*loglen)
2990 #else
2991  cpabort("mp_isend called in non parallel case")
2992  mark_used(msgin)
2993  mark_used(dest)
2994  mark_used(comm)
2995  mark_used(tag)
2996  request = mp_request_null
2997 #endif
2998  CALL mp_timestop(handle)
2999  END SUBROUTINE mp_isend_bv
3000 
3001 ! **************************************************************************************************
3002 !> \brief Non-blocking receive of logical vector data
3003 !> \param msgout the received message
3004 !> \param source the source processor
3005 !> \param comm the communicator object
3006 !> \param request communication request index
3007 !> \param tag message tag
3008 !> \par History
3009 !> 3.2016 added _bv subroutine [Nico Holmberg]
3010 !> \author fawzi
3011 !> \note see mp_irecv_iv
3012 !> \note
3013 !> arrays can be pointers or assumed shape, but they must be contiguous!
3014 ! **************************************************************************************************
3015  SUBROUTINE mp_irecv_bv(msgout, source, comm, request, tag)
3016  LOGICAL, DIMENSION(:), INTENT(INOUT) :: msgout
3017  INTEGER, INTENT(IN) :: source
3018  CLASS(mp_comm_type), INTENT(IN) :: comm
3019  TYPE(mp_request_type), INTENT(out) :: request
3020  INTEGER, INTENT(in), OPTIONAL :: tag
3021 
3022  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_bv'
3023 
3024  INTEGER :: handle
3025 #if defined(__parallel)
3026  INTEGER :: ierr, msglen, my_tag
3027  LOGICAL :: foo(1)
3028 #endif
3029 
3030  CALL mp_timeset(routinen, handle)
3031 
3032 #if defined(__parallel)
3033 #if !defined(__GNUC__) || __GNUC__ >= 9
3034  cpassert(is_contiguous(msgout))
3035 #endif
3036 
3037  my_tag = 0
3038  IF (PRESENT(tag)) my_tag = tag
3039 
3040  msglen = SIZE(msgout, 1)
3041  IF (msglen > 0) THEN
3042  CALL mpi_irecv(msgout(1), msglen, mpi_logical, source, my_tag, &
3043  comm%handle, request%handle, ierr)
3044  ELSE
3045  CALL mpi_irecv(foo, msglen, mpi_logical, source, my_tag, &
3046  comm%handle, request%handle, ierr)
3047  END IF
3048  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
3049 
3050  CALL add_perf(perf_id=12, count=1, msg_size=msglen*loglen)
3051 #else
3052  cpabort("mp_irecv called in non parallel case")
3053  mark_used(msgout)
3054  mark_used(source)
3055  mark_used(comm)
3056  mark_used(tag)
3057  request = mp_request_null
3058 #endif
3059  CALL mp_timestop(handle)
3060  END SUBROUTINE mp_irecv_bv
3061 
3062 ! **************************************************************************************************
3063 !> \brief Non-blocking send of rank-3 logical data
3064 !> \param msgin the input message
3065 !> \param dest the destination processor
3066 !> \param comm the communicator object
3067 !> \param request communication request index
3068 !> \param tag message tag
3069 !> \par History
3070 !> 2.2016 added _bm3 subroutine [Nico Holmberg]
3071 !> \author fawzi
3072 !> \note see mp_irecv_iv
3073 !> \note
3074 !> arrays can be pointers or assumed shape, but they must be contiguous!
3075 ! **************************************************************************************************
3076  SUBROUTINE mp_isend_bm3(msgin, dest, comm, request, tag)
3077  LOGICAL, DIMENSION(:, :, :), INTENT(INOUT) :: msgin
3078  INTEGER, INTENT(IN) :: dest
3079  CLASS(mp_comm_type), INTENT(IN) :: comm
3080  TYPE(mp_request_type), INTENT(out) :: request
3081  INTEGER, INTENT(in), OPTIONAL :: tag
3082 
3083  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_bm3'
3084 
3085  INTEGER :: handle
3086 #if defined(__parallel)
3087  INTEGER :: ierr, msglen, my_tag
3088  LOGICAL :: foo(1)
3089 #endif
3090 
3091  CALL mp_timeset(routinen, handle)
3092 
3093 #if defined(__parallel)
3094 #if !defined(__GNUC__) || __GNUC__ >= 9
3095  cpassert(is_contiguous(msgin))
3096 #endif
3097 
3098  my_tag = 0
3099  IF (PRESENT(tag)) my_tag = tag
3100 
3101  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
3102  IF (msglen > 0) THEN
3103  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_logical, dest, my_tag, &
3104  comm%handle, request%handle, ierr)
3105  ELSE
3106  CALL mpi_isend(foo, msglen, mpi_logical, dest, my_tag, &
3107  comm%handle, request%handle, ierr)
3108  END IF
3109  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
3110 
3111  CALL add_perf(perf_id=11, count=1, msg_size=msglen*loglen)
3112 #else
3113  cpabort("mp_isend called in non parallel case")
3114  mark_used(msgin)
3115  mark_used(dest)
3116  mark_used(comm)
3117  mark_used(tag)
3118  request = mp_request_null
3119 #endif
3120  CALL mp_timestop(handle)
3121  END SUBROUTINE mp_isend_bm3
3122 
3123 ! **************************************************************************************************
3124 !> \brief Non-blocking receive of rank-3 logical data
3125 !> \param msgout the received message
3126 !> \param source the source processor
3127 !> \param comm the communicator object
3128 !> \param request communication request index
3129 !> \param tag message tag
3130 !> \par History
3131 !> 2.2016 added _bm3 subroutine [Nico Holmberg]
3132 !> \author fawzi
3133 !> \note see mp_irecv_iv
3134 !> \note
3135 !> arrays can be pointers or assumed shape, but they must be contiguous!
3136 ! **************************************************************************************************
3137  SUBROUTINE mp_irecv_bm3(msgout, source, comm, request, tag)
3138  LOGICAL, DIMENSION(:, :, :), INTENT(INOUT) :: msgout
3139  INTEGER, INTENT(IN) :: source
3140  CLASS(mp_comm_type), INTENT(IN) :: comm
3141  TYPE(mp_request_type), INTENT(out) :: request
3142  INTEGER, INTENT(in), OPTIONAL :: tag
3143 
3144  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_bm3'
3145 
3146  INTEGER :: handle
3147 #if defined(__parallel)
3148  INTEGER :: ierr, msglen, my_tag
3149  LOGICAL :: foo(1)
3150 #endif
3151 
3152  CALL mp_timeset(routinen, handle)
3153 
3154 #if defined(__parallel)
3155 #if !defined(__GNUC__) || __GNUC__ >= 9
3156  cpassert(is_contiguous(msgout))
3157 #endif
3158 
3159  my_tag = 0
3160  IF (PRESENT(tag)) my_tag = tag
3161 
3162  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
3163  IF (msglen > 0) THEN
3164  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_logical, source, my_tag, &
3165  comm%handle, request%handle, ierr)
3166  ELSE
3167  CALL mpi_irecv(foo, msglen, mpi_logical, source, my_tag, &
3168  comm%handle, request%handle, ierr)
3169  END IF
3170  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
3171 
3172  CALL add_perf(perf_id=12, count=1, msg_size=msglen*loglen)
3173 #else
3174  cpabort("mp_irecv called in non parallel case")
3175  mark_used(msgout)
3176  mark_used(source)
3177  mark_used(comm)
3178  mark_used(request)
3179  mark_used(tag)
3180  request = mp_request_null
3181 #endif
3182  CALL mp_timestop(handle)
3183  END SUBROUTINE mp_irecv_bm3
3184 
3185 ! **************************************************************************************************
3186 !> \brief ...
3187 !> \param msg ...
3188 !> \param source ...
3189 !> \param comm ...
3190 ! **************************************************************************************************
3191  SUBROUTINE mp_bcast_av(msg, source, comm)
3192  CHARACTER(LEN=*), INTENT(INOUT) :: msg
3193  INTEGER, INTENT(IN) :: source
3194  CLASS(mp_comm_type), INTENT(IN) :: comm
3195 
3196  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_av'
3197 
3198  INTEGER :: handle
3199 #if defined(__parallel)
3200  INTEGER :: i, ierr, msglen
3201  INTEGER, DIMENSION(:), ALLOCATABLE :: imsg
3202 #endif
3203 
3204  CALL mp_timeset(routinen, handle)
3205 
3206 #if defined(__parallel)
3207 
3208  IF (comm%mepos == source) msglen = len_trim(msg)
3209 
3210  CALL comm%bcast(msglen, source)
3211  ! this is a workaround to avoid problems on the T3E
3212  ! at the moment we have a data alignment error when trying to
3213  ! broadcast characters on the T3E (not always!)
3214  ! JH 19/3/99 on galileo
3215  ! CALL mpi_bcast(msg,msglen,MPI_CHARACTER,source,gid%handle,ierr)
3216  ALLOCATE (imsg(1:msglen))
3217  DO i = 1, msglen
3218  imsg(i) = ichar(msg(i:i))
3219  END DO
3220  CALL mpi_bcast(imsg, msglen, mpi_integer, source, comm%handle, ierr)
3221  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
3222  msg = ""
3223  DO i = 1, msglen
3224  msg(i:i) = char(imsg(i))
3225  END DO
3226  DEALLOCATE (imsg)
3227  CALL add_perf(perf_id=2, count=1, msg_size=msglen*charlen)
3228 #else
3229  mark_used(msg)
3230  mark_used(source)
3231  mark_used(comm)
3232 #endif
3233  CALL mp_timestop(handle)
3234  END SUBROUTINE mp_bcast_av
3235 
3236 ! **************************************************************************************************
3237 !> \brief ...
3238 !> \param msg ...
3239 !> \param comm ...
3240 ! **************************************************************************************************
3241  SUBROUTINE mp_bcast_av_src(msg, comm)
3242  CHARACTER(LEN=*), INTENT(INOUT) :: msg
3243  CLASS(mp_comm_type), INTENT(IN) :: comm
3244 
3245  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_av_src'
3246 
3247  INTEGER :: handle
3248 #if defined(__parallel)
3249  INTEGER :: i, ierr, msglen
3250  INTEGER, DIMENSION(:), ALLOCATABLE :: imsg
3251 #endif
3252 
3253  CALL mp_timeset(routinen, handle)
3254 
3255 #if defined(__parallel)
3256 
3257  IF (comm%is_source()) msglen = len_trim(msg)
3258 
3259  CALL comm%bcast(msglen, comm%source)
3260  ! this is a workaround to avoid problems on the T3E
3261  ! at the moment we have a data alignment error when trying to
3262  ! broadcast characters on the T3E (not always!)
3263  ! JH 19/3/99 on galileo
3264  ! CALL mpi_bcast(msg,msglen,MPI_CHARACTER,source,gid%handle,ierr)
3265  ALLOCATE (imsg(1:msglen))
3266  DO i = 1, msglen
3267  imsg(i) = ichar(msg(i:i))
3268  END DO
3269  CALL mpi_bcast(imsg, msglen, mpi_integer, comm%source, comm%handle, ierr)
3270  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
3271  msg = ""
3272  DO i = 1, msglen
3273  msg(i:i) = char(imsg(i))
3274  END DO
3275  DEALLOCATE (imsg)
3276  CALL add_perf(perf_id=2, count=1, msg_size=msglen*charlen)
3277 #else
3278  mark_used(msg)
3279  mark_used(comm)
3280 #endif
3281  CALL mp_timestop(handle)
3282  END SUBROUTINE mp_bcast_av_src
3283 
3284 ! **************************************************************************************************
3285 !> \brief ...
3286 !> \param msg ...
3287 !> \param source ...
3288 !> \param comm ...
3289 ! **************************************************************************************************
3290  SUBROUTINE mp_bcast_am(msg, source, comm)
3291  CHARACTER(LEN=*), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3292  INTEGER, INTENT(IN) :: source
3293  CLASS(mp_comm_type), INTENT(IN) :: comm
3294 
3295  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_am'
3296 
3297  INTEGER :: handle
3298 #if defined(__parallel)
3299  INTEGER :: i, ierr, j, k, msglen, msgsiz
3300  INTEGER, ALLOCATABLE :: imsg(:), imsglen(:)
3301 #endif
3302 
3303  CALL mp_timeset(routinen, handle)
3304 
3305 #if defined(__parallel)
3306  msgsiz = SIZE(msg)
3307  ! Determine size of the minimum array of integers to broadcast the string
3308  ALLOCATE (imsglen(1:msgsiz))
3309  IF (comm%mepos == source) THEN
3310  DO j = 1, msgsiz
3311  imsglen(j) = len_trim(msg(j))
3312  END DO
3313  END IF
3314  CALL comm%bcast(imsglen, source)
3315  msglen = sum(imsglen)
3316  ! this is a workaround to avoid problems on the T3E
3317  ! at the moment we have a data alignment error when trying to
3318  ! broadcast characters on the T3E (not always!)
3319  ! JH 19/3/99 on galileo
3320  ALLOCATE (imsg(1:msglen))
3321  k = 0
3322  DO j = 1, msgsiz
3323  DO i = 1, imsglen(j)
3324  k = k + 1
3325  imsg(k) = ichar(msg(j) (i:i))
3326  END DO
3327  END DO
3328  CALL mpi_bcast(imsg, msglen, mpi_integer, source, comm%handle, ierr)
3329  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
3330  msg = ""
3331  k = 0
3332  DO j = 1, msgsiz
3333  DO i = 1, imsglen(j)
3334  k = k + 1
3335  msg(j) (i:i) = char(imsg(k))
3336  END DO
3337  END DO
3338  DEALLOCATE (imsg)
3339  DEALLOCATE (imsglen)
3340  CALL add_perf(perf_id=2, count=1, msg_size=msglen*charlen*msgsiz)
3341 #else
3342  mark_used(msg)
3343  mark_used(source)
3344  mark_used(comm)
3345 #endif
3346  CALL mp_timestop(handle)
3347  END SUBROUTINE mp_bcast_am
3348 
3349  SUBROUTINE mp_bcast_am_src(msg, comm)
3350  CHARACTER(LEN=*), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3351  CLASS(mp_comm_type), INTENT(IN) :: comm
3352 
3353  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_am_src'
3354 
3355  INTEGER :: handle
3356 #if defined(__parallel)
3357  INTEGER :: i, ierr, j, k, msglen, msgsiz
3358  INTEGER, ALLOCATABLE :: imsg(:), imsglen(:)
3359 #endif
3360 
3361  CALL mp_timeset(routinen, handle)
3362 
3363 #if defined(__parallel)
3364  msgsiz = SIZE(msg)
3365  ! Determine size of the minimum array of integers to broadcast the string
3366  ALLOCATE (imsglen(1:msgsiz))
3367  DO j = 1, msgsiz
3368  imsglen(j) = len_trim(msg(j))
3369  END DO
3370  CALL comm%bcast(imsglen, comm%source)
3371  msglen = sum(imsglen)
3372  ! this is a workaround to avoid problems on the T3E
3373  ! at the moment we have a data alignment error when trying to
3374  ! broadcast characters on the T3E (not always!)
3375  ! JH 19/3/99 on galileo
3376  ALLOCATE (imsg(1:msglen))
3377  k = 0
3378  DO j = 1, msgsiz
3379  DO i = 1, imsglen(j)
3380  k = k + 1
3381  imsg(k) = ichar(msg(j) (i:i))
3382  END DO
3383  END DO
3384  CALL mpi_bcast(imsg, msglen, mpi_integer, comm%source, comm%handle, ierr)
3385  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
3386  msg = ""
3387  k = 0
3388  DO j = 1, msgsiz
3389  DO i = 1, imsglen(j)
3390  k = k + 1
3391  msg(j) (i:i) = char(imsg(k))
3392  END DO
3393  END DO
3394  DEALLOCATE (imsg)
3395  DEALLOCATE (imsglen)
3396  CALL add_perf(perf_id=2, count=1, msg_size=msglen*charlen*msgsiz)
3397 #else
3398  mark_used(msg)
3399  mark_used(comm)
3400 #endif
3401  CALL mp_timestop(handle)
3402  END SUBROUTINE mp_bcast_am_src
3403 
3404 ! **************************************************************************************************
3405 !> \brief Finds the location of the minimal element in a vector.
3406 !> \param[in,out] msg Find location of maximum element among these
3407 !> data (input).
3408 !> \param[in] comm Message passing environment identifier
3409 !> \par MPI mapping
3410 !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3411 !> \par Invalid data types
3412 !> This routine is invalid for (int_8) data!
3413 ! **************************************************************************************************
3414  SUBROUTINE mp_minloc_dv(msg, comm)
3415  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3416  CLASS(mp_comm_type), INTENT(IN) :: comm
3417 
3418  CHARACTER(len=*), PARAMETER :: routinen = 'mp_minloc_dv'
3419 
3420  INTEGER :: handle
3421 #if defined(__parallel)
3422  INTEGER :: ierr, msglen
3423  REAL(kind=real_8), ALLOCATABLE :: res(:)
3424 #endif
3425 
3426  IF ("d" .EQ. "l" .AND. real_8 .EQ. int_8) THEN
3427  cpabort("Minimal location not available with long integers @ "//routinen)
3428  END IF
3429  CALL mp_timeset(routinen, handle)
3430 
3431 #if defined(__parallel)
3432  msglen = SIZE(msg)
3433  ALLOCATE (res(1:msglen), stat=ierr)
3434  IF (ierr /= 0) &
3435  cpabort("allocate @ "//routinen)
3436  CALL mpi_allreduce(msg, res, msglen/2, mpi_2double_precision, mpi_minloc, comm%handle, ierr)
3437  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3438  msg = res
3439  DEALLOCATE (res)
3440  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
3441 #else
3442  mark_used(msg)
3443  mark_used(comm)
3444 #endif
3445  CALL mp_timestop(handle)
3446  END SUBROUTINE mp_minloc_dv
3447 
3448 ! **************************************************************************************************
3449 !> \brief Finds the location of the minimal element in a vector.
3450 !> \param[in,out] msg Find location of maximum element among these
3451 !> data (input).
3452 !> \param[in] comm Message passing environment identifier
3453 !> \par MPI mapping
3454 !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3455 !> \par Invalid data types
3456 !> This routine is invalid for (int_8) data!
3457 ! **************************************************************************************************
3458  SUBROUTINE mp_minloc_iv(msg, comm)
3459  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3460  CLASS(mp_comm_type), INTENT(IN) :: comm
3461 
3462  CHARACTER(len=*), PARAMETER :: routinen = 'mp_minloc_iv'
3463 
3464  INTEGER :: handle
3465 #if defined(__parallel)
3466  INTEGER :: ierr, msglen
3467  INTEGER(KIND=int_4), ALLOCATABLE :: res(:)
3468 #endif
3469 
3470  IF ("i" .EQ. "l" .AND. int_4 .EQ. int_8) THEN
3471  cpabort("Minimal location not available with long integers @ "//routinen)
3472  END IF
3473  CALL mp_timeset(routinen, handle)
3474 
3475 #if defined(__parallel)
3476  msglen = SIZE(msg)
3477  ALLOCATE (res(1:msglen))
3478  CALL mpi_allreduce(msg, res, msglen/2, mpi_2integer, mpi_minloc, comm%handle, ierr)
3479  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3480  msg = res
3481  DEALLOCATE (res)
3482  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
3483 #else
3484  mark_used(msg)
3485  mark_used(comm)
3486 #endif
3487  CALL mp_timestop(handle)
3488  END SUBROUTINE mp_minloc_iv
3489 
3490 ! **************************************************************************************************
3491 !> \brief Finds the location of the minimal element in a vector.
3492 !> \param[in,out] msg Find location of maximum element among these
3493 !> data (input).
3494 !> \param[in] comm Message passing environment identifier
3495 !> \par MPI mapping
3496 !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3497 !> \par Invalid data types
3498 !> This routine is invalid for (int_8) data!
3499 ! **************************************************************************************************
3500  SUBROUTINE mp_minloc_lv(msg, comm)
3501  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3502  CLASS(mp_comm_type), INTENT(IN) :: comm
3503 
3504  CHARACTER(len=*), PARAMETER :: routinen = 'mp_minloc_lv'
3505 
3506  INTEGER :: handle
3507 #if defined(__parallel)
3508  INTEGER :: ierr, msglen
3509  INTEGER(KIND=int_8), ALLOCATABLE :: res(:)
3510 #endif
3511 
3512  IF ("l" .EQ. "l" .AND. int_8 .EQ. int_8) THEN
3513  cpabort("Minimal location not available with long integers @ "//routinen)
3514  END IF
3515  CALL mp_timeset(routinen, handle)
3516 
3517 #if defined(__parallel)
3518  msglen = SIZE(msg)
3519  ALLOCATE (res(1:msglen))
3520  CALL mpi_allreduce(msg, res, msglen/2, mpi_integer8, mpi_minloc, comm%handle, ierr)
3521  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3522  msg = res
3523  DEALLOCATE (res)
3524  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
3525 #else
3526  mark_used(msg)
3527  mark_used(comm)
3528 #endif
3529  CALL mp_timestop(handle)
3530  END SUBROUTINE mp_minloc_lv
3531 
3532 ! **************************************************************************************************
3533 !> \brief Finds the location of the minimal element in a vector.
3534 !> \param[in,out] msg Find location of maximum element among these
3535 !> data (input).
3536 !> \param[in] comm Message passing environment identifier
3537 !> \par MPI mapping
3538 !> mpi_allreduce with the MPI_MINLOC reduction function identifier
3539 !> \par Invalid data types
3540 !> This routine is invalid for (int_8) data!
3541 ! **************************************************************************************************
3542  SUBROUTINE mp_minloc_rv(msg, comm)
3543  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3544  CLASS(mp_comm_type), INTENT(IN) :: comm
3545 
3546  CHARACTER(len=*), PARAMETER :: routinen = 'mp_minloc_rv'
3547 
3548  INTEGER :: handle
3549 #if defined(__parallel)
3550  INTEGER :: ierr, msglen
3551  REAL(kind=real_4), ALLOCATABLE :: res(:)
3552 #endif
3553 
3554  IF ("r" .EQ. "l" .AND. real_4 .EQ. int_8) THEN
3555  cpabort("Minimal location not available with long integers @ "//routinen)
3556  END IF
3557  CALL mp_timeset(routinen, handle)
3558 
3559 #if defined(__parallel)
3560  msglen = SIZE(msg)
3561  ALLOCATE (res(1:msglen))
3562  CALL mpi_allreduce(msg, res, msglen/2, mpi_2real, mpi_minloc, comm%handle, ierr)
3563  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3564  msg = res
3565  DEALLOCATE (res)
3566  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
3567 #else
3568  mark_used(msg)
3569  mark_used(comm)
3570 #endif
3571  CALL mp_timestop(handle)
3572  END SUBROUTINE mp_minloc_rv
3573 
3574 ! **************************************************************************************************
3575 !> \brief Finds the location of the maximal element in a vector.
3576 !> \param[in,out] msg Find location of maximum element among these
3577 !> data (input).
3578 !> \param[in] comm Message passing environment identifier
3579 !> \par MPI mapping
3580 !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3581 !> \par Invalid data types
3582 !> This routine is invalid for (int_8) data!
3583 ! **************************************************************************************************
3584  SUBROUTINE mp_maxloc_dv(msg, comm)
3585  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3586  CLASS(mp_comm_type), INTENT(IN) :: comm
3587 
3588  CHARACTER(len=*), PARAMETER :: routinen = 'mp_maxloc_dv'
3589 
3590  INTEGER :: handle
3591 #if defined(__parallel)
3592  INTEGER :: ierr, msglen
3593  REAL(kind=real_8), ALLOCATABLE :: res(:)
3594 #endif
3595 
3596  IF ("d" .EQ. "l" .AND. real_8 .EQ. int_8) THEN
3597  cpabort("Maximal location not available with long integers @ "//routinen)
3598  END IF
3599  CALL mp_timeset(routinen, handle)
3600 
3601 #if defined(__parallel)
3602  msglen = SIZE(msg)
3603  ALLOCATE (res(1:msglen))
3604  CALL mpi_allreduce(msg, res, msglen/2, mpi_2double_precision, mpi_maxloc, comm%handle, ierr)
3605  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3606  msg = res
3607  DEALLOCATE (res)
3608  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
3609 #else
3610  mark_used(msg)
3611  mark_used(comm)
3612 #endif
3613  CALL mp_timestop(handle)
3614  END SUBROUTINE mp_maxloc_dv
3615 
3616 ! **************************************************************************************************
3617 !> \brief Finds the location of the maximal element in a vector.
3618 !> \param[in,out] msg Find location of maximum element among these
3619 !> data (input).
3620 !> \param[in] comm Message passing environment identifier
3621 !> \par MPI mapping
3622 !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3623 !> \par Invalid data types
3624 !> This routine is invalid for (int_8) data!
3625 ! **************************************************************************************************
3626  SUBROUTINE mp_maxloc_iv(msg, comm)
3627  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3628  CLASS(mp_comm_type), INTENT(IN) :: comm
3629 
3630  CHARACTER(len=*), PARAMETER :: routinen = 'mp_maxloc_iv'
3631 
3632  INTEGER :: handle
3633 #if defined(__parallel)
3634  INTEGER :: ierr, msglen
3635  INTEGER(KIND=int_4), ALLOCATABLE :: res(:)
3636 #endif
3637 
3638  IF ("i" .EQ. "l" .AND. int_4 .EQ. int_8) THEN
3639  cpabort("Maximal location not available with long integers @ "//routinen)
3640  END IF
3641  CALL mp_timeset(routinen, handle)
3642 
3643 #if defined(__parallel)
3644  msglen = SIZE(msg)
3645  ALLOCATE (res(1:msglen))
3646  CALL mpi_allreduce(msg, res, msglen/2, mpi_2integer, mpi_maxloc, comm%handle, ierr)
3647  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3648  msg = res
3649  DEALLOCATE (res)
3650  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
3651 #else
3652  mark_used(msg)
3653  mark_used(comm)
3654 #endif
3655  CALL mp_timestop(handle)
3656  END SUBROUTINE mp_maxloc_iv
3657 
3658 ! **************************************************************************************************
3659 !> \brief Finds the location of the maximal element in a vector.
3660 !> \param[in,out] msg Find location of maximum element among these
3661 !> data (input).
3662 !> \param[in] comm Message passing environment identifier
3663 !> \par MPI mapping
3664 !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3665 !> \par Invalid data types
3666 !> This routine is invalid for (int_8) data!
3667 ! **************************************************************************************************
3668  SUBROUTINE mp_maxloc_lv(msg, comm)
3669  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3670  CLASS(mp_comm_type), INTENT(IN) :: comm
3671 
3672  CHARACTER(len=*), PARAMETER :: routinen = 'mp_maxloc_lv'
3673 
3674  INTEGER :: handle
3675 #if defined(__parallel)
3676  INTEGER :: ierr, msglen
3677  INTEGER(KIND=int_8), ALLOCATABLE :: res(:)
3678 #endif
3679 
3680  IF ("l" .EQ. "l" .AND. int_8 .EQ. int_8) THEN
3681  cpabort("Maximal location not available with long integers @ "//routinen)
3682  END IF
3683  CALL mp_timeset(routinen, handle)
3684 
3685 #if defined(__parallel)
3686  msglen = SIZE(msg)
3687  ALLOCATE (res(1:msglen))
3688  CALL mpi_allreduce(msg, res, msglen/2, mpi_integer8, mpi_maxloc, comm%handle, ierr)
3689  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3690  msg = res
3691  DEALLOCATE (res)
3692  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
3693 #else
3694  mark_used(msg)
3695  mark_used(comm)
3696 #endif
3697  CALL mp_timestop(handle)
3698  END SUBROUTINE mp_maxloc_lv
3699 
3700 ! **************************************************************************************************
3701 !> \brief Finds the location of the maximal element in a vector.
3702 !> \param[in,out] msg Find location of maximum element among these
3703 !> data (input).
3704 !> \param[in] comm Message passing environment identifier
3705 !> \par MPI mapping
3706 !> mpi_allreduce with the MPI_MAXLOC reduction function identifier
3707 !> \par Invalid data types
3708 !> This routine is invalid for (int_8) data!
3709 ! **************************************************************************************************
3710  SUBROUTINE mp_maxloc_rv(msg, comm)
3711  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
3712  CLASS(mp_comm_type), INTENT(IN) :: comm
3713 
3714  CHARACTER(len=*), PARAMETER :: routinen = 'mp_maxloc_rv'
3715 
3716  INTEGER :: handle
3717 #if defined(__parallel)
3718  INTEGER :: ierr, msglen
3719  REAL(kind=real_4), ALLOCATABLE :: res(:)
3720 #endif
3721 
3722  IF ("r" .EQ. "l" .AND. real_4 .EQ. int_8) THEN
3723  cpabort("Maximal location not available with long integers @ "//routinen)
3724  END IF
3725  CALL mp_timeset(routinen, handle)
3726 
3727 #if defined(__parallel)
3728  msglen = SIZE(msg)
3729  ALLOCATE (res(1:msglen))
3730  CALL mpi_allreduce(msg, res, msglen/2, mpi_2real, mpi_maxloc, comm%handle, ierr)
3731  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3732  msg = res
3733  DEALLOCATE (res)
3734  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
3735 #else
3736  mark_used(msg)
3737  mark_used(comm)
3738 #endif
3739  CALL mp_timestop(handle)
3740  END SUBROUTINE mp_maxloc_rv
3741 
3742 ! **************************************************************************************************
3743 !> \brief Logical OR reduction
3744 !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3745 !> and resultant inclusive disjunction (output)
3746 !> \param[in] comm Message passing environment identifier
3747 !> \par MPI mapping
3748 !> mpi_allreduce
3749 ! **************************************************************************************************
3750  SUBROUTINE mp_sum_b(msg, comm)
3751  LOGICAL, INTENT(INOUT) :: msg
3752  CLASS(mp_comm_type), INTENT(IN) :: comm
3753 
3754  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_b'
3755 
3756  INTEGER :: handle
3757 #if defined(__parallel)
3758  INTEGER :: ierr, msglen
3759 #endif
3760 
3761  CALL mp_timeset(routinen, handle)
3762 #if defined(__parallel)
3763  msglen = 1
3764  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_logical, mpi_lor, comm%handle, ierr)
3765  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3766 #else
3767  mark_used(msg)
3768  mark_used(comm)
3769 #endif
3770  CALL mp_timestop(handle)
3771  END SUBROUTINE mp_sum_b
3772 
3773 ! **************************************************************************************************
3774 !> \brief Logical OR reduction
3775 !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3776 !> and resultant inclusive disjunction (output)
3777 !> \param[in] comm Message passing environment identifier
3778 !> \par MPI mapping
3779 !> mpi_allreduce
3780 ! **************************************************************************************************
3781  SUBROUTINE mp_sum_bv(msg, comm)
3782  LOGICAL, DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: msg
3783  CLASS(mp_comm_type), INTENT(IN) :: comm
3784 
3785  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_bv'
3786 
3787  INTEGER :: handle
3788 #if defined(__parallel)
3789  INTEGER :: ierr, msglen
3790 #endif
3791 
3792  CALL mp_timeset(routinen, handle)
3793 #if defined(__parallel)
3794  msglen = SIZE(msg)
3795  IF (msglen .GT. 0) THEN
3796  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_logical, mpi_lor, comm%handle, ierr)
3797  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3798  END IF
3799 #else
3800  mark_used(msg)
3801  mark_used(comm)
3802 #endif
3803  CALL mp_timestop(handle)
3804  END SUBROUTINE mp_sum_bv
3805 
3806 ! **************************************************************************************************
3807 !> \brief Logical OR reduction
3808 !> \param[in,out] msg Datum to perform inclusive disjunction (input)
3809 !> and resultant inclusive disjunction (output)
3810 !> \param[in] comm Message passing environment identifier
3811 !> \param request ...
3812 !> \par MPI mapping
3813 !> mpi_allreduce
3814 ! **************************************************************************************************
3815  SUBROUTINE mp_isum_bv(msg, comm, request)
3816  LOGICAL, DIMENSION(:), INTENT(INOUT) :: msg
3817  CLASS(mp_comm_type), INTENT(IN) :: comm
3818  TYPE(mp_request_type), INTENT(INOUT) :: request
3819 
3820  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_bv'
3821 
3822  INTEGER :: handle
3823 #if defined(__parallel)
3824  INTEGER :: ierr, msglen
3825 #endif
3826 
3827  CALL mp_timeset(routinen, handle)
3828 #if defined(__parallel)
3829  msglen = SIZE(msg)
3830 #if !defined(__GNUC__) || __GNUC__ >= 9
3831  cpassert(is_contiguous(msg))
3832 #endif
3833 
3834  IF (msglen .GT. 0) THEN
3835  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_logical, mpi_lor, comm%handle, request%handle, ierr)
3836  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
3837  ELSE
3838  request = mp_request_null
3839  END IF
3840 #else
3841  mark_used(msg)
3842  mark_used(comm)
3843  request = mp_request_null
3844 #endif
3845  CALL mp_timestop(handle)
3846  END SUBROUTINE mp_isum_bv
3847 
3848 ! **************************************************************************************************
3849 !> \brief Get Version of the MPI Library (MPI 3)
3850 !> \param[out] version Version of the library,
3851 !> declared as CHARACTER(LEN=mp_max_library_version_string)
3852 !> \param[out] resultlen Length (in printable characters) of
3853 !> the result returned in version (integer)
3854 ! **************************************************************************************************
3855  SUBROUTINE mp_get_library_version(version, resultlen)
3856  CHARACTER(len=*), INTENT(OUT) :: version
3857  INTEGER, INTENT(OUT) :: resultlen
3858 
3859 #if defined(__parallel)
3860  INTEGER :: ierr
3861 #endif
3862 
3863  version = ''
3864 
3865 #if defined(__parallel)
3866  ierr = 0
3867  CALL mpi_get_library_version(version, resultlen, ierr)
3868  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_get_library_version @ mp_get_library_version")
3869 #else
3870  resultlen = 0
3871 #endif
3872  END SUBROUTINE mp_get_library_version
3873 
3874 ! **************************************************************************************************
3875 !> \brief Opens a file
3876 !> \param[in] groupid message passing environment identifier
3877 !> \param[out] fh file handle (file storage unit)
3878 !> \param[in] filepath path to the file
3879 !> \param amode_status access mode
3880 !> \param info ...
3881 !> \par MPI-I/O mapping mpi_file_open
3882 !> \par STREAM-I/O mapping OPEN
3883 !>
3884 !> \param[in](optional) info info object
3885 !> \par History
3886 !> 11.2012 created [Hossein Bani-Hashemian]
3887 ! **************************************************************************************************
3888  SUBROUTINE mp_file_open(groupid, fh, filepath, amode_status, info)
3889  CLASS(mp_comm_type), INTENT(IN) :: groupid
3890  CLASS(mp_file_type), INTENT(OUT) :: fh
3891  CHARACTER(len=*), INTENT(IN) :: filepath
3892  INTEGER, INTENT(IN) :: amode_status
3893  TYPE(mp_info_type), INTENT(IN), OPTIONAL :: info
3894 
3895 #if defined(__parallel)
3896  INTEGER :: ierr
3897  mpi_info_type :: my_info
3898 #else
3899  CHARACTER(LEN=10) :: fstatus, fposition
3900  INTEGER :: amode, handle, istat
3901  LOGICAL :: exists, is_open
3902 #endif
3903 
3904 #if defined(__parallel)
3905  ierr = 0
3906  my_info = mpi_info_null
3907  IF (PRESENT(info)) my_info = info%handle
3908  CALL mpi_file_open(groupid%handle, filepath, amode_status, my_info, fh%handle, ierr)
3909  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
3910  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_open")
3911 #else
3912  mark_used(groupid)
3913  mark_used(info)
3914  amode = amode_status
3915  IF (amode .GT. file_amode_append) THEN
3916  fposition = "APPEND"
3917  amode = amode - file_amode_append
3918  ELSE
3919  fposition = "REWIND"
3920  END IF
3921  IF ((amode .EQ. file_amode_create) .OR. &
3922  (amode .EQ. file_amode_create + file_amode_wronly) .OR. &
3923  (amode .EQ. file_amode_create + file_amode_wronly + file_amode_excl)) THEN
3924  fstatus = "UNKNOWN"
3925  ELSE
3926  fstatus = "OLD"
3927  END IF
3928  ! Get a new unit number
3929  DO handle = 1, 999
3930  INQUIRE (unit=handle, exist=exists, opened=is_open, iostat=istat)
3931  IF (exists .AND. (.NOT. is_open) .AND. (istat == 0)) EXIT
3932  END DO
3933  OPEN (unit=handle, file=filepath, status=fstatus, access="STREAM", position=fposition)
3934  fh%handle = handle
3935 #endif
3936  END SUBROUTINE mp_file_open
3937 
3938 ! **************************************************************************************************
3939 !> \brief Deletes a file. Auxiliary routine to emulate 'replace' action for mp_file_open.
3940 !> Only the master processor should call this routine.
3941 !> \param[in] filepath path to the file
3942 !> \param[in](optional) info info object
3943 !> \par History
3944 !> 11.2017 created [Nico Holmberg]
3945 ! **************************************************************************************************
3946  SUBROUTINE mp_file_delete(filepath, info)
3947  CHARACTER(len=*), INTENT(IN) :: filepath
3948  TYPE(mp_info_type), INTENT(IN), OPTIONAL :: info
3949 
3950 #if defined(__parallel)
3951  INTEGER :: ierr
3952  mpi_info_type :: my_info
3953  LOGICAL :: exists
3954 
3955  ierr = 0
3956  my_info = mpi_info_null
3957  IF (PRESENT(info)) my_info = info%handle
3958  INQUIRE (file=filepath, exist=exists)
3959  IF (exists) CALL mpi_file_delete(filepath, my_info, ierr)
3960  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_delete")
3961 #else
3962  mark_used(filepath)
3963  mark_used(info)
3964  ! Explicit file delete not necessary, handled by subsequent call to open_file with action 'replace'
3965 #endif
3966 
3967  END SUBROUTINE mp_file_delete
3968 
3969 ! **************************************************************************************************
3970 !> \brief Closes a file
3971 !> \param[in] fh file handle (file storage unit)
3972 !> \par MPI-I/O mapping mpi_file_close
3973 !> \par STREAM-I/O mapping CLOSE
3974 !>
3975 !> \par History
3976 !> 11.2012 created [Hossein Bani-Hashemian]
3977 ! **************************************************************************************************
3978  SUBROUTINE mp_file_close(fh)
3979  CLASS(mp_file_type), INTENT(INOUT) :: fh
3980 
3981 #if defined(__parallel)
3982  INTEGER :: ierr
3983 
3984  ierr = 0
3985  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
3986  CALL mpi_file_close(fh%handle, ierr)
3987  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_close")
3988 #else
3989  CLOSE (fh%handle)
3990  fh%handle = mp_file_null_handle
3991 #endif
3992  END SUBROUTINE mp_file_close
3993 
3994  SUBROUTINE mp_file_assign(fh_new, fh_old)
3995  CLASS(mp_file_type), INTENT(OUT) :: fh_new
3996  CLASS(mp_file_type), INTENT(IN) :: fh_old
3997 
3998  fh_new%handle = fh_old%handle
3999 
4000  END SUBROUTINE
4001 
4002 ! **************************************************************************************************
4003 !> \brief Returns the file size
4004 !> \param[in] fh file handle (file storage unit)
4005 !> \param[out] file_size the file size
4006 !> \par MPI-I/O mapping mpi_file_get_size
4007 !> \par STREAM-I/O mapping INQUIRE
4008 !>
4009 !> \par History
4010 !> 12.2012 created [Hossein Bani-Hashemian]
4011 ! **************************************************************************************************
4012  SUBROUTINE mp_file_get_size(fh, file_size)
4013  CLASS(mp_file_type), INTENT(IN) :: fh
4014  INTEGER(kind=file_offset), INTENT(OUT) :: file_size
4015 
4016 #if defined(__parallel)
4017  INTEGER :: ierr
4018 #endif
4019 
4020 #if defined(__parallel)
4021  ierr = 0
4022  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
4023  CALL mpi_file_get_size(fh%handle, file_size, ierr)
4024  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_get_size")
4025 #else
4026  INQUIRE (unit=fh%handle, size=file_size)
4027 #endif
4028  END SUBROUTINE mp_file_get_size
4029 
4030 ! **************************************************************************************************
4031 !> \brief Returns the file position
4032 !> \param[in] fh file handle (file storage unit)
4033 !> \param[out] file_size the file position
4034 !> \par MPI-I/O mapping mpi_file_get_position
4035 !> \par STREAM-I/O mapping INQUIRE
4036 !>
4037 !> \par History
4038 !> 11.2017 created [Nico Holmberg]
4039 ! **************************************************************************************************
4040  SUBROUTINE mp_file_get_position(fh, pos)
4041  CLASS(mp_file_type), INTENT(IN) :: fh
4042  INTEGER(kind=file_offset), INTENT(OUT) :: pos
4043 
4044 #if defined(__parallel)
4045  INTEGER :: ierr
4046 #endif
4047 
4048 #if defined(__parallel)
4049  ierr = 0
4050  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
4051  CALL mpi_file_get_position(fh%handle, pos, ierr)
4052  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ mp_file_get_position")
4053 #else
4054  INQUIRE (unit=fh%handle, pos=pos)
4055 #endif
4056  END SUBROUTINE mp_file_get_position
4057 
4058 ! **************************************************************************************************
4059 !> \brief (parallel) Blocking individual file write using explicit offsets
4060 !> (serial) Unformatted stream write
4061 !> \param[in] fh file handle (file storage unit)
4062 !> \param[in] offset file offset (position)
4063 !> \param[in] msg data to be written to the file
4064 !> \param msglen ...
4065 !> \par MPI-I/O mapping mpi_file_write_at
4066 !> \par STREAM-I/O mapping WRITE
4067 !> \param[in](optional) msglen number of the elements of data
4068 ! **************************************************************************************************
4069  SUBROUTINE mp_file_write_at_chv(fh, offset, msg, msglen)
4070  CHARACTER, CONTIGUOUS, INTENT(IN) :: msg(:)
4071  CLASS(mp_file_type), INTENT(IN) :: fh
4072  INTEGER, INTENT(IN), OPTIONAL :: msglen
4073  INTEGER(kind=file_offset), INTENT(IN) :: offset
4074 
4075 #if defined(__parallel)
4076  INTEGER :: ierr, msg_len
4077 #endif
4078 
4079 #if defined(__parallel)
4080  msg_len = SIZE(msg)
4081  IF (PRESENT(msglen)) msg_len = msglen
4082  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_character, mpi_status_ignore, ierr)
4083  IF (ierr .NE. 0) &
4084  cpabort("mpi_file_write_at_chv @ mp_file_write_at_chv")
4085 #else
4086  mark_used(msglen)
4087  WRITE (unit=fh%handle, pos=offset + 1) msg
4088 #endif
4089  END SUBROUTINE mp_file_write_at_chv
4090 
4091 ! **************************************************************************************************
4092 !> \brief ...
4093 !> \param fh ...
4094 !> \param offset ...
4095 !> \param msg ...
4096 ! **************************************************************************************************
4097  SUBROUTINE mp_file_write_at_ch(fh, offset, msg)
4098  CHARACTER(LEN=*), INTENT(IN) :: msg
4099  CLASS(mp_file_type), INTENT(IN) :: fh
4100  INTEGER(kind=file_offset), INTENT(IN) :: offset
4101 
4102 #if defined(__parallel)
4103  INTEGER :: ierr
4104 #endif
4105 
4106 #if defined(__parallel)
4107  CALL mpi_file_write_at(fh%handle, offset, msg, len(msg), mpi_character, mpi_status_ignore, ierr)
4108  IF (ierr .NE. 0) &
4109  cpabort("mpi_file_write_at_ch @ mp_file_write_at_ch")
4110 #else
4111  WRITE (unit=fh%handle, pos=offset + 1) msg
4112 #endif
4113  END SUBROUTINE mp_file_write_at_ch
4114 
4115 ! **************************************************************************************************
4116 !> \brief (parallel) Blocking collective file write using explicit offsets
4117 !> (serial) Unformatted stream write
4118 !> \param fh ...
4119 !> \param offset ...
4120 !> \param msg ...
4121 !> \param msglen ...
4122 !> \par MPI-I/O mapping mpi_file_write_at_all
4123 !> \par STREAM-I/O mapping WRITE
4124 ! **************************************************************************************************
4125  SUBROUTINE mp_file_write_at_all_chv(fh, offset, msg, msglen)
4126  CHARACTER, CONTIGUOUS, INTENT(IN) :: msg(:)
4127  CLASS(mp_file_type), INTENT(IN) :: fh
4128  INTEGER, INTENT(IN), OPTIONAL :: msglen
4129  INTEGER(kind=file_offset), INTENT(IN) :: offset
4130 
4131 #if defined(__parallel)
4132  INTEGER :: ierr, msg_len
4133 #endif
4134 
4135 #if defined(__parallel)
4136  msg_len = SIZE(msg)
4137  IF (PRESENT(msglen)) msg_len = msglen
4138  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_character, mpi_status_ignore, ierr)
4139  IF (ierr .NE. 0) &
4140  cpabort("mpi_file_write_at_all_chv @ mp_file_write_at_all_chv")
4141 #else
4142  mark_used(msglen)
4143  WRITE (unit=fh%handle, pos=offset + 1) msg
4144 #endif
4145  END SUBROUTINE mp_file_write_at_all_chv
4146 
4147 ! **************************************************************************************************
4148 !> \brief wrapper to MPI_File_write_at_all
4149 !> \param fh ...
4150 !> \param offset ...
4151 !> \param msg ...
4152 ! **************************************************************************************************
4153  SUBROUTINE mp_file_write_at_all_ch(fh, offset, msg)
4154  CHARACTER(LEN=*), INTENT(IN) :: msg
4155  CLASS(mp_file_type), INTENT(IN) :: fh
4156  INTEGER(kind=file_offset), INTENT(IN) :: offset
4157 
4158 #if defined(__parallel)
4159  INTEGER :: ierr
4160 #endif
4161 
4162 #if defined(__parallel)
4163  CALL mpi_file_write_at_all(fh%handle, offset, msg, len(msg), mpi_character, mpi_status_ignore, ierr)
4164  IF (ierr .NE. 0) &
4165  cpabort("mpi_file_write_at_all_ch @ mp_file_write_at_all_ch")
4166 #else
4167  WRITE (unit=fh%handle, pos=offset + 1) msg
4168 #endif
4169  END SUBROUTINE mp_file_write_at_all_ch
4170 
4171 ! **************************************************************************************************
4172 !> \brief (parallel) Blocking individual file read using explicit offsets
4173 !> (serial) Unformatted stream read
4174 !> \param[in] fh file handle (file storage unit)
4175 !> \param[in] offset file offset (position)
4176 !> \param[out] msg data to be read from the file
4177 !> \param msglen ...
4178 !> \par MPI-I/O mapping mpi_file_read_at
4179 !> \par STREAM-I/O mapping READ
4180 !> \param[in](optional) msglen number of elements of data
4181 ! **************************************************************************************************
4182  SUBROUTINE mp_file_read_at_chv(fh, offset, msg, msglen)
4183  CHARACTER, CONTIGUOUS, INTENT(OUT) :: msg(:)
4184  CLASS(mp_file_type), INTENT(IN) :: fh
4185  INTEGER, INTENT(IN), OPTIONAL :: msglen
4186  INTEGER(kind=file_offset), INTENT(IN) :: offset
4187 
4188 #if defined(__parallel)
4189  INTEGER :: ierr, msg_len
4190 #endif
4191 
4192 #if defined(__parallel)
4193  msg_len = SIZE(msg)
4194  IF (PRESENT(msglen)) msg_len = msglen
4195  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_character, mpi_status_ignore, ierr)
4196  IF (ierr .NE. 0) &
4197  cpabort("mpi_file_read_at_chv @ mp_file_read_at_chv")
4198 #else
4199  mark_used(msglen)
4200  READ (unit=fh%handle, pos=offset + 1) msg
4201 #endif
4202  END SUBROUTINE mp_file_read_at_chv
4203 
4204 ! **************************************************************************************************
4205 !> \brief wrapper to MPI_File_read_at
4206 !> \param fh ...
4207 !> \param offset ...
4208 !> \param msg ...
4209 ! **************************************************************************************************
4210  SUBROUTINE mp_file_read_at_ch(fh, offset, msg)
4211  CHARACTER(LEN=*), INTENT(OUT) :: msg
4212  CLASS(mp_file_type), INTENT(IN) :: fh
4213  INTEGER(kind=file_offset), INTENT(IN) :: offset
4214 
4215 #if defined(__parallel)
4216  INTEGER :: ierr
4217 #endif
4218 
4219 #if defined(__parallel)
4220  CALL mpi_file_read_at(fh%handle, offset, msg, len(msg), mpi_character, mpi_status_ignore, ierr)
4221  IF (ierr .NE. 0) &
4222  cpabort("mpi_file_read_at_ch @ mp_file_read_at_ch")
4223 #else
4224  READ (unit=fh%handle, pos=offset + 1) msg
4225 #endif
4226  END SUBROUTINE mp_file_read_at_ch
4227 
4228 ! **************************************************************************************************
4229 !> \brief (parallel) Blocking collective file read using explicit offsets
4230 !> (serial) Unformatted stream read
4231 !> \param fh ...
4232 !> \param offset ...
4233 !> \param msg ...
4234 !> \param msglen ...
4235 !> \par MPI-I/O mapping mpi_file_read_at_all
4236 !> \par STREAM-I/O mapping READ
4237 ! **************************************************************************************************
4238  SUBROUTINE mp_file_read_at_all_chv(fh, offset, msg, msglen)
4239  CHARACTER, INTENT(OUT) :: msg(:)
4240  CLASS(mp_file_type), INTENT(IN) :: fh
4241  INTEGER, INTENT(IN), OPTIONAL :: msglen
4242  INTEGER(kind=file_offset), INTENT(IN) :: offset
4243 
4244 #if defined(__parallel)
4245  INTEGER :: ierr, msg_len
4246 #endif
4247 
4248 #if defined(__parallel)
4249  msg_len = SIZE(msg)
4250  IF (PRESENT(msglen)) msg_len = msglen
4251  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_character, mpi_status_ignore, ierr)
4252  IF (ierr .NE. 0) &
4253  cpabort("mpi_file_read_at_all_chv @ mp_file_read_at_all_chv")
4254 #else
4255  mark_used(msglen)
4256  READ (unit=fh%handle, pos=offset + 1) msg
4257 #endif
4258  END SUBROUTINE mp_file_read_at_all_chv
4259 
4260 ! **************************************************************************************************
4261 !> \brief wrapper to MPI_File_read_at_all
4262 !> \param fh ...
4263 !> \param offset ...
4264 !> \param msg ...
4265 ! **************************************************************************************************
4266  SUBROUTINE mp_file_read_at_all_ch(fh, offset, msg)
4267  CHARACTER(LEN=*), INTENT(OUT) :: msg
4268  CLASS(mp_file_type), INTENT(IN) :: fh
4269  INTEGER(kind=file_offset), INTENT(IN) :: offset
4270 
4271 #if defined(__parallel)
4272  INTEGER :: ierr
4273 #endif
4274 
4275 #if defined(__parallel)
4276  CALL mpi_file_read_at_all(fh%handle, offset, msg, len(msg), mpi_character, mpi_status_ignore, ierr)
4277  IF (ierr .NE. 0) &
4278  cpabort("mpi_file_read_at_all_ch @ mp_file_read_at_all_ch")
4279 #else
4280  READ (unit=fh%handle, pos=offset + 1) msg
4281 #endif
4282  END SUBROUTINE mp_file_read_at_all_ch
4283 
4284 ! **************************************************************************************************
4285 !> \brief Returns the size of a data type in bytes
4286 !> \param[in] type_descriptor data type
4287 !> \param[out] type_size size of the data type
4288 !> \par MPI mapping
4289 !> mpi_type_size
4290 !>
4291 ! **************************************************************************************************
4292  SUBROUTINE mp_type_size(type_descriptor, type_size)
4293  TYPE(mp_type_descriptor_type), INTENT(IN) :: type_descriptor
4294  INTEGER, INTENT(OUT) :: type_size
4295 
4296 #if defined(__parallel)
4297  INTEGER :: ierr
4298 
4299  ierr = 0
4300  CALL mpi_type_size(type_descriptor%type_handle, type_size, ierr)
4301  IF (ierr .NE. 0) &
4302  cpabort("mpi_type_size failed @ mp_type_size")
4303 #else
4304  SELECT CASE (type_descriptor%type_handle)
4305  CASE (1)
4306  type_size = real_4_size
4307  CASE (3)
4308  type_size = real_8_size
4309  CASE (5)
4310  type_size = 2*real_4_size
4311  CASE (7)
4312  type_size = 2*real_8_size
4313  END SELECT
4314 #endif
4315  END SUBROUTINE mp_type_size
4316 
4317 ! **************************************************************************************************
4318 !> \brief wrapper to MPI_Type_create_struct
4319 !> \param subtypes ...
4320 !> \param vector_descriptor ...
4321 !> \param index_descriptor ...
4322 !> \return ...
4323 ! **************************************************************************************************
4324  FUNCTION mp_type_make_struct(subtypes, &
4325  vector_descriptor, index_descriptor) &
4326  result(type_descriptor)
4327  TYPE(mp_type_descriptor_type), &
4328  DIMENSION(:), INTENT(IN) :: subtypes
4329  INTEGER, DIMENSION(2), INTENT(IN), &
4330  OPTIONAL :: vector_descriptor
4331  TYPE(mp_indexing_meta_type), &
4332  INTENT(IN), OPTIONAL :: index_descriptor
4333  TYPE(mp_type_descriptor_type) :: type_descriptor
4334 
4335  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_struct'
4336 
4337  INTEGER :: i, n
4338  INTEGER, ALLOCATABLE, DIMENSION(:) :: lengths
4339 #if defined(__parallel)
4340  INTEGER :: ierr
4341  INTEGER(kind=mpi_address_kind), &
4342  ALLOCATABLE, DIMENSION(:) :: displacements
4343 #endif
4344  mpi_data_type, ALLOCATABLE, DIMENSION(:) :: old_types
4345 
4346  n = SIZE(subtypes)
4347  type_descriptor%length = 1
4348 #if defined(__parallel)
4349  ierr = 0
4350  CALL mpi_get_address(mpi_bottom, type_descriptor%base, ierr)
4351  IF (ierr /= 0) &
4352  cpabort("MPI_get_address @ "//routinen)
4353  ALLOCATE (displacements(n))
4354 #endif
4355  type_descriptor%vector_descriptor(1:2) = 1
4356  type_descriptor%has_indexing = .false.
4357  ALLOCATE (type_descriptor%subtype(n))
4358  type_descriptor%subtype(:) = subtypes(:)
4359  ALLOCATE (lengths(n), old_types(n))
4360  DO i = 1, SIZE(subtypes)
4361 #if defined(__parallel)
4362  displacements(i) = subtypes(i)%base
4363 #endif
4364  old_types(i) = subtypes(i)%type_handle
4365  lengths(i) = subtypes(i)%length
4366  END DO
4367 #if defined(__parallel)
4368  CALL mpi_type_create_struct(n, &
4369  lengths, displacements, old_types, &
4370  type_descriptor%type_handle, ierr)
4371  IF (ierr /= 0) &
4372  cpabort("MPI_Type_create_struct @ "//routinen)
4373  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
4374  IF (ierr /= 0) &
4375  cpabort("MPI_Type_commit @ "//routinen)
4376 #endif
4377  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
4378  cpabort(routinen//" Vectors and indices NYI")
4379  END IF
4380  END FUNCTION mp_type_make_struct
4381 
4382 ! **************************************************************************************************
4383 !> \brief wrapper to MPI_Type_free
4384 !> \param type_descriptor ...
4385 ! **************************************************************************************************
4386  RECURSIVE SUBROUTINE mp_type_free_m(type_descriptor)
4387  TYPE(mp_type_descriptor_type), INTENT(inout) :: type_descriptor
4388 
4389  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_free_m'
4390 
4391  INTEGER :: handle, i
4392 #if defined(__parallel)
4393  INTEGER :: ierr
4394 #endif
4395 
4396  CALL mp_timeset(routinen, handle)
4397 
4398  ! If the subtype is associated, then it's a user-defined data type.
4399 
4400  IF (ASSOCIATED(type_descriptor%subtype)) THEN
4401  DO i = 1, SIZE(type_descriptor%subtype)
4402  CALL mp_type_free_m(type_descriptor%subtype(i))
4403  END DO
4404  DEALLOCATE (type_descriptor%subtype)
4405  END IF
4406 #if defined(__parallel)
4407  ierr = 0
4408  CALL mpi_type_free(type_descriptor%type_handle, ierr)
4409  IF (ierr /= 0) &
4410  cpabort("MPI_Type_free @ "//routinen)
4411 #endif
4412 
4413  CALL mp_timestop(handle)
4414 
4415  END SUBROUTINE mp_type_free_m
4416 
4417 ! **************************************************************************************************
4418 !> \brief ...
4419 !> \param type_descriptors ...
4420 ! **************************************************************************************************
4421  SUBROUTINE mp_type_free_v(type_descriptors)
4422  TYPE(mp_type_descriptor_type), DIMENSION(:), &
4423  INTENT(inout) :: type_descriptors
4424 
4425  INTEGER :: i
4426 
4427  DO i = 1, SIZE(type_descriptors)
4428  CALL mp_type_free(type_descriptors(i))
4429  END DO
4430 
4431  END SUBROUTINE mp_type_free_v
4432 
4433 ! **************************************************************************************************
4434 !> \brief Creates an indexed MPI type for arrays of strings using bytes for spacing (hindexed type)
4435 !> \param count number of array blocks to read
4436 !> \param lengths lengths of each array block
4437 !> \param displs byte offsets for array blocks
4438 !> \return container holding the created type
4439 !> \author Nico Holmberg [05.2017]
4440 ! **************************************************************************************************
4441  FUNCTION mp_file_type_hindexed_make_chv(count, lengths, displs) &
4442  result(type_descriptor)
4443  INTEGER, INTENT(IN) :: count
4444  INTEGER, DIMENSION(1:count), &
4445  INTENT(IN), TARGET :: lengths
4446  INTEGER(kind=file_offset), &
4447  DIMENSION(1:count), INTENT(in), TARGET :: displs
4448  TYPE(mp_file_descriptor_type) :: type_descriptor
4449 
4450  CHARACTER(len=*), PARAMETER :: routinen = 'mp_file_hindexed_make_chv'
4451 
4452  INTEGER :: ierr, handle
4453 
4454  ierr = 0
4455  CALL mp_timeset(routinen, handle)
4456 
4457 #if defined(__parallel)
4458  CALL mpi_type_create_hindexed(count, lengths, int(displs, kind=address_kind), mpi_character, &
4459  type_descriptor%type_handle, ierr)
4460  IF (ierr /= 0) &
4461  cpabort("MPI_Type_create_hindexed @ "//routinen)
4462  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
4463  IF (ierr /= 0) &
4464  cpabort("MPI_Type_commit @ "//routinen)
4465 #else
4466  type_descriptor%type_handle = 68
4467 #endif
4468  type_descriptor%length = count
4469  type_descriptor%has_indexing = .true.
4470  type_descriptor%index_descriptor%index => lengths
4471  type_descriptor%index_descriptor%chunks => displs
4472 
4473  CALL mp_timestop(handle)
4474 
4475  END FUNCTION mp_file_type_hindexed_make_chv
4476 
4477 ! **************************************************************************************************
4478 !> \brief Uses a previously created indexed MPI character type to tell the MPI processes
4479 !> how to partition (set_view) an opened file
4480 !> \param fh the file handle associated with the input file
4481 !> \param offset global offset determining where the relevant data begins
4482 !> \param type_descriptor container for the MPI type
4483 !> \author Nico Holmberg [05.2017]
4484 ! **************************************************************************************************
4485  SUBROUTINE mp_file_type_set_view_chv(fh, offset, type_descriptor)
4486  TYPE(mp_file_type), INTENT(IN) :: fh
4487  INTEGER(kind=file_offset), INTENT(IN) :: offset
4488  TYPE(mp_file_descriptor_type) :: type_descriptor
4489 
4490  CHARACTER(len=*), PARAMETER :: routinen = 'mp_file_set_view_chv'
4491 
4492  INTEGER :: handle
4493 #if defined(__parallel)
4494  INTEGER :: ierr
4495 #endif
4496 
4497  CALL mp_timeset(routinen, handle)
4498 
4499 #if defined(__parallel)
4500  ierr = 0
4501  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
4502  CALL mpi_file_set_view(fh%handle, offset, mpi_character, &
4503  type_descriptor%type_handle, "native", mpi_info_null, ierr)
4504  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_set_view")
4505 #else
4506  ! Uses absolute offsets stored in mp_file_descriptor_type
4507  mark_used(fh)
4508  mark_used(offset)
4509  mark_used(type_descriptor)
4510 #endif
4511 
4512  CALL mp_timestop(handle)
4513 
4514  END SUBROUTINE mp_file_type_set_view_chv
4515 
4516 ! **************************************************************************************************
4517 !> \brief (parallel) Collective, blocking read of a character array from a file. File access pattern
4518 ! determined by a previously set file view.
4519 !> (serial) Unformatted stream read using explicit offsets
4520 !> \param fh the file handle associated with the input file
4521 !> \param msglen the message length of an individual vector component
4522 !> \param ndims the number of vector components
4523 !> \param buffer the buffer where the data is placed
4524 !> \param type_descriptor container for the MPI type
4525 !> \author Nico Holmberg [05.2017]
4526 ! **************************************************************************************************
4527  SUBROUTINE mp_file_read_all_chv(fh, msglen, ndims, buffer, type_descriptor)
4528  CLASS(mp_file_type), INTENT(IN) :: fh
4529  INTEGER, INTENT(IN) :: msglen
4530  INTEGER, INTENT(IN) :: ndims
4531  CHARACTER(LEN=msglen), DIMENSION(ndims), INTENT(INOUT) :: buffer
4532  TYPE(mp_file_descriptor_type), &
4533  INTENT(IN), OPTIONAL :: type_descriptor
4534 
4535  CHARACTER(len=*), PARAMETER :: routinen = 'mp_file_read_all_chv'
4536 
4537  INTEGER :: handle
4538 #if defined(__parallel)
4539  INTEGER:: ierr
4540 #else
4541  INTEGER :: i
4542 #endif
4543 
4544  CALL mp_timeset(routinen, handle)
4545 
4546 #if defined(__parallel)
4547  ierr = 0
4548  mark_used(type_descriptor)
4549  CALL mpi_file_read_all(fh%handle, buffer, ndims*msglen, mpi_character, mpi_status_ignore, ierr)
4550  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_read_all")
4551  CALL add_perf(perf_id=28, count=1, msg_size=ndims*msglen)
4552 #else
4553  mark_used(msglen)
4554  mark_used(ndims)
4555  IF (.NOT. PRESENT(type_descriptor)) &
4556  CALL cp_abort(__location__, &
4557  "Container for mp_file_descriptor_type must be present in serial call.")
4558  IF (.NOT. type_descriptor%has_indexing) &
4559  CALL cp_abort(__location__, &
4560  "File view has not been set in mp_file_descriptor_type.")
4561  ! Use explicit offsets
4562  DO i = 1, ndims
4563  READ (fh%handle, pos=type_descriptor%index_descriptor%chunks(i)) buffer(i)
4564  END DO
4565 #endif
4566 
4567  CALL mp_timestop(handle)
4568 
4569  END SUBROUTINE mp_file_read_all_chv
4570 
4571 ! **************************************************************************************************
4572 !> \brief (parallel) Collective, blocking write of a character array to a file. File access pattern
4573 ! determined by a previously set file view.
4574 !> (serial) Unformatted stream write using explicit offsets
4575 !> \param fh the file handle associated with the output file
4576 !> \param msglen the message length of an individual vector component
4577 !> \param ndims the number of vector components
4578 !> \param buffer the buffer where the data is placed
4579 !> \param type_descriptor container for the MPI type
4580 !> \author Nico Holmberg [05.2017]
4581 ! **************************************************************************************************
4582  SUBROUTINE mp_file_write_all_chv(fh, msglen, ndims, buffer, type_descriptor)
4583  CLASS(mp_file_type), INTENT(IN) :: fh
4584  INTEGER, INTENT(IN) :: msglen
4585  INTEGER, INTENT(IN) :: ndims
4586  CHARACTER(LEN=msglen), DIMENSION(ndims), INTENT(IN) :: buffer
4587  TYPE(mp_file_descriptor_type), &
4588  INTENT(IN), OPTIONAL :: type_descriptor
4589 
4590  CHARACTER(len=*), PARAMETER :: routinen = 'mp_file_write_all_chv'
4591 
4592  INTEGER :: handle
4593 #if defined(__parallel)
4594  INTEGER :: ierr
4595 #else
4596  INTEGER :: i
4597 #endif
4598 
4599  CALL mp_timeset(routinen, handle)
4600 
4601 #if defined(__parallel)
4602  mark_used(type_descriptor)
4603  CALL mpi_file_set_errhandler(fh%handle, mpi_errors_return, ierr)
4604  CALL mpi_file_write_all(fh%handle, buffer, ndims*msglen, mpi_character, mpi_status_ignore, ierr)
4605  IF (ierr .NE. 0) CALL mp_stop(ierr, "mpi_file_set_errhandler @ MPI_File_write_all")
4606  CALL add_perf(perf_id=28, count=1, msg_size=ndims*msglen)
4607 #else
4608  mark_used(msglen)
4609  mark_used(ndims)
4610  IF (.NOT. PRESENT(type_descriptor)) &
4611  CALL cp_abort(__location__, &
4612  "Container for mp_file_descriptor_type must be present in serial call.")
4613  IF (.NOT. type_descriptor%has_indexing) &
4614  CALL cp_abort(__location__, &
4615  "File view has not been set in mp_file_descriptor_type.")
4616  ! Use explicit offsets
4617  DO i = 1, ndims
4618  WRITE (fh%handle, pos=type_descriptor%index_descriptor%chunks(i)) buffer(i)
4619  END DO
4620 #endif
4621 
4622  CALL mp_timestop(handle)
4623 
4624  END SUBROUTINE mp_file_write_all_chv
4625 
4626 ! **************************************************************************************************
4627 !> \brief Releases the type used for MPI I/O
4628 !> \param type_descriptor the container for the MPI type
4629 !> \author Nico Holmberg [05.2017]
4630 ! **************************************************************************************************
4631  SUBROUTINE mp_file_type_free(type_descriptor)
4632  TYPE(mp_file_descriptor_type) :: type_descriptor
4633 
4634  CHARACTER(len=*), PARAMETER :: routinen = 'mp_file_type_free'
4635 
4636  INTEGER :: handle
4637 #if defined(__parallel)
4638  INTEGER :: ierr
4639 #endif
4640 
4641  CALL mp_timeset(routinen, handle)
4642 
4643 #if defined(__parallel)
4644  CALL mpi_type_free(type_descriptor%type_handle, ierr)
4645  IF (ierr /= 0) &
4646  cpabort("MPI_Type_free @ "//routinen)
4647 #endif
4648 #if defined(__parallel) && defined(__MPI_F08)
4649  type_descriptor%type_handle%mpi_val = -1
4650 #else
4651  type_descriptor%type_handle = -1
4652 #endif
4653  type_descriptor%length = -1
4654  IF (type_descriptor%has_indexing) THEN
4655  NULLIFY (type_descriptor%index_descriptor%index)
4656  NULLIFY (type_descriptor%index_descriptor%chunks)
4657  type_descriptor%has_indexing = .false.
4658  END IF
4659 
4660  CALL mp_timestop(handle)
4661 
4662  END SUBROUTINE mp_file_type_free
4663 
4664 ! **************************************************************************************************
4665 !> \brief (parallel) Utility routine to determine MPI file access mode based on variables
4666 ! that in the serial case would get passed to the intrinsic OPEN
4667 !> (serial) No action
4668 !> \param mpi_io flag that determines if MPI I/O will actually be used
4669 !> \param replace flag that indicates whether file needs to be deleted prior to opening it
4670 !> \param amode the MPI I/O access mode
4671 !> \param form formatted or unformatted data?
4672 !> \param action the variable that determines what to do with file
4673 !> \param status the status flag:
4674 !> \param position should the file be appended or rewound
4675 !> \author Nico Holmberg [11.2017]
4676 ! **************************************************************************************************
4677  SUBROUTINE mp_file_get_amode(mpi_io, replace, amode, form, action, status, position)
4678  LOGICAL, INTENT(INOUT) :: mpi_io, replace
4679  INTEGER, INTENT(OUT) :: amode
4680  CHARACTER(len=*), INTENT(IN) :: form, action, status, position
4681 
4682  amode = -1
4683 #if defined(__parallel)
4684  ! Disable mpi io for unformatted access
4685  SELECT CASE (form)
4686  CASE ("FORMATTED")
4687  ! Do nothing
4688  CASE ("UNFORMATTED")
4689  mpi_io = .false.
4690  CASE DEFAULT
4691  cpabort("Unknown MPI file form requested.")
4692  END SELECT
4693  ! Determine file access mode (limited set of allowed choices)
4694  SELECT CASE (action)
4695  CASE ("WRITE")
4696  amode = file_amode_wronly
4697  SELECT CASE (status)
4698  CASE ("NEW")
4699  ! Try to open new file for writing, crash if file already exists
4700  amode = amode + file_amode_create + file_amode_excl
4701  CASE ("UNKNOWN")
4702  ! Open file for writing and create it if file does not exist
4703  amode = amode + file_amode_create
4704  SELECT CASE (position)
4705  CASE ("APPEND")
4706  ! Append existing file
4707  amode = amode + file_amode_append
4708  CASE ("REWIND", "ASIS")
4709  ! Do nothing
4710  CASE DEFAULT
4711  cpabort("Unknown MPI file position requested.")
4712  END SELECT
4713  CASE ("OLD")
4714  SELECT CASE (position)
4715  CASE ("APPEND")
4716  ! Append existing file
4717  amode = amode + file_amode_append
4718  CASE ("REWIND", "ASIS")
4719  ! Do nothing
4720  CASE DEFAULT
4721  cpabort("Unknown MPI file position requested.")
4722  END SELECT
4723  CASE ("REPLACE")
4724  ! Overwrite existing file. Must delete existing file first
4725  amode = amode + file_amode_create
4726  replace = .true.
4727  CASE ("SCRATCH")
4728  ! Disable
4729  mpi_io = .false.
4730  CASE DEFAULT
4731  cpabort("Unknown MPI file status requested.")
4732  END SELECT
4733  CASE ("READ")
4734  amode = file_amode_rdonly
4735  SELECT CASE (status)
4736  CASE ("NEW")
4737  cpabort("Cannot read from 'NEW' file.")
4738  CASE ("REPLACE")
4739  cpabort("Illegal status 'REPLACE' for read.")
4740  CASE ("UNKNOWN", "OLD")
4741  ! Do nothing
4742  CASE ("SCRATCH")
4743  ! Disable
4744  mpi_io = .false.
4745  CASE DEFAULT
4746  cpabort("Unknown MPI file status requested.")
4747  END SELECT
4748  CASE ("READWRITE")
4749  amode = file_amode_rdwr
4750  SELECT CASE (status)
4751  CASE ("NEW")
4752  ! Try to open new file, crash if file already exists
4753  amode = amode + file_amode_create + file_amode_excl
4754  CASE ("UNKNOWN")
4755  ! Open file and create it if file does not exist
4756  amode = amode + file_amode_create
4757  SELECT CASE (position)
4758  CASE ("APPEND")
4759  ! Append existing file
4760  amode = amode + file_amode_append
4761  CASE ("REWIND", "ASIS")
4762  ! Do nothing
4763  CASE DEFAULT
4764  cpabort("Unknown MPI file position requested.")
4765  END SELECT
4766  CASE ("OLD")
4767  SELECT CASE (position)
4768  CASE ("APPEND")
4769  ! Append existing file
4770  amode = amode + file_amode_append
4771  CASE ("REWIND", "ASIS")
4772  ! Do nothing
4773  CASE DEFAULT
4774  cpabort("Unknown MPI file position requested.")
4775  END SELECT
4776  CASE ("REPLACE")
4777  ! Overwrite existing file. Must delete existing file first
4778  amode = amode + file_amode_create
4779  replace = .true.
4780  CASE ("SCRATCH")
4781  ! Disable
4782  mpi_io = .false.
4783  CASE DEFAULT
4784  cpabort("Unknown MPI file status requested.")
4785  END SELECT
4786  CASE DEFAULT
4787  cpabort("Unknown MPI file action requested.")
4788  END SELECT
4789 #else
4790  mark_used(replace)
4791  mark_used(form)
4792  mark_used(position)
4793  mark_used(status)
4794  mark_used(action)
4795  mpi_io = .false.
4796 #endif
4797 
4798  END SUBROUTINE mp_file_get_amode
4799 
4800 ! **************************************************************************************************
4801 !> \brief Non-blocking send of custom type
4802 !> \param msgin ...
4803 !> \param dest ...
4804 !> \param comm ...
4805 !> \param request ...
4806 !> \param tag ...
4807 ! **************************************************************************************************
4808  SUBROUTINE mp_isend_custom(msgin, dest, comm, request, tag)
4809  TYPE(mp_type_descriptor_type), INTENT(IN) :: msgin
4810  INTEGER, INTENT(IN) :: dest
4811  CLASS(mp_comm_type), INTENT(IN) :: comm
4812  TYPE(mp_request_type), INTENT(out) :: request
4813  INTEGER, INTENT(in), OPTIONAL :: tag
4814 
4815  INTEGER :: ierr, my_tag
4816 
4817  ierr = 0
4818  my_tag = 0
4819 
4820 #if defined(__parallel)
4821  IF (PRESENT(tag)) my_tag = tag
4822 
4823  CALL mpi_isend(mpi_bottom, 1, msgin%type_handle, dest, my_tag, &
4824  comm%handle, request%handle, ierr)
4825  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ mp_isend_custom")
4826 #else
4827  mark_used(msgin)
4828  mark_used(dest)
4829  mark_used(comm)
4830  mark_used(tag)
4831  ierr = 1
4832  request = mp_request_null
4833  CALL mp_stop(ierr, "mp_isend called in non parallel case")
4834 #endif
4835  END SUBROUTINE mp_isend_custom
4836 
4837 ! **************************************************************************************************
4838 !> \brief Non-blocking receive of vector data
4839 !> \param msgout ...
4840 !> \param source ...
4841 !> \param comm ...
4842 !> \param request ...
4843 !> \param tag ...
4844 ! **************************************************************************************************
4845  SUBROUTINE mp_irecv_custom(msgout, source, comm, request, tag)
4846  TYPE(mp_type_descriptor_type), INTENT(INOUT) :: msgout
4847  INTEGER, INTENT(IN) :: source
4848  CLASS(mp_comm_type), INTENT(IN) :: comm
4849  TYPE(mp_request_type), INTENT(out) :: request
4850  INTEGER, INTENT(in), OPTIONAL :: tag
4851 
4852  INTEGER :: ierr, my_tag
4853 
4854  ierr = 0
4855  my_tag = 0
4856 
4857 #if defined(__parallel)
4858  IF (PRESENT(tag)) my_tag = tag
4859 
4860  CALL mpi_irecv(mpi_bottom, 1, msgout%type_handle, source, my_tag, &
4861  comm%handle, request%handle, ierr)
4862  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ mp_irecv_custom")
4863 #else
4864  mark_used(msgout)
4865  mark_used(source)
4866  mark_used(comm)
4867  mark_used(tag)
4868  ierr = 1
4869  request = mp_request_null
4870  cpabort("mp_irecv called in non parallel case")
4871 #endif
4872  END SUBROUTINE mp_irecv_custom
4873 
4874 ! **************************************************************************************************
4875 !> \brief Window free
4876 !> \param win ...
4877 ! **************************************************************************************************
4878  SUBROUTINE mp_win_free(win)
4879  CLASS(mp_win_type), INTENT(INOUT) :: win
4880 
4881  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_free'
4882 
4883  INTEGER :: handle
4884 #if defined(__parallel)
4885  INTEGER :: ierr
4886 #endif
4887 
4888  CALL mp_timeset(routinen, handle)
4889 
4890 #if defined(__parallel)
4891  ierr = 0
4892  CALL mpi_win_free(win%handle, ierr)
4893  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_free @ "//routinen)
4894 
4895  CALL add_perf(perf_id=21, count=1)
4896 #else
4897  win%handle = mp_win_null_handle
4898 #endif
4899  CALL mp_timestop(handle)
4900  END SUBROUTINE mp_win_free
4901 
4902  SUBROUTINE mp_win_assign(win_new, win_old)
4903  CLASS(mp_win_type), INTENT(OUT) :: win_new
4904  CLASS(mp_win_type), INTENT(IN) :: win_old
4905 
4906  win_new%handle = win_old%handle
4907 
4908  END SUBROUTINE mp_win_assign
4909 
4910 ! **************************************************************************************************
4911 !> \brief Window flush
4912 !> \param win ...
4913 ! **************************************************************************************************
4914  SUBROUTINE mp_win_flush_all(win)
4915  CLASS(mp_win_type), INTENT(IN) :: win
4916 
4917  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_flush_all'
4918 
4919  INTEGER :: handle, ierr
4920 
4921  ierr = 0
4922  CALL mp_timeset(routinen, handle)
4923 
4924 #if defined(__parallel)
4925  CALL mpi_win_flush_all(win%handle, ierr)
4926  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_flush_all @ "//routinen)
4927 #else
4928  mark_used(win)
4929 #endif
4930  CALL mp_timestop(handle)
4931  END SUBROUTINE mp_win_flush_all
4932 
4933 ! **************************************************************************************************
4934 !> \brief Window lock
4935 !> \param win ...
4936 ! **************************************************************************************************
4937  SUBROUTINE mp_win_lock_all(win)
4938  CLASS(mp_win_type), INTENT(IN) :: win
4939 
4940  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_lock_all'
4941 
4942  INTEGER :: handle, ierr
4943 
4944  ierr = 0
4945  CALL mp_timeset(routinen, handle)
4946 
4947 #if defined(__parallel)
4948 
4949  CALL mpi_win_lock_all(mpi_mode_nocheck, win%handle, ierr)
4950  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_lock_all @ "//routinen)
4951 
4952  CALL add_perf(perf_id=19, count=1)
4953 #else
4954  mark_used(win)
4955 #endif
4956  CALL mp_timestop(handle)
4957  END SUBROUTINE mp_win_lock_all
4958 
4959 ! **************************************************************************************************
4960 !> \brief Window lock
4961 !> \param win ...
4962 ! **************************************************************************************************
4963  SUBROUTINE mp_win_unlock_all(win)
4964  CLASS(mp_win_type), INTENT(IN) :: win
4965 
4966  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_unlock_all'
4967 
4968  INTEGER :: handle, ierr
4969 
4970  ierr = 0
4971  CALL mp_timeset(routinen, handle)
4972 
4973 #if defined(__parallel)
4974 
4975  CALL mpi_win_unlock_all(win%handle, ierr)
4976  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_unlock_all @ "//routinen)
4977 
4978  CALL add_perf(perf_id=19, count=1)
4979 #else
4980  mark_used(win)
4981 #endif
4982  CALL mp_timestop(handle)
4983  END SUBROUTINE mp_win_unlock_all
4984 
4985 ! **************************************************************************************************
4986 !> \brief Starts a timer region
4987 !> \param routineN ...
4988 !> \param handle ...
4989 ! **************************************************************************************************
4990  SUBROUTINE mp_timeset(routineN, handle)
4991  CHARACTER(len=*), INTENT(IN) :: routinen
4992  INTEGER, INTENT(OUT) :: handle
4993 
4994  IF (mp_collect_timings) &
4995  CALL timeset(routinen, handle)
4996  END SUBROUTINE mp_timeset
4997 
4998 ! **************************************************************************************************
4999 !> \brief Ends a timer region
5000 !> \param handle ...
5001 ! **************************************************************************************************
5002  SUBROUTINE mp_timestop(handle)
5003  INTEGER, INTENT(IN) :: handle
5004 
5005  IF (mp_collect_timings) &
5006  CALL timestop(handle)
5007  END SUBROUTINE mp_timestop
5008 
5009 ! **************************************************************************************************
5010 !> \brief Shift around the data in msg
5011 !> \param[in,out] msg Rank-2 data to shift
5012 !> \param[in] comm message passing environment identifier
5013 !> \param[in] displ_in displacements (?)
5014 !> \par Example
5015 !> msg will be moved from rank to rank+displ_in (in a circular way)
5016 !> \par Limitations
5017 !> * displ_in will be 1 by default (others not tested)
5018 !> * the message array needs to be the same size on all processes
5019 ! **************************************************************************************************
5020  SUBROUTINE mp_shift_im(msg, comm, displ_in)
5021 
5022  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
5023  CLASS(mp_comm_type), INTENT(IN) :: comm
5024  INTEGER, INTENT(IN), OPTIONAL :: displ_in
5025 
5026  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_im'
5027 
5028  INTEGER :: handle, ierror
5029 #if defined(__parallel)
5030  INTEGER :: displ, left, &
5031  msglen, myrank, nprocs, &
5032  right, tag
5033 #endif
5034 
5035  ierror = 0
5036  CALL mp_timeset(routinen, handle)
5037 
5038 #if defined(__parallel)
5039  CALL mpi_comm_rank(comm%handle, myrank, ierror)
5040  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
5041  CALL mpi_comm_size(comm%handle, nprocs, ierror)
5042  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
5043  IF (PRESENT(displ_in)) THEN
5044  displ = displ_in
5045  ELSE
5046  displ = 1
5047  END IF
5048  right = modulo(myrank + displ, nprocs)
5049  left = modulo(myrank - displ, nprocs)
5050  tag = 17
5051  msglen = SIZE(msg)
5052  CALL mpi_sendrecv_replace(msg, msglen, mpi_integer, right, tag, left, tag, &
5053  comm%handle, mpi_status_ignore, ierror)
5054  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
5055  CALL add_perf(perf_id=7, count=1, msg_size=msglen*int_4_size)
5056 #else
5057  mark_used(msg)
5058  mark_used(comm)
5059  mark_used(displ_in)
5060 #endif
5061  CALL mp_timestop(handle)
5062 
5063  END SUBROUTINE mp_shift_im
5064 
5065 ! **************************************************************************************************
5066 !> \brief Shift around the data in msg
5067 !> \param[in,out] msg Data to shift
5068 !> \param[in] comm message passing environment identifier
5069 !> \param[in] displ_in displacements (?)
5070 !> \par Example
5071 !> msg will be moved from rank to rank+displ_in (in a circular way)
5072 !> \par Limitations
5073 !> * displ_in will be 1 by default (others not tested)
5074 !> * the message array needs to be the same size on all processes
5075 ! **************************************************************************************************
5076  SUBROUTINE mp_shift_i (msg, comm, displ_in)
5077 
5078  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
5079  CLASS(mp_comm_type), INTENT(IN) :: comm
5080  INTEGER, INTENT(IN), OPTIONAL :: displ_in
5081 
5082  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_i'
5083 
5084  INTEGER :: handle, ierror
5085 #if defined(__parallel)
5086  INTEGER :: displ, left, &
5087  msglen, myrank, nprocs, &
5088  right, tag
5089 #endif
5090 
5091  ierror = 0
5092  CALL mp_timeset(routinen, handle)
5093 
5094 #if defined(__parallel)
5095  CALL mpi_comm_rank(comm%handle, myrank, ierror)
5096  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
5097  CALL mpi_comm_size(comm%handle, nprocs, ierror)
5098  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
5099  IF (PRESENT(displ_in)) THEN
5100  displ = displ_in
5101  ELSE
5102  displ = 1
5103  END IF
5104  right = modulo(myrank + displ, nprocs)
5105  left = modulo(myrank - displ, nprocs)
5106  tag = 19
5107  msglen = SIZE(msg)
5108  CALL mpi_sendrecv_replace(msg, msglen, mpi_integer, right, tag, left, &
5109  tag, comm%handle, mpi_status_ignore, ierror)
5110  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
5111  CALL add_perf(perf_id=7, count=1, msg_size=msglen*int_4_size)
5112 #else
5113  mark_used(msg)
5114  mark_used(comm)
5115  mark_used(displ_in)
5116 #endif
5117  CALL mp_timestop(handle)
5118 
5119  END SUBROUTINE mp_shift_i
5120 
5121 ! **************************************************************************************************
5122 !> \brief All-to-all data exchange, rank-1 data of different sizes
5123 !> \param[in] sb Data to send
5124 !> \param[in] scount Data counts for data sent to other processes
5125 !> \param[in] sdispl Respective data offsets for data sent to process
5126 !> \param[in,out] rb Buffer into which to receive data
5127 !> \param[in] rcount Data counts for data received from other
5128 !> processes
5129 !> \param[in] rdispl Respective data offsets for data received from
5130 !> other processes
5131 !> \param[in] comm Message passing environment identifier
5132 !> \par MPI mapping
5133 !> mpi_alltoallv
5134 !> \par Array sizes
5135 !> The scount, rcount, and the sdispl and rdispl arrays have a
5136 !> size equal to the number of processes.
5137 !> \par Offsets
5138 !> Values in sdispl and rdispl start with 0.
5139 ! **************************************************************************************************
5140  SUBROUTINE mp_alltoall_i11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
5141 
5142  INTEGER(KIND=int_4), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
5143  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
5144  INTEGER(KIND=int_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
5145  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
5146  CLASS(mp_comm_type), INTENT(IN) :: comm
5147 
5148  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i11v'
5149 
5150  INTEGER :: handle
5151 #if defined(__parallel)
5152  INTEGER :: ierr, msglen
5153 #else
5154  INTEGER :: i
5155 #endif
5156 
5157  CALL mp_timeset(routinen, handle)
5158 
5159 #if defined(__parallel)
5160  CALL mpi_alltoallv(sb, scount, sdispl, mpi_integer, &
5161  rb, rcount, rdispl, mpi_integer, comm%handle, ierr)
5162  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
5163  msglen = sum(scount) + sum(rcount)
5164  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5165 #else
5166  mark_used(comm)
5167  mark_used(scount)
5168  mark_used(sdispl)
5169  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
5170  DO i = 1, rcount(1)
5171  rb(rdispl(1) + i) = sb(sdispl(1) + i)
5172  END DO
5173 #endif
5174  CALL mp_timestop(handle)
5175 
5176  END SUBROUTINE mp_alltoall_i11v
5177 
5178 ! **************************************************************************************************
5179 !> \brief All-to-all data exchange, rank-2 data of different sizes
5180 !> \param sb ...
5181 !> \param scount ...
5182 !> \param sdispl ...
5183 !> \param rb ...
5184 !> \param rcount ...
5185 !> \param rdispl ...
5186 !> \param comm ...
5187 !> \par MPI mapping
5188 !> mpi_alltoallv
5189 !> \note see mp_alltoall_i11v
5190 ! **************************************************************************************************
5191  SUBROUTINE mp_alltoall_i22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
5192 
5193  INTEGER(KIND=int_4), DIMENSION(:, :), &
5194  INTENT(IN), CONTIGUOUS :: sb
5195  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
5196  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, &
5197  INTENT(INOUT) :: rb
5198  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
5199  CLASS(mp_comm_type), INTENT(IN) :: comm
5200 
5201  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i22v'
5202 
5203  INTEGER :: handle
5204 #if defined(__parallel)
5205  INTEGER :: ierr, msglen
5206 #endif
5207 
5208  CALL mp_timeset(routinen, handle)
5209 
5210 #if defined(__parallel)
5211  CALL mpi_alltoallv(sb, scount, sdispl, mpi_integer, &
5212  rb, rcount, rdispl, mpi_integer, comm%handle, ierr)
5213  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
5214  msglen = sum(scount) + sum(rcount)
5215  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*int_4_size)
5216 #else
5217  mark_used(comm)
5218  mark_used(scount)
5219  mark_used(sdispl)
5220  mark_used(rcount)
5221  mark_used(rdispl)
5222  rb = sb
5223 #endif
5224  CALL mp_timestop(handle)
5225 
5226  END SUBROUTINE mp_alltoall_i22v
5227 
5228 ! **************************************************************************************************
5229 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
5230 !> \param[in] sb array with data to send
5231 !> \param[out] rb array into which data is received
5232 !> \param[in] count number of elements to send/receive (product of the
5233 !> extents of the first two dimensions)
5234 !> \param[in] comm Message passing environment identifier
5235 !> \par Index meaning
5236 !> \par The first two indices specify the data while the last index counts
5237 !> the processes
5238 !> \par Sizes of ranks
5239 !> All processes have the same data size.
5240 !> \par MPI mapping
5241 !> mpi_alltoall
5242 ! **************************************************************************************************
5243  SUBROUTINE mp_alltoall_i (sb, rb, count, comm)
5244 
5245  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
5246  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
5247  INTEGER, INTENT(IN) :: count
5248  CLASS(mp_comm_type), INTENT(IN) :: comm
5249 
5250  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i'
5251 
5252  INTEGER :: handle
5253 #if defined(__parallel)
5254  INTEGER :: ierr, msglen, np
5255 #endif
5256 
5257  CALL mp_timeset(routinen, handle)
5258 
5259 #if defined(__parallel)
5260  CALL mpi_alltoall(sb, count, mpi_integer, &
5261  rb, count, mpi_integer, comm%handle, ierr)
5262  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5263  CALL mpi_comm_size(comm%handle, np, ierr)
5264  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5265  msglen = 2*count*np
5266  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5267 #else
5268  mark_used(count)
5269  mark_used(comm)
5270  rb = sb
5271 #endif
5272  CALL mp_timestop(handle)
5273 
5274  END SUBROUTINE mp_alltoall_i
5275 
5276 ! **************************************************************************************************
5277 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
5278 !> \param sb ...
5279 !> \param rb ...
5280 !> \param count ...
5281 !> \param commp ...
5282 !> \note see mp_alltoall_i
5283 ! **************************************************************************************************
5284  SUBROUTINE mp_alltoall_i22(sb, rb, count, comm)
5285 
5286  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
5287  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
5288  INTEGER, INTENT(IN) :: count
5289  CLASS(mp_comm_type), INTENT(IN) :: comm
5290 
5291  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i22'
5292 
5293  INTEGER :: handle
5294 #if defined(__parallel)
5295  INTEGER :: ierr, msglen, np
5296 #endif
5297 
5298  CALL mp_timeset(routinen, handle)
5299 
5300 #if defined(__parallel)
5301  CALL mpi_alltoall(sb, count, mpi_integer, &
5302  rb, count, mpi_integer, comm%handle, ierr)
5303  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5304  CALL mpi_comm_size(comm%handle, np, ierr)
5305  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5306  msglen = 2*SIZE(sb)*np
5307  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5308 #else
5309  mark_used(count)
5310  mark_used(comm)
5311  rb = sb
5312 #endif
5313  CALL mp_timestop(handle)
5314 
5315  END SUBROUTINE mp_alltoall_i22
5316 
5317 ! **************************************************************************************************
5318 !> \brief All-to-all data exchange, rank-3 data with equal sizes
5319 !> \param sb ...
5320 !> \param rb ...
5321 !> \param count ...
5322 !> \param comm ...
5323 !> \note see mp_alltoall_i
5324 ! **************************************************************************************************
5325  SUBROUTINE mp_alltoall_i33(sb, rb, count, comm)
5326 
5327  INTEGER(KIND=int_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
5328  INTEGER(KIND=int_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
5329  INTEGER, INTENT(IN) :: count
5330  CLASS(mp_comm_type), INTENT(IN) :: comm
5331 
5332  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i33'
5333 
5334  INTEGER :: handle
5335 #if defined(__parallel)
5336  INTEGER :: ierr, msglen, np
5337 #endif
5338 
5339  CALL mp_timeset(routinen, handle)
5340 
5341 #if defined(__parallel)
5342  CALL mpi_alltoall(sb, count, mpi_integer, &
5343  rb, count, mpi_integer, comm%handle, ierr)
5344  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5345  CALL mpi_comm_size(comm%handle, np, ierr)
5346  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5347  msglen = 2*count*np
5348  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5349 #else
5350  mark_used(count)
5351  mark_used(comm)
5352  rb = sb
5353 #endif
5354  CALL mp_timestop(handle)
5355 
5356  END SUBROUTINE mp_alltoall_i33
5357 
5358 ! **************************************************************************************************
5359 !> \brief All-to-all data exchange, rank 4 data, equal sizes
5360 !> \param sb ...
5361 !> \param rb ...
5362 !> \param count ...
5363 !> \param comm ...
5364 !> \note see mp_alltoall_i
5365 ! **************************************************************************************************
5366  SUBROUTINE mp_alltoall_i44(sb, rb, count, comm)
5367 
5368  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
5369  INTENT(IN) :: sb
5370  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
5371  INTENT(OUT) :: rb
5372  INTEGER, INTENT(IN) :: count
5373  CLASS(mp_comm_type), INTENT(IN) :: comm
5374 
5375  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i44'
5376 
5377  INTEGER :: handle
5378 #if defined(__parallel)
5379  INTEGER :: ierr, msglen, np
5380 #endif
5381 
5382  CALL mp_timeset(routinen, handle)
5383 
5384 #if defined(__parallel)
5385  CALL mpi_alltoall(sb, count, mpi_integer, &
5386  rb, count, mpi_integer, comm%handle, ierr)
5387  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5388  CALL mpi_comm_size(comm%handle, np, ierr)
5389  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5390  msglen = 2*count*np
5391  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5392 #else
5393  mark_used(count)
5394  mark_used(comm)
5395  rb = sb
5396 #endif
5397  CALL mp_timestop(handle)
5398 
5399  END SUBROUTINE mp_alltoall_i44
5400 
5401 ! **************************************************************************************************
5402 !> \brief All-to-all data exchange, rank 5 data, equal sizes
5403 !> \param sb ...
5404 !> \param rb ...
5405 !> \param count ...
5406 !> \param comm ...
5407 !> \note see mp_alltoall_i
5408 ! **************************************************************************************************
5409  SUBROUTINE mp_alltoall_i55(sb, rb, count, comm)
5410 
5411  INTEGER(KIND=int_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
5412  INTENT(IN) :: sb
5413  INTEGER(KIND=int_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
5414  INTENT(OUT) :: rb
5415  INTEGER, INTENT(IN) :: count
5416  CLASS(mp_comm_type), INTENT(IN) :: comm
5417 
5418  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i55'
5419 
5420  INTEGER :: handle
5421 #if defined(__parallel)
5422  INTEGER :: ierr, msglen, np
5423 #endif
5424 
5425  CALL mp_timeset(routinen, handle)
5426 
5427 #if defined(__parallel)
5428  CALL mpi_alltoall(sb, count, mpi_integer, &
5429  rb, count, mpi_integer, comm%handle, ierr)
5430  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5431  CALL mpi_comm_size(comm%handle, np, ierr)
5432  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5433  msglen = 2*count*np
5434  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5435 #else
5436  mark_used(count)
5437  mark_used(comm)
5438  rb = sb
5439 #endif
5440  CALL mp_timestop(handle)
5441 
5442  END SUBROUTINE mp_alltoall_i55
5443 
5444 ! **************************************************************************************************
5445 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
5446 !> \param sb ...
5447 !> \param rb ...
5448 !> \param count ...
5449 !> \param comm ...
5450 !> \note see mp_alltoall_i
5451 !> \note User must ensure size consistency.
5452 ! **************************************************************************************************
5453  SUBROUTINE mp_alltoall_i45(sb, rb, count, comm)
5454 
5455  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
5456  INTENT(IN) :: sb
5457  INTEGER(KIND=int_4), &
5458  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
5459  INTEGER, INTENT(IN) :: count
5460  CLASS(mp_comm_type), INTENT(IN) :: comm
5461 
5462  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i45'
5463 
5464  INTEGER :: handle
5465 #if defined(__parallel)
5466  INTEGER :: ierr, msglen, np
5467 #endif
5468 
5469  CALL mp_timeset(routinen, handle)
5470 
5471 #if defined(__parallel)
5472  CALL mpi_alltoall(sb, count, mpi_integer, &
5473  rb, count, mpi_integer, comm%handle, ierr)
5474  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5475  CALL mpi_comm_size(comm%handle, np, ierr)
5476  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5477  msglen = 2*count*np
5478  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5479 #else
5480  mark_used(count)
5481  mark_used(comm)
5482  rb = reshape(sb, shape(rb))
5483 #endif
5484  CALL mp_timestop(handle)
5485 
5486  END SUBROUTINE mp_alltoall_i45
5487 
5488 ! **************************************************************************************************
5489 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
5490 !> \param sb ...
5491 !> \param rb ...
5492 !> \param count ...
5493 !> \param comm ...
5494 !> \note see mp_alltoall_i
5495 !> \note User must ensure size consistency.
5496 ! **************************************************************************************************
5497  SUBROUTINE mp_alltoall_i34(sb, rb, count, comm)
5498 
5499  INTEGER(KIND=int_4), DIMENSION(:, :, :), CONTIGUOUS, &
5500  INTENT(IN) :: sb
5501  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
5502  INTENT(OUT) :: rb
5503  INTEGER, INTENT(IN) :: count
5504  CLASS(mp_comm_type), INTENT(IN) :: comm
5505 
5506  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i34'
5507 
5508  INTEGER :: handle
5509 #if defined(__parallel)
5510  INTEGER :: ierr, msglen, np
5511 #endif
5512 
5513  CALL mp_timeset(routinen, handle)
5514 
5515 #if defined(__parallel)
5516  CALL mpi_alltoall(sb, count, mpi_integer, &
5517  rb, count, mpi_integer, comm%handle, ierr)
5518  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5519  CALL mpi_comm_size(comm%handle, np, ierr)
5520  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5521  msglen = 2*count*np
5522  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5523 #else
5524  mark_used(count)
5525  mark_used(comm)
5526  rb = reshape(sb, shape(rb))
5527 #endif
5528  CALL mp_timestop(handle)
5529 
5530  END SUBROUTINE mp_alltoall_i34
5531 
5532 ! **************************************************************************************************
5533 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
5534 !> \param sb ...
5535 !> \param rb ...
5536 !> \param count ...
5537 !> \param comm ...
5538 !> \note see mp_alltoall_i
5539 !> \note User must ensure size consistency.
5540 ! **************************************************************************************************
5541  SUBROUTINE mp_alltoall_i54(sb, rb, count, comm)
5542 
5543  INTEGER(KIND=int_4), &
5544  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
5545  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
5546  INTENT(OUT) :: rb
5547  INTEGER, INTENT(IN) :: count
5548  CLASS(mp_comm_type), INTENT(IN) :: comm
5549 
5550  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_i54'
5551 
5552  INTEGER :: handle
5553 #if defined(__parallel)
5554  INTEGER :: ierr, msglen, np
5555 #endif
5556 
5557  CALL mp_timeset(routinen, handle)
5558 
5559 #if defined(__parallel)
5560  CALL mpi_alltoall(sb, count, mpi_integer, &
5561  rb, count, mpi_integer, comm%handle, ierr)
5562  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
5563  CALL mpi_comm_size(comm%handle, np, ierr)
5564  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
5565  msglen = 2*count*np
5566  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_4_size)
5567 #else
5568  mark_used(count)
5569  mark_used(comm)
5570  rb = reshape(sb, shape(rb))
5571 #endif
5572  CALL mp_timestop(handle)
5573 
5574  END SUBROUTINE mp_alltoall_i54
5575 
5576 ! **************************************************************************************************
5577 !> \brief Send one datum to another process
5578 !> \param[in] msg Scalar to send
5579 !> \param[in] dest Destination process
5580 !> \param[in] tag Transfer identifier
5581 !> \param[in] comm Message passing environment identifier
5582 !> \par MPI mapping
5583 !> mpi_send
5584 ! **************************************************************************************************
5585  SUBROUTINE mp_send_i (msg, dest, tag, comm)
5586  INTEGER(KIND=int_4), INTENT(IN) :: msg
5587  INTEGER, INTENT(IN) :: dest, tag
5588  CLASS(mp_comm_type), INTENT(IN) :: comm
5589 
5590  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_i'
5591 
5592  INTEGER :: handle
5593 #if defined(__parallel)
5594  INTEGER :: ierr, msglen
5595 #endif
5596 
5597  CALL mp_timeset(routinen, handle)
5598 
5599 #if defined(__parallel)
5600  msglen = 1
5601  CALL mpi_send(msg, msglen, mpi_integer, dest, tag, comm%handle, ierr)
5602  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
5603  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_4_size)
5604 #else
5605  mark_used(msg)
5606  mark_used(dest)
5607  mark_used(tag)
5608  mark_used(comm)
5609  ! only defined in parallel
5610  cpabort("not in parallel mode")
5611 #endif
5612  CALL mp_timestop(handle)
5613  END SUBROUTINE mp_send_i
5614 
5615 ! **************************************************************************************************
5616 !> \brief Send rank-1 data to another process
5617 !> \param[in] msg Rank-1 data to send
5618 !> \param dest ...
5619 !> \param tag ...
5620 !> \param comm ...
5621 !> \note see mp_send_i
5622 ! **************************************************************************************************
5623  SUBROUTINE mp_send_iv(msg, dest, tag, comm)
5624  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:)
5625  INTEGER, INTENT(IN) :: dest, tag
5626  CLASS(mp_comm_type), INTENT(IN) :: comm
5627 
5628  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_iv'
5629 
5630  INTEGER :: handle
5631 #if defined(__parallel)
5632  INTEGER :: ierr, msglen
5633 #endif
5634 
5635  CALL mp_timeset(routinen, handle)
5636 
5637 #if defined(__parallel)
5638  msglen = SIZE(msg)
5639  CALL mpi_send(msg, msglen, mpi_integer, dest, tag, comm%handle, ierr)
5640  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
5641  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_4_size)
5642 #else
5643  mark_used(msg)
5644  mark_used(dest)
5645  mark_used(tag)
5646  mark_used(comm)
5647  ! only defined in parallel
5648  cpabort("not in parallel mode")
5649 #endif
5650  CALL mp_timestop(handle)
5651  END SUBROUTINE mp_send_iv
5652 
5653 ! **************************************************************************************************
5654 !> \brief Send rank-2 data to another process
5655 !> \param[in] msg Rank-2 data to send
5656 !> \param dest ...
5657 !> \param tag ...
5658 !> \param comm ...
5659 !> \note see mp_send_i
5660 ! **************************************************************************************************
5661  SUBROUTINE mp_send_im2(msg, dest, tag, comm)
5662  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
5663  INTEGER, INTENT(IN) :: dest, tag
5664  CLASS(mp_comm_type), INTENT(IN) :: comm
5665 
5666  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_im2'
5667 
5668  INTEGER :: handle
5669 #if defined(__parallel)
5670  INTEGER :: ierr, msglen
5671 #endif
5672 
5673  CALL mp_timeset(routinen, handle)
5674 
5675 #if defined(__parallel)
5676  msglen = SIZE(msg)
5677  CALL mpi_send(msg, msglen, mpi_integer, dest, tag, comm%handle, ierr)
5678  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
5679  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_4_size)
5680 #else
5681  mark_used(msg)
5682  mark_used(dest)
5683  mark_used(tag)
5684  mark_used(comm)
5685  ! only defined in parallel
5686  cpabort("not in parallel mode")
5687 #endif
5688  CALL mp_timestop(handle)
5689  END SUBROUTINE mp_send_im2
5690 
5691 ! **************************************************************************************************
5692 !> \brief Send rank-3 data to another process
5693 !> \param[in] msg Rank-3 data to send
5694 !> \param dest ...
5695 !> \param tag ...
5696 !> \param comm ...
5697 !> \note see mp_send_i
5698 ! **************************************************************************************************
5699  SUBROUTINE mp_send_im3(msg, dest, tag, comm)
5700  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
5701  INTEGER, INTENT(IN) :: dest, tag
5702  CLASS(mp_comm_type), INTENT(IN) :: comm
5703 
5704  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
5705 
5706  INTEGER :: handle
5707 #if defined(__parallel)
5708  INTEGER :: ierr, msglen
5709 #endif
5710 
5711  CALL mp_timeset(routinen, handle)
5712 
5713 #if defined(__parallel)
5714  msglen = SIZE(msg)
5715  CALL mpi_send(msg, msglen, mpi_integer, dest, tag, comm%handle, ierr)
5716  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
5717  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_4_size)
5718 #else
5719  mark_used(msg)
5720  mark_used(dest)
5721  mark_used(tag)
5722  mark_used(comm)
5723  ! only defined in parallel
5724  cpabort("not in parallel mode")
5725 #endif
5726  CALL mp_timestop(handle)
5727  END SUBROUTINE mp_send_im3
5728 
5729 ! **************************************************************************************************
5730 !> \brief Receive one datum from another process
5731 !> \param[in,out] msg Place received data into this variable
5732 !> \param[in,out] source Process to receive from
5733 !> \param[in,out] tag Transfer identifier
5734 !> \param[in] comm Message passing environment identifier
5735 !> \par MPI mapping
5736 !> mpi_send
5737 ! **************************************************************************************************
5738  SUBROUTINE mp_recv_i (msg, source, tag, comm)
5739  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
5740  INTEGER, INTENT(INOUT) :: source, tag
5741  CLASS(mp_comm_type), INTENT(IN) :: comm
5742 
5743  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_i'
5744 
5745  INTEGER :: handle
5746 #if defined(__parallel)
5747  INTEGER :: ierr, msglen
5748  mpi_status_type :: status
5749 #endif
5750 
5751  CALL mp_timeset(routinen, handle)
5752 
5753 #if defined(__parallel)
5754  msglen = 1
5755  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
5756  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, mpi_status_ignore, ierr)
5757  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5758  ELSE
5759  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, status, ierr)
5760  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5761  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_4_size)
5762  source = status mpi_status_extract(mpi_source)
5763  tag = status mpi_status_extract(mpi_tag)
5764  END IF
5765 #else
5766  mark_used(msg)
5767  mark_used(source)
5768  mark_used(tag)
5769  mark_used(comm)
5770  ! only defined in parallel
5771  cpabort("not in parallel mode")
5772 #endif
5773  CALL mp_timestop(handle)
5774  END SUBROUTINE mp_recv_i
5775 
5776 ! **************************************************************************************************
5777 !> \brief Receive rank-1 data from another process
5778 !> \param[in,out] msg Place received data into this rank-1 array
5779 !> \param source ...
5780 !> \param tag ...
5781 !> \param comm ...
5782 !> \note see mp_recv_i
5783 ! **************************************************************************************************
5784  SUBROUTINE mp_recv_iv(msg, source, tag, comm)
5785  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
5786  INTEGER, INTENT(INOUT) :: source, tag
5787  CLASS(mp_comm_type), INTENT(IN) :: comm
5788 
5789  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_iv'
5790 
5791  INTEGER :: handle
5792 #if defined(__parallel)
5793  INTEGER :: ierr, msglen
5794  mpi_status_type :: status
5795 #endif
5796 
5797  CALL mp_timeset(routinen, handle)
5798 
5799 #if defined(__parallel)
5800  msglen = SIZE(msg)
5801  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
5802  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, mpi_status_ignore, ierr)
5803  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5804  ELSE
5805  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, status, ierr)
5806  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5807  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_4_size)
5808  source = status mpi_status_extract(mpi_source)
5809  tag = status mpi_status_extract(mpi_tag)
5810  END IF
5811 #else
5812  mark_used(msg)
5813  mark_used(source)
5814  mark_used(tag)
5815  mark_used(comm)
5816  ! only defined in parallel
5817  cpabort("not in parallel mode")
5818 #endif
5819  CALL mp_timestop(handle)
5820  END SUBROUTINE mp_recv_iv
5821 
5822 ! **************************************************************************************************
5823 !> \brief Receive rank-2 data from another process
5824 !> \param[in,out] msg Place received data into this rank-2 array
5825 !> \param source ...
5826 !> \param tag ...
5827 !> \param comm ...
5828 !> \note see mp_recv_i
5829 ! **************************************************************************************************
5830  SUBROUTINE mp_recv_im2(msg, source, tag, comm)
5831  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
5832  INTEGER, INTENT(INOUT) :: source, tag
5833  CLASS(mp_comm_type), INTENT(IN) :: comm
5834 
5835  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_im2'
5836 
5837  INTEGER :: handle
5838 #if defined(__parallel)
5839  INTEGER :: ierr, msglen
5840  mpi_status_type :: status
5841 #endif
5842 
5843  CALL mp_timeset(routinen, handle)
5844 
5845 #if defined(__parallel)
5846  msglen = SIZE(msg)
5847  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
5848  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, mpi_status_ignore, ierr)
5849  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5850  ELSE
5851  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, status, ierr)
5852  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5853  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_4_size)
5854  source = status mpi_status_extract(mpi_source)
5855  tag = status mpi_status_extract(mpi_tag)
5856  END IF
5857 #else
5858  mark_used(msg)
5859  mark_used(source)
5860  mark_used(tag)
5861  mark_used(comm)
5862  ! only defined in parallel
5863  cpabort("not in parallel mode")
5864 #endif
5865  CALL mp_timestop(handle)
5866  END SUBROUTINE mp_recv_im2
5867 
5868 ! **************************************************************************************************
5869 !> \brief Receive rank-3 data from another process
5870 !> \param[in,out] msg Place received data into this rank-3 array
5871 !> \param source ...
5872 !> \param tag ...
5873 !> \param comm ...
5874 !> \note see mp_recv_i
5875 ! **************************************************************************************************
5876  SUBROUTINE mp_recv_im3(msg, source, tag, comm)
5877  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
5878  INTEGER, INTENT(INOUT) :: source, tag
5879  CLASS(mp_comm_type), INTENT(IN) :: comm
5880 
5881  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_im3'
5882 
5883  INTEGER :: handle
5884 #if defined(__parallel)
5885  INTEGER :: ierr, msglen
5886  mpi_status_type :: status
5887 #endif
5888 
5889  CALL mp_timeset(routinen, handle)
5890 
5891 #if defined(__parallel)
5892  msglen = SIZE(msg)
5893  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
5894  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, mpi_status_ignore, ierr)
5895  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5896  ELSE
5897  CALL mpi_recv(msg, msglen, mpi_integer, source, tag, comm%handle, status, ierr)
5898  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
5899  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_4_size)
5900  source = status mpi_status_extract(mpi_source)
5901  tag = status mpi_status_extract(mpi_tag)
5902  END IF
5903 #else
5904  mark_used(msg)
5905  mark_used(source)
5906  mark_used(tag)
5907  mark_used(comm)
5908  ! only defined in parallel
5909  cpabort("not in parallel mode")
5910 #endif
5911  CALL mp_timestop(handle)
5912  END SUBROUTINE mp_recv_im3
5913 
5914 ! **************************************************************************************************
5915 !> \brief Broadcasts a datum to all processes.
5916 !> \param[in] msg Datum to broadcast
5917 !> \param[in] source Processes which broadcasts
5918 !> \param[in] comm Message passing environment identifier
5919 !> \par MPI mapping
5920 !> mpi_bcast
5921 ! **************************************************************************************************
5922  SUBROUTINE mp_bcast_i (msg, source, comm)
5923  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
5924  INTEGER, INTENT(IN) :: source
5925  CLASS(mp_comm_type), INTENT(IN) :: comm
5926 
5927  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_i'
5928 
5929  INTEGER :: handle
5930 #if defined(__parallel)
5931  INTEGER :: ierr, msglen
5932 #endif
5933 
5934  CALL mp_timeset(routinen, handle)
5935 
5936 #if defined(__parallel)
5937  msglen = 1
5938  CALL mpi_bcast(msg, msglen, mpi_integer, source, comm%handle, ierr)
5939  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
5940  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
5941 #else
5942  mark_used(msg)
5943  mark_used(source)
5944  mark_used(comm)
5945 #endif
5946  CALL mp_timestop(handle)
5947  END SUBROUTINE mp_bcast_i
5948 
5949 ! **************************************************************************************************
5950 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
5951 !> \param[in] msg Datum to broadcast
5952 !> \param[in] comm Message passing environment identifier
5953 !> \par MPI mapping
5954 !> mpi_bcast
5955 ! **************************************************************************************************
5956  SUBROUTINE mp_bcast_i_src(msg, comm)
5957  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
5958  CLASS(mp_comm_type), INTENT(IN) :: comm
5959 
5960  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_i_src'
5961 
5962  INTEGER :: handle
5963 #if defined(__parallel)
5964  INTEGER :: ierr, msglen
5965 #endif
5966 
5967  CALL mp_timeset(routinen, handle)
5968 
5969 #if defined(__parallel)
5970  msglen = 1
5971  CALL mpi_bcast(msg, msglen, mpi_integer, comm%source, comm%handle, ierr)
5972  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
5973  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
5974 #else
5975  mark_used(msg)
5976  mark_used(comm)
5977 #endif
5978  CALL mp_timestop(handle)
5979  END SUBROUTINE mp_bcast_i_src
5980 
5981 ! **************************************************************************************************
5982 !> \brief Broadcasts a datum to all processes.
5983 !> \param[in] msg Datum to broadcast
5984 !> \param[in] source Processes which broadcasts
5985 !> \param[in] comm Message passing environment identifier
5986 !> \par MPI mapping
5987 !> mpi_bcast
5988 ! **************************************************************************************************
5989  SUBROUTINE mp_ibcast_i (msg, source, comm, request)
5990  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
5991  INTEGER, INTENT(IN) :: source
5992  CLASS(mp_comm_type), INTENT(IN) :: comm
5993  TYPE(mp_request_type), INTENT(OUT) :: request
5994 
5995  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_i'
5996 
5997  INTEGER :: handle
5998 #if defined(__parallel)
5999  INTEGER :: ierr, msglen
6000 #endif
6001 
6002  CALL mp_timeset(routinen, handle)
6003 
6004 #if defined(__parallel)
6005  msglen = 1
6006  CALL mpi_ibcast(msg, msglen, mpi_integer, source, comm%handle, request%handle, ierr)
6007  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
6008  CALL add_perf(perf_id=22, count=1, msg_size=msglen*int_4_size)
6009 #else
6010  mark_used(msg)
6011  mark_used(source)
6012  mark_used(comm)
6013  request = mp_request_null
6014 #endif
6015  CALL mp_timestop(handle)
6016  END SUBROUTINE mp_ibcast_i
6017 
6018 ! **************************************************************************************************
6019 !> \brief Broadcasts rank-1 data to all processes
6020 !> \param[in] msg Data to broadcast
6021 !> \param source ...
6022 !> \param comm ...
6023 !> \note see mp_bcast_i1
6024 ! **************************************************************************************************
6025  SUBROUTINE mp_bcast_iv(msg, source, comm)
6026  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
6027  INTEGER, INTENT(IN) :: source
6028  CLASS(mp_comm_type), INTENT(IN) :: comm
6029 
6030  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_iv'
6031 
6032  INTEGER :: handle
6033 #if defined(__parallel)
6034  INTEGER :: ierr, msglen
6035 #endif
6036 
6037  CALL mp_timeset(routinen, handle)
6038 
6039 #if defined(__parallel)
6040  msglen = SIZE(msg)
6041  CALL mpi_bcast(msg, msglen, mpi_integer, source, comm%handle, ierr)
6042  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6043  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6044 #else
6045  mark_used(msg)
6046  mark_used(source)
6047  mark_used(comm)
6048 #endif
6049  CALL mp_timestop(handle)
6050  END SUBROUTINE mp_bcast_iv
6051 
6052 ! **************************************************************************************************
6053 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
6054 !> \param[in] msg Data to broadcast
6055 !> \param comm ...
6056 !> \note see mp_bcast_i1
6057 ! **************************************************************************************************
6058  SUBROUTINE mp_bcast_iv_src(msg, comm)
6059  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
6060  CLASS(mp_comm_type), INTENT(IN) :: comm
6061 
6062  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_iv_src'
6063 
6064  INTEGER :: handle
6065 #if defined(__parallel)
6066  INTEGER :: ierr, msglen
6067 #endif
6068 
6069  CALL mp_timeset(routinen, handle)
6070 
6071 #if defined(__parallel)
6072  msglen = SIZE(msg)
6073  CALL mpi_bcast(msg, msglen, mpi_integer, comm%source, comm%handle, ierr)
6074  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6075  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6076 #else
6077  mark_used(msg)
6078  mark_used(comm)
6079 #endif
6080  CALL mp_timestop(handle)
6081  END SUBROUTINE mp_bcast_iv_src
6082 
6083 ! **************************************************************************************************
6084 !> \brief Broadcasts rank-1 data to all processes
6085 !> \param[in] msg Data to broadcast
6086 !> \param source ...
6087 !> \param comm ...
6088 !> \note see mp_bcast_i1
6089 ! **************************************************************************************************
6090  SUBROUTINE mp_ibcast_iv(msg, source, comm, request)
6091  INTEGER(KIND=int_4), INTENT(INOUT) :: msg(:)
6092  INTEGER, INTENT(IN) :: source
6093  CLASS(mp_comm_type), INTENT(IN) :: comm
6094  TYPE(mp_request_type) :: request
6095 
6096  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_iv'
6097 
6098  INTEGER :: handle
6099 #if defined(__parallel)
6100  INTEGER :: ierr, msglen
6101 #endif
6102 
6103  CALL mp_timeset(routinen, handle)
6104 
6105 #if defined(__parallel)
6106 #if !defined(__GNUC__) || __GNUC__ >= 9
6107  cpassert(is_contiguous(msg))
6108 #endif
6109  msglen = SIZE(msg)
6110  CALL mpi_ibcast(msg, msglen, mpi_integer, source, comm%handle, request%handle, ierr)
6111  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
6112  CALL add_perf(perf_id=22, count=1, msg_size=msglen*int_4_size)
6113 #else
6114  mark_used(msg)
6115  mark_used(source)
6116  mark_used(comm)
6117  request = mp_request_null
6118 #endif
6119  CALL mp_timestop(handle)
6120  END SUBROUTINE mp_ibcast_iv
6121 
6122 ! **************************************************************************************************
6123 !> \brief Broadcasts rank-2 data to all processes
6124 !> \param[in] msg Data to broadcast
6125 !> \param source ...
6126 !> \param comm ...
6127 !> \note see mp_bcast_i1
6128 ! **************************************************************************************************
6129  SUBROUTINE mp_bcast_im(msg, source, comm)
6130  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
6131  INTEGER, INTENT(IN) :: source
6132  CLASS(mp_comm_type), INTENT(IN) :: comm
6133 
6134  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_im'
6135 
6136  INTEGER :: handle
6137 #if defined(__parallel)
6138  INTEGER :: ierr, msglen
6139 #endif
6140 
6141  CALL mp_timeset(routinen, handle)
6142 
6143 #if defined(__parallel)
6144  msglen = SIZE(msg)
6145  CALL mpi_bcast(msg, msglen, mpi_integer, source, comm%handle, ierr)
6146  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6147  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6148 #else
6149  mark_used(msg)
6150  mark_used(source)
6151  mark_used(comm)
6152 #endif
6153  CALL mp_timestop(handle)
6154  END SUBROUTINE mp_bcast_im
6155 
6156 ! **************************************************************************************************
6157 !> \brief Broadcasts rank-2 data to all processes
6158 !> \param[in] msg Data to broadcast
6159 !> \param source ...
6160 !> \param comm ...
6161 !> \note see mp_bcast_i1
6162 ! **************************************************************************************************
6163  SUBROUTINE mp_bcast_im_src(msg, comm)
6164  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
6165  CLASS(mp_comm_type), INTENT(IN) :: comm
6166 
6167  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_im_src'
6168 
6169  INTEGER :: handle
6170 #if defined(__parallel)
6171  INTEGER :: ierr, msglen
6172 #endif
6173 
6174  CALL mp_timeset(routinen, handle)
6175 
6176 #if defined(__parallel)
6177  msglen = SIZE(msg)
6178  CALL mpi_bcast(msg, msglen, mpi_integer, comm%source, comm%handle, ierr)
6179  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6180  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6181 #else
6182  mark_used(msg)
6183  mark_used(comm)
6184 #endif
6185  CALL mp_timestop(handle)
6186  END SUBROUTINE mp_bcast_im_src
6187 
6188 ! **************************************************************************************************
6189 !> \brief Broadcasts rank-3 data to all processes
6190 !> \param[in] msg Data to broadcast
6191 !> \param source ...
6192 !> \param comm ...
6193 !> \note see mp_bcast_i1
6194 ! **************************************************************************************************
6195  SUBROUTINE mp_bcast_i3(msg, source, comm)
6196  INTEGER(KIND=int_4), CONTIGUOUS :: msg(:, :, :)
6197  INTEGER, INTENT(IN) :: source
6198  CLASS(mp_comm_type), INTENT(IN) :: comm
6199 
6200  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_i3'
6201 
6202  INTEGER :: handle
6203 #if defined(__parallel)
6204  INTEGER :: ierr, msglen
6205 #endif
6206 
6207  CALL mp_timeset(routinen, handle)
6208 
6209 #if defined(__parallel)
6210  msglen = SIZE(msg)
6211  CALL mpi_bcast(msg, msglen, mpi_integer, source, comm%handle, ierr)
6212  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6213  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6214 #else
6215  mark_used(msg)
6216  mark_used(source)
6217  mark_used(comm)
6218 #endif
6219  CALL mp_timestop(handle)
6220  END SUBROUTINE mp_bcast_i3
6221 
6222 ! **************************************************************************************************
6223 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
6224 !> \param[in] msg Data to broadcast
6225 !> \param source ...
6226 !> \param comm ...
6227 !> \note see mp_bcast_i1
6228 ! **************************************************************************************************
6229  SUBROUTINE mp_bcast_i3_src(msg, comm)
6230  INTEGER(KIND=int_4), CONTIGUOUS :: msg(:, :, :)
6231  CLASS(mp_comm_type), INTENT(IN) :: comm
6232 
6233  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_i3_src'
6234 
6235  INTEGER :: handle
6236 #if defined(__parallel)
6237  INTEGER :: ierr, msglen
6238 #endif
6239 
6240  CALL mp_timeset(routinen, handle)
6241 
6242 #if defined(__parallel)
6243  msglen = SIZE(msg)
6244  CALL mpi_bcast(msg, msglen, mpi_integer, comm%source, comm%handle, ierr)
6245  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
6246  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_4_size)
6247 #else
6248  mark_used(msg)
6249  mark_used(comm)
6250 #endif
6251  CALL mp_timestop(handle)
6252  END SUBROUTINE mp_bcast_i3_src
6253 
6254 ! **************************************************************************************************
6255 !> \brief Sums a datum from all processes with result left on all processes.
6256 !> \param[in,out] msg Datum to sum (input) and result (output)
6257 !> \param[in] comm Message passing environment identifier
6258 !> \par MPI mapping
6259 !> mpi_allreduce
6260 ! **************************************************************************************************
6261  SUBROUTINE mp_sum_i (msg, comm)
6262  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6263  CLASS(mp_comm_type), INTENT(IN) :: comm
6264 
6265  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_i'
6266 
6267  INTEGER :: handle
6268 #if defined(__parallel)
6269  INTEGER :: ierr, msglen
6270 #endif
6271 
6272  CALL mp_timeset(routinen, handle)
6273 
6274 #if defined(__parallel)
6275  msglen = 1
6276  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6277  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6278  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6279 #else
6280  mark_used(msg)
6281  mark_used(comm)
6282 #endif
6283  CALL mp_timestop(handle)
6284  END SUBROUTINE mp_sum_i
6285 
6286 ! **************************************************************************************************
6287 !> \brief Element-wise sum of a rank-1 array on all processes.
6288 !> \param[in,out] msg Vector to sum and result
6289 !> \param comm ...
6290 !> \note see mp_sum_i
6291 ! **************************************************************************************************
6292  SUBROUTINE mp_sum_iv(msg, comm)
6293  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
6294  CLASS(mp_comm_type), INTENT(IN) :: comm
6295 
6296  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_iv'
6297 
6298  INTEGER :: handle
6299 #if defined(__parallel)
6300  INTEGER :: ierr, msglen
6301 #endif
6302 
6303  CALL mp_timeset(routinen, handle)
6304 
6305 #if defined(__parallel)
6306  msglen = SIZE(msg)
6307  IF (msglen > 0) THEN
6308  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6309  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6310  END IF
6311  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6312 #else
6313  mark_used(msg)
6314  mark_used(comm)
6315 #endif
6316  CALL mp_timestop(handle)
6317  END SUBROUTINE mp_sum_iv
6318 
6319 ! **************************************************************************************************
6320 !> \brief Element-wise sum of a rank-1 array on all processes.
6321 !> \param[in,out] msg Vector to sum and result
6322 !> \param comm ...
6323 !> \note see mp_sum_i
6324 ! **************************************************************************************************
6325  SUBROUTINE mp_isum_iv(msg, comm, request)
6326  INTEGER(KIND=int_4), INTENT(INOUT) :: msg(:)
6327  CLASS(mp_comm_type), INTENT(IN) :: comm
6328  TYPE(mp_request_type), INTENT(OUT) :: request
6329 
6330  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_iv'
6331 
6332  INTEGER :: handle
6333 #if defined(__parallel)
6334  INTEGER :: ierr, msglen
6335 #endif
6336 
6337  CALL mp_timeset(routinen, handle)
6338 
6339 #if defined(__parallel)
6340 #if !defined(__GNUC__) || __GNUC__ >= 9
6341  cpassert(is_contiguous(msg))
6342 #endif
6343  msglen = SIZE(msg)
6344  IF (msglen > 0) THEN
6345  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_sum, comm%handle, request%handle, ierr)
6346  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
6347  ELSE
6348  request = mp_request_null
6349  END IF
6350  CALL add_perf(perf_id=23, count=1, msg_size=msglen*int_4_size)
6351 #else
6352  mark_used(msg)
6353  mark_used(comm)
6354  request = mp_request_null
6355 #endif
6356  CALL mp_timestop(handle)
6357  END SUBROUTINE mp_isum_iv
6358 
6359 ! **************************************************************************************************
6360 !> \brief Element-wise sum of a rank-2 array on all processes.
6361 !> \param[in] msg Matrix to sum and result
6362 !> \param comm ...
6363 !> \note see mp_sum_i
6364 ! **************************************************************************************************
6365  SUBROUTINE mp_sum_im(msg, comm)
6366  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
6367  CLASS(mp_comm_type), INTENT(IN) :: comm
6368 
6369  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_im'
6370 
6371  INTEGER :: handle
6372 #if defined(__parallel)
6373  INTEGER, PARAMETER :: max_msg = 2**25
6374  INTEGER :: ierr, m1, msglen, step, msglensum
6375 #endif
6376 
6377  CALL mp_timeset(routinen, handle)
6378 
6379 #if defined(__parallel)
6380  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
6381  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
6382  msglensum = 0
6383  DO m1 = lbound(msg, 2), ubound(msg, 2), step
6384  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
6385  msglensum = msglensum + msglen
6386  IF (msglen > 0) THEN
6387  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6388  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6389  END IF
6390  END DO
6391  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*int_4_size)
6392 #else
6393  mark_used(msg)
6394  mark_used(comm)
6395 #endif
6396  CALL mp_timestop(handle)
6397  END SUBROUTINE mp_sum_im
6398 
6399 ! **************************************************************************************************
6400 !> \brief Element-wise sum of a rank-3 array on all processes.
6401 !> \param[in] msg Array to sum and result
6402 !> \param comm ...
6403 !> \note see mp_sum_i
6404 ! **************************************************************************************************
6405  SUBROUTINE mp_sum_im3(msg, comm)
6406  INTEGER(KIND=int_4), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
6407  CLASS(mp_comm_type), INTENT(IN) :: comm
6408 
6409  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_im3'
6410 
6411  INTEGER :: handle
6412 #if defined(__parallel)
6413  INTEGER :: ierr, msglen
6414 #endif
6415 
6416  CALL mp_timeset(routinen, handle)
6417 
6418 #if defined(__parallel)
6419  msglen = SIZE(msg)
6420  IF (msglen > 0) THEN
6421  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6422  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6423  END IF
6424  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6425 #else
6426  mark_used(msg)
6427  mark_used(comm)
6428 #endif
6429  CALL mp_timestop(handle)
6430  END SUBROUTINE mp_sum_im3
6431 
6432 ! **************************************************************************************************
6433 !> \brief Element-wise sum of a rank-4 array on all processes.
6434 !> \param[in] msg Array to sum and result
6435 !> \param comm ...
6436 !> \note see mp_sum_i
6437 ! **************************************************************************************************
6438  SUBROUTINE mp_sum_im4(msg, comm)
6439  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
6440  CLASS(mp_comm_type), INTENT(IN) :: comm
6441 
6442  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_im4'
6443 
6444  INTEGER :: handle
6445 #if defined(__parallel)
6446  INTEGER :: ierr, msglen
6447 #endif
6448 
6449  CALL mp_timeset(routinen, handle)
6450 
6451 #if defined(__parallel)
6452  msglen = SIZE(msg)
6453  IF (msglen > 0) THEN
6454  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6455  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6456  END IF
6457  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6458 #else
6459  mark_used(msg)
6460  mark_used(comm)
6461 #endif
6462  CALL mp_timestop(handle)
6463  END SUBROUTINE mp_sum_im4
6464 
6465 ! **************************************************************************************************
6466 !> \brief Element-wise sum of data from all processes with result left only on
6467 !> one.
6468 !> \param[in,out] msg Vector to sum (input) and (only on process root)
6469 !> result (output)
6470 !> \param root ...
6471 !> \param[in] comm Message passing environment identifier
6472 !> \par MPI mapping
6473 !> mpi_reduce
6474 ! **************************************************************************************************
6475  SUBROUTINE mp_sum_root_iv(msg, root, comm)
6476  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
6477  INTEGER, INTENT(IN) :: root
6478  CLASS(mp_comm_type), INTENT(IN) :: comm
6479 
6480  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_iv'
6481 
6482  INTEGER :: handle
6483 #if defined(__parallel)
6484  INTEGER :: ierr, m1, msglen, taskid
6485  INTEGER(KIND=int_4), ALLOCATABLE :: res(:)
6486 #endif
6487 
6488  CALL mp_timeset(routinen, handle)
6489 
6490 #if defined(__parallel)
6491  msglen = SIZE(msg)
6492  CALL mpi_comm_rank(comm%handle, taskid, ierr)
6493  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
6494  IF (msglen > 0) THEN
6495  m1 = SIZE(msg, 1)
6496  ALLOCATE (res(m1))
6497  CALL mpi_reduce(msg, res, msglen, mpi_integer, mpi_sum, &
6498  root, comm%handle, ierr)
6499  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
6500  IF (taskid == root) THEN
6501  msg = res
6502  END IF
6503  DEALLOCATE (res)
6504  END IF
6505  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6506 #else
6507  mark_used(msg)
6508  mark_used(root)
6509  mark_used(comm)
6510 #endif
6511  CALL mp_timestop(handle)
6512  END SUBROUTINE mp_sum_root_iv
6513 
6514 ! **************************************************************************************************
6515 !> \brief Element-wise sum of data from all processes with result left only on
6516 !> one.
6517 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
6518 !> result (output)
6519 !> \param root ...
6520 !> \param comm ...
6521 !> \note see mp_sum_root_iv
6522 ! **************************************************************************************************
6523  SUBROUTINE mp_sum_root_im(msg, root, comm)
6524  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
6525  INTEGER, INTENT(IN) :: root
6526  CLASS(mp_comm_type), INTENT(IN) :: comm
6527 
6528  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
6529 
6530  INTEGER :: handle
6531 #if defined(__parallel)
6532  INTEGER :: ierr, m1, m2, msglen, taskid
6533  INTEGER(KIND=int_4), ALLOCATABLE :: res(:, :)
6534 #endif
6535 
6536  CALL mp_timeset(routinen, handle)
6537 
6538 #if defined(__parallel)
6539  msglen = SIZE(msg)
6540  CALL mpi_comm_rank(comm%handle, taskid, ierr)
6541  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
6542  IF (msglen > 0) THEN
6543  m1 = SIZE(msg, 1)
6544  m2 = SIZE(msg, 2)
6545  ALLOCATE (res(m1, m2))
6546  CALL mpi_reduce(msg, res, msglen, mpi_integer, mpi_sum, root, comm%handle, ierr)
6547  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
6548  IF (taskid == root) THEN
6549  msg = res
6550  END IF
6551  DEALLOCATE (res)
6552  END IF
6553  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6554 #else
6555  mark_used(root)
6556  mark_used(msg)
6557  mark_used(comm)
6558 #endif
6559  CALL mp_timestop(handle)
6560  END SUBROUTINE mp_sum_root_im
6561 
6562 ! **************************************************************************************************
6563 !> \brief Partial sum of data from all processes with result on each process.
6564 !> \param[in] msg Matrix to sum (input)
6565 !> \param[out] res Matrix containing result (output)
6566 !> \param[in] comm Message passing environment identifier
6567 ! **************************************************************************************************
6568  SUBROUTINE mp_sum_partial_im(msg, res, comm)
6569  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
6570  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: res(:, :)
6571  CLASS(mp_comm_type), INTENT(IN) :: comm
6572 
6573  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_im'
6574 
6575  INTEGER :: handle
6576 #if defined(__parallel)
6577  INTEGER :: ierr, msglen, taskid
6578 #endif
6579 
6580  CALL mp_timeset(routinen, handle)
6581 
6582 #if defined(__parallel)
6583  msglen = SIZE(msg)
6584  CALL mpi_comm_rank(comm%handle, taskid, ierr)
6585  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
6586  IF (msglen > 0) THEN
6587  CALL mpi_scan(msg, res, msglen, mpi_integer, mpi_sum, comm%handle, ierr)
6588  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
6589  END IF
6590  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6591  ! perf_id is same as for other summation routines
6592 #else
6593  res = msg
6594  mark_used(comm)
6595 #endif
6596  CALL mp_timestop(handle)
6597  END SUBROUTINE mp_sum_partial_im
6598 
6599 ! **************************************************************************************************
6600 !> \brief Finds the maximum of a datum with the result left on all processes.
6601 !> \param[in,out] msg Find maximum among these data (input) and
6602 !> maximum (output)
6603 !> \param[in] comm Message passing environment identifier
6604 !> \par MPI mapping
6605 !> mpi_allreduce
6606 ! **************************************************************************************************
6607  SUBROUTINE mp_max_i (msg, comm)
6608  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6609  CLASS(mp_comm_type), INTENT(IN) :: comm
6610 
6611  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_i'
6612 
6613  INTEGER :: handle
6614 #if defined(__parallel)
6615  INTEGER :: ierr, msglen
6616 #endif
6617 
6618  CALL mp_timeset(routinen, handle)
6619 
6620 #if defined(__parallel)
6621  msglen = 1
6622  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_max, comm%handle, ierr)
6623  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6624  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6625 #else
6626  mark_used(msg)
6627  mark_used(comm)
6628 #endif
6629  CALL mp_timestop(handle)
6630  END SUBROUTINE mp_max_i
6631 
6632 ! **************************************************************************************************
6633 !> \brief Finds the maximum of a datum with the result left on all processes.
6634 !> \param[in,out] msg Find maximum among these data (input) and
6635 !> maximum (output)
6636 !> \param[in] comm Message passing environment identifier
6637 !> \par MPI mapping
6638 !> mpi_allreduce
6639 ! **************************************************************************************************
6640  SUBROUTINE mp_max_root_i (msg, root, comm)
6641  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6642  INTEGER, INTENT(IN) :: root
6643  CLASS(mp_comm_type), INTENT(IN) :: comm
6644 
6645  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_i'
6646 
6647  INTEGER :: handle
6648 #if defined(__parallel)
6649  INTEGER :: ierr, msglen
6650  INTEGER(KIND=int_4) :: res
6651 #endif
6652 
6653  CALL mp_timeset(routinen, handle)
6654 
6655 #if defined(__parallel)
6656  msglen = 1
6657  CALL mpi_reduce(msg, res, msglen, mpi_integer, mpi_max, root, comm%handle, ierr)
6658  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
6659  IF (root == comm%mepos) msg = res
6660  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6661 #else
6662  mark_used(msg)
6663  mark_used(comm)
6664  mark_used(root)
6665 #endif
6666  CALL mp_timestop(handle)
6667  END SUBROUTINE mp_max_root_i
6668 
6669 ! **************************************************************************************************
6670 !> \brief Finds the element-wise maximum of a vector with the result left on
6671 !> all processes.
6672 !> \param[in,out] msg Find maximum among these data (input) and
6673 !> maximum (output)
6674 !> \param comm ...
6675 !> \note see mp_max_i
6676 ! **************************************************************************************************
6677  SUBROUTINE mp_max_iv(msg, comm)
6678  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
6679  CLASS(mp_comm_type), INTENT(IN) :: comm
6680 
6681  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_iv'
6682 
6683  INTEGER :: handle
6684 #if defined(__parallel)
6685  INTEGER :: ierr, msglen
6686 #endif
6687 
6688  CALL mp_timeset(routinen, handle)
6689 
6690 #if defined(__parallel)
6691  msglen = SIZE(msg)
6692  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_max, comm%handle, ierr)
6693  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6694  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6695 #else
6696  mark_used(msg)
6697  mark_used(comm)
6698 #endif
6699  CALL mp_timestop(handle)
6700  END SUBROUTINE mp_max_iv
6701 
6702 ! **************************************************************************************************
6703 !> \brief Finds the element-wise maximum of a vector with the result left on
6704 !> all processes.
6705 !> \param[in,out] msg Find maximum among these data (input) and
6706 !> maximum (output)
6707 !> \param comm ...
6708 !> \note see mp_max_i
6709 ! **************************************************************************************************
6710  SUBROUTINE mp_max_root_im(msg, root, comm)
6711  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
6712  INTEGER :: root
6713  CLASS(mp_comm_type), INTENT(IN) :: comm
6714 
6715  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_im'
6716 
6717  INTEGER :: handle
6718 #if defined(__parallel)
6719  INTEGER :: ierr, msglen
6720  INTEGER(KIND=int_4) :: res(size(msg, 1), size(msg, 2))
6721 #endif
6722 
6723  CALL mp_timeset(routinen, handle)
6724 
6725 #if defined(__parallel)
6726  msglen = SIZE(msg)
6727  CALL mpi_reduce(msg, res, msglen, mpi_integer, mpi_max, root, comm%handle, ierr)
6728  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6729  IF (root == comm%mepos) msg = res
6730  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6731 #else
6732  mark_used(msg)
6733  mark_used(comm)
6734  mark_used(root)
6735 #endif
6736  CALL mp_timestop(handle)
6737  END SUBROUTINE mp_max_root_im
6738 
6739 ! **************************************************************************************************
6740 !> \brief Finds the minimum of a datum with the result left on all processes.
6741 !> \param[in,out] msg Find minimum among these data (input) and
6742 !> maximum (output)
6743 !> \param[in] comm Message passing environment identifier
6744 !> \par MPI mapping
6745 !> mpi_allreduce
6746 ! **************************************************************************************************
6747  SUBROUTINE mp_min_i (msg, comm)
6748  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6749  CLASS(mp_comm_type), INTENT(IN) :: comm
6750 
6751  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_i'
6752 
6753  INTEGER :: handle
6754 #if defined(__parallel)
6755  INTEGER :: ierr, msglen
6756 #endif
6757 
6758  CALL mp_timeset(routinen, handle)
6759 
6760 #if defined(__parallel)
6761  msglen = 1
6762  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_min, comm%handle, ierr)
6763  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6764  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6765 #else
6766  mark_used(msg)
6767  mark_used(comm)
6768 #endif
6769  CALL mp_timestop(handle)
6770  END SUBROUTINE mp_min_i
6771 
6772 ! **************************************************************************************************
6773 !> \brief Finds the element-wise minimum of vector with the result left on
6774 !> all processes.
6775 !> \param[in,out] msg Find minimum among these data (input) and
6776 !> maximum (output)
6777 !> \param comm ...
6778 !> \par MPI mapping
6779 !> mpi_allreduce
6780 !> \note see mp_min_i
6781 ! **************************************************************************************************
6782  SUBROUTINE mp_min_iv(msg, comm)
6783  INTEGER(KIND=int_4), INTENT(INOUT), CONTIGUOUS :: msg(:)
6784  CLASS(mp_comm_type), INTENT(IN) :: comm
6785 
6786  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_iv'
6787 
6788  INTEGER :: handle
6789 #if defined(__parallel)
6790  INTEGER :: ierr, msglen
6791 #endif
6792 
6793  CALL mp_timeset(routinen, handle)
6794 
6795 #if defined(__parallel)
6796  msglen = SIZE(msg)
6797  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_min, comm%handle, ierr)
6798  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6799  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6800 #else
6801  mark_used(msg)
6802  mark_used(comm)
6803 #endif
6804  CALL mp_timestop(handle)
6805  END SUBROUTINE mp_min_iv
6806 
6807 ! **************************************************************************************************
6808 !> \brief Multiplies a set of numbers scattered across a number of processes,
6809 !> then replicates the result.
6810 !> \param[in,out] msg a number to multiply (input) and result (output)
6811 !> \param[in] comm message passing environment identifier
6812 !> \par MPI mapping
6813 !> mpi_allreduce
6814 ! **************************************************************************************************
6815  SUBROUTINE mp_prod_i (msg, comm)
6816  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6817  CLASS(mp_comm_type), INTENT(IN) :: comm
6818 
6819  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_i'
6820 
6821  INTEGER :: handle
6822 #if defined(__parallel)
6823  INTEGER :: ierr, msglen
6824 #endif
6825 
6826  CALL mp_timeset(routinen, handle)
6827 
6828 #if defined(__parallel)
6829  msglen = 1
6830  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer, mpi_prod, comm%handle, ierr)
6831  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
6832  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_4_size)
6833 #else
6834  mark_used(msg)
6835  mark_used(comm)
6836 #endif
6837  CALL mp_timestop(handle)
6838  END SUBROUTINE mp_prod_i
6839 
6840 ! **************************************************************************************************
6841 !> \brief Scatters data from one processes to all others
6842 !> \param[in] msg_scatter Data to scatter (for root process)
6843 !> \param[out] msg Received data
6844 !> \param[in] root Process which scatters data
6845 !> \param[in] comm Message passing environment identifier
6846 !> \par MPI mapping
6847 !> mpi_scatter
6848 ! **************************************************************************************************
6849  SUBROUTINE mp_scatter_iv(msg_scatter, msg, root, comm)
6850  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
6851  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg(:)
6852  INTEGER, INTENT(IN) :: root
6853  CLASS(mp_comm_type), INTENT(IN) :: comm
6854 
6855  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_iv'
6856 
6857  INTEGER :: handle
6858 #if defined(__parallel)
6859  INTEGER :: ierr, msglen
6860 #endif
6861 
6862  CALL mp_timeset(routinen, handle)
6863 
6864 #if defined(__parallel)
6865  msglen = SIZE(msg)
6866  CALL mpi_scatter(msg_scatter, msglen, mpi_integer, msg, &
6867  msglen, mpi_integer, root, comm%handle, ierr)
6868  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
6869  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
6870 #else
6871  mark_used(root)
6872  mark_used(comm)
6873  msg = msg_scatter
6874 #endif
6875  CALL mp_timestop(handle)
6876  END SUBROUTINE mp_scatter_iv
6877 
6878 ! **************************************************************************************************
6879 !> \brief Scatters data from one processes to all others
6880 !> \param[in] msg_scatter Data to scatter (for root process)
6881 !> \param[in] root Process which scatters data
6882 !> \param[in] comm Message passing environment identifier
6883 !> \par MPI mapping
6884 !> mpi_scatter
6885 ! **************************************************************************************************
6886  SUBROUTINE mp_iscatter_i (msg_scatter, msg, root, comm, request)
6887  INTEGER(KIND=int_4), INTENT(IN) :: msg_scatter(:)
6888  INTEGER(KIND=int_4), INTENT(INOUT) :: msg
6889  INTEGER, INTENT(IN) :: root
6890  CLASS(mp_comm_type), INTENT(IN) :: comm
6891  TYPE(mp_request_type), INTENT(OUT) :: request
6892 
6893  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_i'
6894 
6895  INTEGER :: handle
6896 #if defined(__parallel)
6897  INTEGER :: ierr, msglen
6898 #endif
6899 
6900  CALL mp_timeset(routinen, handle)
6901 
6902 #if defined(__parallel)
6903 #if !defined(__GNUC__) || __GNUC__ >= 9
6904  cpassert(is_contiguous(msg_scatter))
6905 #endif
6906  msglen = 1
6907  CALL mpi_iscatter(msg_scatter, msglen, mpi_integer, msg, &
6908  msglen, mpi_integer, root, comm%handle, request%handle, ierr)
6909  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
6910  CALL add_perf(perf_id=24, count=1, msg_size=1*int_4_size)
6911 #else
6912  mark_used(root)
6913  mark_used(comm)
6914  msg = msg_scatter(1)
6915  request = mp_request_null
6916 #endif
6917  CALL mp_timestop(handle)
6918  END SUBROUTINE mp_iscatter_i
6919 
6920 ! **************************************************************************************************
6921 !> \brief Scatters data from one processes to all others
6922 !> \param[in] msg_scatter Data to scatter (for root process)
6923 !> \param[in] root Process which scatters data
6924 !> \param[in] comm Message passing environment identifier
6925 !> \par MPI mapping
6926 !> mpi_scatter
6927 ! **************************************************************************************************
6928  SUBROUTINE mp_iscatter_iv2(msg_scatter, msg, root, comm, request)
6929  INTEGER(KIND=int_4), INTENT(IN) :: msg_scatter(:, :)
6930  INTEGER(KIND=int_4), INTENT(INOUT) :: msg(:)
6931  INTEGER, INTENT(IN) :: root
6932  CLASS(mp_comm_type), INTENT(IN) :: comm
6933  TYPE(mp_request_type), INTENT(OUT) :: request
6934 
6935  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_iv2'
6936 
6937  INTEGER :: handle
6938 #if defined(__parallel)
6939  INTEGER :: ierr, msglen
6940 #endif
6941 
6942  CALL mp_timeset(routinen, handle)
6943 
6944 #if defined(__parallel)
6945 #if !defined(__GNUC__) || __GNUC__ >= 9
6946  cpassert(is_contiguous(msg_scatter))
6947 #endif
6948  msglen = SIZE(msg)
6949  CALL mpi_iscatter(msg_scatter, msglen, mpi_integer, msg, &
6950  msglen, mpi_integer, root, comm%handle, request%handle, ierr)
6951  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
6952  CALL add_perf(perf_id=24, count=1, msg_size=1*int_4_size)
6953 #else
6954  mark_used(root)
6955  mark_used(comm)
6956  msg(:) = msg_scatter(:, 1)
6957  request = mp_request_null
6958 #endif
6959  CALL mp_timestop(handle)
6960  END SUBROUTINE mp_iscatter_iv2
6961 
6962 ! **************************************************************************************************
6963 !> \brief Scatters data from one processes to all others
6964 !> \param[in] msg_scatter Data to scatter (for root process)
6965 !> \param[in] root Process which scatters data
6966 !> \param[in] comm Message passing environment identifier
6967 !> \par MPI mapping
6968 !> mpi_scatter
6969 ! **************************************************************************************************
6970  SUBROUTINE mp_iscatterv_iv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
6971  INTEGER(KIND=int_4), INTENT(IN) :: msg_scatter(:)
6972  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
6973  INTEGER(KIND=int_4), INTENT(INOUT) :: msg(:)
6974  INTEGER, INTENT(IN) :: recvcount, root
6975  CLASS(mp_comm_type), INTENT(IN) :: comm
6976  TYPE(mp_request_type), INTENT(OUT) :: request
6977 
6978  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_iv'
6979 
6980  INTEGER :: handle
6981 #if defined(__parallel)
6982  INTEGER :: ierr
6983 #endif
6984 
6985  CALL mp_timeset(routinen, handle)
6986 
6987 #if defined(__parallel)
6988 #if !defined(__GNUC__) || __GNUC__ >= 9
6989  cpassert(is_contiguous(msg_scatter))
6990  cpassert(is_contiguous(msg))
6991  cpassert(is_contiguous(sendcounts))
6992  cpassert(is_contiguous(displs))
6993 #endif
6994  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_integer, msg, &
6995  recvcount, mpi_integer, root, comm%handle, request%handle, ierr)
6996  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
6997  CALL add_perf(perf_id=24, count=1, msg_size=1*int_4_size)
6998 #else
6999  mark_used(sendcounts)
7000  mark_used(displs)
7001  mark_used(recvcount)
7002  mark_used(root)
7003  mark_used(comm)
7004  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
7005  request = mp_request_null
7006 #endif
7007  CALL mp_timestop(handle)
7008  END SUBROUTINE mp_iscatterv_iv
7009 
7010 ! **************************************************************************************************
7011 !> \brief Gathers a datum from all processes to one
7012 !> \param[in] msg Datum to send to root
7013 !> \param[out] msg_gather Received data (on root)
7014 !> \param[in] root Process which gathers the data
7015 !> \param[in] comm Message passing environment identifier
7016 !> \par MPI mapping
7017 !> mpi_gather
7018 ! **************************************************************************************************
7019  SUBROUTINE mp_gather_i (msg, msg_gather, root, comm)
7020  INTEGER(KIND=int_4), INTENT(IN) :: msg
7021  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
7022  INTEGER, INTENT(IN) :: root
7023  CLASS(mp_comm_type), INTENT(IN) :: comm
7024 
7025  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_i'
7026 
7027  INTEGER :: handle
7028 #if defined(__parallel)
7029  INTEGER :: ierr, msglen
7030 #endif
7031 
7032  CALL mp_timeset(routinen, handle)
7033 
7034 #if defined(__parallel)
7035  msglen = 1
7036  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7037  msglen, mpi_integer, root, comm%handle, ierr)
7038  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7039  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7040 #else
7041  mark_used(root)
7042  mark_used(comm)
7043  msg_gather(1) = msg
7044 #endif
7045  CALL mp_timestop(handle)
7046  END SUBROUTINE mp_gather_i
7047 
7048 ! **************************************************************************************************
7049 !> \brief Gathers a datum from all processes to one, uses the source process of comm
7050 !> \param[in] msg Datum to send to root
7051 !> \param[out] msg_gather Received data (on root)
7052 !> \param[in] comm Message passing environment identifier
7053 !> \par MPI mapping
7054 !> mpi_gather
7055 ! **************************************************************************************************
7056  SUBROUTINE mp_gather_i_src(msg, msg_gather, comm)
7057  INTEGER(KIND=int_4), INTENT(IN) :: msg
7058  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
7059  CLASS(mp_comm_type), INTENT(IN) :: comm
7060 
7061  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_i_src'
7062 
7063  INTEGER :: handle
7064 #if defined(__parallel)
7065  INTEGER :: ierr, msglen
7066 #endif
7067 
7068  CALL mp_timeset(routinen, handle)
7069 
7070 #if defined(__parallel)
7071  msglen = 1
7072  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7073  msglen, mpi_integer, comm%source, comm%handle, ierr)
7074  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7075  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7076 #else
7077  mark_used(comm)
7078  msg_gather(1) = msg
7079 #endif
7080  CALL mp_timestop(handle)
7081  END SUBROUTINE mp_gather_i_src
7082 
7083 ! **************************************************************************************************
7084 !> \brief Gathers data from all processes to one
7085 !> \param[in] msg Datum to send to root
7086 !> \param msg_gather ...
7087 !> \param root ...
7088 !> \param comm ...
7089 !> \par Data length
7090 !> All data (msg) is equal-sized
7091 !> \par MPI mapping
7092 !> mpi_gather
7093 !> \note see mp_gather_i
7094 ! **************************************************************************************************
7095  SUBROUTINE mp_gather_iv(msg, msg_gather, root, comm)
7096  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:)
7097  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
7098  INTEGER, INTENT(IN) :: root
7099  CLASS(mp_comm_type), INTENT(IN) :: comm
7100 
7101  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_iv'
7102 
7103  INTEGER :: handle
7104 #if defined(__parallel)
7105  INTEGER :: ierr, msglen
7106 #endif
7107 
7108  CALL mp_timeset(routinen, handle)
7109 
7110 #if defined(__parallel)
7111  msglen = SIZE(msg)
7112  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7113  msglen, mpi_integer, root, comm%handle, ierr)
7114  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7115  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7116 #else
7117  mark_used(root)
7118  mark_used(comm)
7119  msg_gather = msg
7120 #endif
7121  CALL mp_timestop(handle)
7122  END SUBROUTINE mp_gather_iv
7123 
7124 ! **************************************************************************************************
7125 !> \brief Gathers data from all processes to one. Gathers from comm%source
7126 !> \param[in] msg Datum to send to root
7127 !> \param msg_gather ...
7128 !> \param comm ...
7129 !> \par Data length
7130 !> All data (msg) is equal-sized
7131 !> \par MPI mapping
7132 !> mpi_gather
7133 !> \note see mp_gather_i
7134 ! **************************************************************************************************
7135  SUBROUTINE mp_gather_iv_src(msg, msg_gather, comm)
7136  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:)
7137  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
7138  CLASS(mp_comm_type), INTENT(IN) :: comm
7139 
7140  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_iv_src'
7141 
7142  INTEGER :: handle
7143 #if defined(__parallel)
7144  INTEGER :: ierr, msglen
7145 #endif
7146 
7147  CALL mp_timeset(routinen, handle)
7148 
7149 #if defined(__parallel)
7150  msglen = SIZE(msg)
7151  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7152  msglen, mpi_integer, comm%source, comm%handle, ierr)
7153  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7154  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7155 #else
7156  mark_used(comm)
7157  msg_gather = msg
7158 #endif
7159  CALL mp_timestop(handle)
7160  END SUBROUTINE mp_gather_iv_src
7161 
7162 ! **************************************************************************************************
7163 !> \brief Gathers data from all processes to one
7164 !> \param[in] msg Datum to send to root
7165 !> \param msg_gather ...
7166 !> \param root ...
7167 !> \param comm ...
7168 !> \par Data length
7169 !> All data (msg) is equal-sized
7170 !> \par MPI mapping
7171 !> mpi_gather
7172 !> \note see mp_gather_i
7173 ! **************************************************************************************************
7174  SUBROUTINE mp_gather_im(msg, msg_gather, root, comm)
7175  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
7176  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
7177  INTEGER, INTENT(IN) :: root
7178  CLASS(mp_comm_type), INTENT(IN) :: comm
7179 
7180  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_im'
7181 
7182  INTEGER :: handle
7183 #if defined(__parallel)
7184  INTEGER :: ierr, msglen
7185 #endif
7186 
7187  CALL mp_timeset(routinen, handle)
7188 
7189 #if defined(__parallel)
7190  msglen = SIZE(msg)
7191  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7192  msglen, mpi_integer, root, comm%handle, ierr)
7193  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7194  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7195 #else
7196  mark_used(root)
7197  mark_used(comm)
7198  msg_gather = msg
7199 #endif
7200  CALL mp_timestop(handle)
7201  END SUBROUTINE mp_gather_im
7202 
7203 ! **************************************************************************************************
7204 !> \brief Gathers data from all processes to one. Gathers from comm%source
7205 !> \param[in] msg Datum to send to root
7206 !> \param msg_gather ...
7207 !> \param comm ...
7208 !> \par Data length
7209 !> All data (msg) is equal-sized
7210 !> \par MPI mapping
7211 !> mpi_gather
7212 !> \note see mp_gather_i
7213 ! **************************************************************************************************
7214  SUBROUTINE mp_gather_im_src(msg, msg_gather, comm)
7215  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
7216  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
7217  CLASS(mp_comm_type), INTENT(IN) :: comm
7218 
7219  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_im_src'
7220 
7221  INTEGER :: handle
7222 #if defined(__parallel)
7223  INTEGER :: ierr, msglen
7224 #endif
7225 
7226  CALL mp_timeset(routinen, handle)
7227 
7228 #if defined(__parallel)
7229  msglen = SIZE(msg)
7230  CALL mpi_gather(msg, msglen, mpi_integer, msg_gather, &
7231  msglen, mpi_integer, comm%source, comm%handle, ierr)
7232  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
7233  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_4_size)
7234 #else
7235  mark_used(comm)
7236  msg_gather = msg
7237 #endif
7238  CALL mp_timestop(handle)
7239  END SUBROUTINE mp_gather_im_src
7240 
7241 ! **************************************************************************************************
7242 !> \brief Gathers data from all processes to one.
7243 !> \param[in] sendbuf Data to send to root
7244 !> \param[out] recvbuf Received data (on root)
7245 !> \param[in] recvcounts Sizes of data received from processes
7246 !> \param[in] displs Offsets of data received from processes
7247 !> \param[in] root Process which gathers the data
7248 !> \param[in] comm Message passing environment identifier
7249 !> \par Data length
7250 !> Data can have different lengths
7251 !> \par Offsets
7252 !> Offsets start at 0
7253 !> \par MPI mapping
7254 !> mpi_gather
7255 ! **************************************************************************************************
7256  SUBROUTINE mp_gatherv_iv(sendbuf, recvbuf, recvcounts, displs, root, comm)
7257 
7258  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
7259  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
7260  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
7261  INTEGER, INTENT(IN) :: root
7262  CLASS(mp_comm_type), INTENT(IN) :: comm
7263 
7264  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_iv'
7265 
7266  INTEGER :: handle
7267 #if defined(__parallel)
7268  INTEGER :: ierr, sendcount
7269 #endif
7270 
7271  CALL mp_timeset(routinen, handle)
7272 
7273 #if defined(__parallel)
7274  sendcount = SIZE(sendbuf)
7275  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer, &
7276  recvbuf, recvcounts, displs, mpi_integer, &
7277  root, comm%handle, ierr)
7278  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
7279  CALL add_perf(perf_id=4, &
7280  count=1, &
7281  msg_size=sendcount*int_4_size)
7282 #else
7283  mark_used(recvcounts)
7284  mark_used(root)
7285  mark_used(comm)
7286  recvbuf(1 + displs(1):) = sendbuf
7287 #endif
7288  CALL mp_timestop(handle)
7289  END SUBROUTINE mp_gatherv_iv
7290 
7291 ! **************************************************************************************************
7292 !> \brief Gathers data from all processes to one. Gathers from comm%source
7293 !> \param[in] sendbuf Data to send to root
7294 !> \param[out] recvbuf Received data (on root)
7295 !> \param[in] recvcounts Sizes of data received from processes
7296 !> \param[in] displs Offsets of data received from processes
7297 !> \param[in] comm Message passing environment identifier
7298 !> \par Data length
7299 !> Data can have different lengths
7300 !> \par Offsets
7301 !> Offsets start at 0
7302 !> \par MPI mapping
7303 !> mpi_gather
7304 ! **************************************************************************************************
7305  SUBROUTINE mp_gatherv_iv_src(sendbuf, recvbuf, recvcounts, displs, comm)
7306 
7307  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
7308  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
7309  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
7310  CLASS(mp_comm_type), INTENT(IN) :: comm
7311 
7312  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_iv_src'
7313 
7314  INTEGER :: handle
7315 #if defined(__parallel)
7316  INTEGER :: ierr, sendcount
7317 #endif
7318 
7319  CALL mp_timeset(routinen, handle)
7320 
7321 #if defined(__parallel)
7322  sendcount = SIZE(sendbuf)
7323  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer, &
7324  recvbuf, recvcounts, displs, mpi_integer, &
7325  comm%source, comm%handle, ierr)
7326  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
7327  CALL add_perf(perf_id=4, &
7328  count=1, &
7329  msg_size=sendcount*int_4_size)
7330 #else
7331  mark_used(recvcounts)
7332  mark_used(comm)
7333  recvbuf(1 + displs(1):) = sendbuf
7334 #endif
7335  CALL mp_timestop(handle)
7336  END SUBROUTINE mp_gatherv_iv_src
7337 
7338 ! **************************************************************************************************
7339 !> \brief Gathers data from all processes to one.
7340 !> \param[in] sendbuf Data to send to root
7341 !> \param[out] recvbuf Received data (on root)
7342 !> \param[in] recvcounts Sizes of data received from processes
7343 !> \param[in] displs Offsets of data received from processes
7344 !> \param[in] root Process which gathers the data
7345 !> \param[in] comm Message passing environment identifier
7346 !> \par Data length
7347 !> Data can have different lengths
7348 !> \par Offsets
7349 !> Offsets start at 0
7350 !> \par MPI mapping
7351 !> mpi_gather
7352 ! **************************************************************************************************
7353  SUBROUTINE mp_gatherv_im2(sendbuf, recvbuf, recvcounts, displs, root, comm)
7354 
7355  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
7356  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
7357  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
7358  INTEGER, INTENT(IN) :: root
7359  CLASS(mp_comm_type), INTENT(IN) :: comm
7360 
7361  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_im2'
7362 
7363  INTEGER :: handle
7364 #if defined(__parallel)
7365  INTEGER :: ierr, sendcount
7366 #endif
7367 
7368  CALL mp_timeset(routinen, handle)
7369 
7370 #if defined(__parallel)
7371  sendcount = SIZE(sendbuf)
7372  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer, &
7373  recvbuf, recvcounts, displs, mpi_integer, &
7374  root, comm%handle, ierr)
7375  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
7376  CALL add_perf(perf_id=4, &
7377  count=1, &
7378  msg_size=sendcount*int_4_size)
7379 #else
7380  mark_used(recvcounts)
7381  mark_used(root)
7382  mark_used(comm)
7383  recvbuf(:, 1 + displs(1):) = sendbuf
7384 #endif
7385  CALL mp_timestop(handle)
7386  END SUBROUTINE mp_gatherv_im2
7387 
7388 ! **************************************************************************************************
7389 !> \brief Gathers data from all processes to one.
7390 !> \param[in] sendbuf Data to send to root
7391 !> \param[out] recvbuf Received data (on root)
7392 !> \param[in] recvcounts Sizes of data received from processes
7393 !> \param[in] displs Offsets of data received from processes
7394 !> \param[in] comm Message passing environment identifier
7395 !> \par Data length
7396 !> Data can have different lengths
7397 !> \par Offsets
7398 !> Offsets start at 0
7399 !> \par MPI mapping
7400 !> mpi_gather
7401 ! **************************************************************************************************
7402  SUBROUTINE mp_gatherv_im2_src(sendbuf, recvbuf, recvcounts, displs, comm)
7403 
7404  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
7405  INTEGER(KIND=int_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
7406  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
7407  CLASS(mp_comm_type), INTENT(IN) :: comm
7408 
7409  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_im2_src'
7410 
7411  INTEGER :: handle
7412 #if defined(__parallel)
7413  INTEGER :: ierr, sendcount
7414 #endif
7415 
7416  CALL mp_timeset(routinen, handle)
7417 
7418 #if defined(__parallel)
7419  sendcount = SIZE(sendbuf)
7420  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer, &
7421  recvbuf, recvcounts, displs, mpi_integer, &
7422  comm%source, comm%handle, ierr)
7423  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
7424  CALL add_perf(perf_id=4, &
7425  count=1, &
7426  msg_size=sendcount*int_4_size)
7427 #else
7428  mark_used(recvcounts)
7429  mark_used(comm)
7430  recvbuf(:, 1 + displs(1):) = sendbuf
7431 #endif
7432  CALL mp_timestop(handle)
7433  END SUBROUTINE mp_gatherv_im2_src
7434 
7435 ! **************************************************************************************************
7436 !> \brief Gathers data from all processes to one.
7437 !> \param[in] sendbuf Data to send to root
7438 !> \param[out] recvbuf Received data (on root)
7439 !> \param[in] recvcounts Sizes of data received from processes
7440 !> \param[in] displs Offsets of data received from processes
7441 !> \param[in] root Process which gathers the data
7442 !> \param[in] comm Message passing environment identifier
7443 !> \par Data length
7444 !> Data can have different lengths
7445 !> \par Offsets
7446 !> Offsets start at 0
7447 !> \par MPI mapping
7448 !> mpi_gather
7449 ! **************************************************************************************************
7450  SUBROUTINE mp_igatherv_iv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
7451  INTEGER(KIND=int_4), DIMENSION(:), INTENT(IN) :: sendbuf
7452  INTEGER(KIND=int_4), DIMENSION(:), INTENT(OUT) :: recvbuf
7453  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
7454  INTEGER, INTENT(IN) :: sendcount, root
7455  CLASS(mp_comm_type), INTENT(IN) :: comm
7456  TYPE(mp_request_type), INTENT(OUT) :: request
7457 
7458  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_iv'
7459 
7460  INTEGER :: handle
7461 #if defined(__parallel)
7462  INTEGER :: ierr
7463 #endif
7464 
7465  CALL mp_timeset(routinen, handle)
7466 
7467 #if defined(__parallel)
7468 #if !defined(__GNUC__) || __GNUC__ >= 9
7469  cpassert(is_contiguous(sendbuf))
7470  cpassert(is_contiguous(recvbuf))
7471  cpassert(is_contiguous(recvcounts))
7472  cpassert(is_contiguous(displs))
7473 #endif
7474  CALL mpi_igatherv(sendbuf, sendcount, mpi_integer, &
7475  recvbuf, recvcounts, displs, mpi_integer, &
7476  root, comm%handle, request%handle, ierr)
7477  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
7478  CALL add_perf(perf_id=24, &
7479  count=1, &
7480  msg_size=sendcount*int_4_size)
7481 #else
7482  mark_used(sendcount)
7483  mark_used(recvcounts)
7484  mark_used(root)
7485  mark_used(comm)
7486  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
7487  request = mp_request_null
7488 #endif
7489  CALL mp_timestop(handle)
7490  END SUBROUTINE mp_igatherv_iv
7491 
7492 ! **************************************************************************************************
7493 !> \brief Gathers a datum from all processes and all processes receive the
7494 !> same data
7495 !> \param[in] msgout Datum to send
7496 !> \param[out] msgin Received data
7497 !> \param[in] comm Message passing environment identifier
7498 !> \par Data size
7499 !> All processes send equal-sized data
7500 !> \par MPI mapping
7501 !> mpi_allgather
7502 ! **************************************************************************************************
7503  SUBROUTINE mp_allgather_i (msgout, msgin, comm)
7504  INTEGER(KIND=int_4), INTENT(IN) :: msgout
7505  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:)
7506  CLASS(mp_comm_type), INTENT(IN) :: comm
7507 
7508  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i'
7509 
7510  INTEGER :: handle
7511 #if defined(__parallel)
7512  INTEGER :: ierr, rcount, scount
7513 #endif
7514 
7515  CALL mp_timeset(routinen, handle)
7516 
7517 #if defined(__parallel)
7518  scount = 1
7519  rcount = 1
7520  CALL mpi_allgather(msgout, scount, mpi_integer, &
7521  msgin, rcount, mpi_integer, &
7522  comm%handle, ierr)
7523  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7524 #else
7525  mark_used(comm)
7526  msgin = msgout
7527 #endif
7528  CALL mp_timestop(handle)
7529  END SUBROUTINE mp_allgather_i
7530 
7531 ! **************************************************************************************************
7532 !> \brief Gathers a datum from all processes and all processes receive the
7533 !> same data
7534 !> \param[in] msgout Datum to send
7535 !> \param[out] msgin Received data
7536 !> \param[in] comm Message passing environment identifier
7537 !> \par Data size
7538 !> All processes send equal-sized data
7539 !> \par MPI mapping
7540 !> mpi_allgather
7541 ! **************************************************************************************************
7542  SUBROUTINE mp_allgather_i2(msgout, msgin, comm)
7543  INTEGER(KIND=int_4), INTENT(IN) :: msgout
7544  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
7545  CLASS(mp_comm_type), INTENT(IN) :: comm
7546 
7547  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i2'
7548 
7549  INTEGER :: handle
7550 #if defined(__parallel)
7551  INTEGER :: ierr, rcount, scount
7552 #endif
7553 
7554  CALL mp_timeset(routinen, handle)
7555 
7556 #if defined(__parallel)
7557  scount = 1
7558  rcount = 1
7559  CALL mpi_allgather(msgout, scount, mpi_integer, &
7560  msgin, rcount, mpi_integer, &
7561  comm%handle, ierr)
7562  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7563 #else
7564  mark_used(comm)
7565  msgin = msgout
7566 #endif
7567  CALL mp_timestop(handle)
7568  END SUBROUTINE mp_allgather_i2
7569 
7570 ! **************************************************************************************************
7571 !> \brief Gathers a datum from all processes and all processes receive the
7572 !> same data
7573 !> \param[in] msgout Datum to send
7574 !> \param[out] msgin Received data
7575 !> \param[in] comm Message passing environment identifier
7576 !> \par Data size
7577 !> All processes send equal-sized data
7578 !> \par MPI mapping
7579 !> mpi_allgather
7580 ! **************************************************************************************************
7581  SUBROUTINE mp_iallgather_i (msgout, msgin, comm, request)
7582  INTEGER(KIND=int_4), INTENT(IN) :: msgout
7583  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:)
7584  CLASS(mp_comm_type), INTENT(IN) :: comm
7585  TYPE(mp_request_type), INTENT(OUT) :: request
7586 
7587  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i'
7588 
7589  INTEGER :: handle
7590 #if defined(__parallel)
7591  INTEGER :: ierr, rcount, scount
7592 #endif
7593 
7594  CALL mp_timeset(routinen, handle)
7595 
7596 #if defined(__parallel)
7597 #if !defined(__GNUC__) || __GNUC__ >= 9
7598  cpassert(is_contiguous(msgin))
7599 #endif
7600  scount = 1
7601  rcount = 1
7602  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7603  msgin, rcount, mpi_integer, &
7604  comm%handle, request%handle, ierr)
7605  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7606 #else
7607  mark_used(comm)
7608  msgin = msgout
7609  request = mp_request_null
7610 #endif
7611  CALL mp_timestop(handle)
7612  END SUBROUTINE mp_iallgather_i
7613 
7614 ! **************************************************************************************************
7615 !> \brief Gathers vector data from all processes and all processes receive the
7616 !> same data
7617 !> \param[in] msgout Rank-1 data to send
7618 !> \param[out] msgin Received data
7619 !> \param[in] comm Message passing environment identifier
7620 !> \par Data size
7621 !> All processes send equal-sized data
7622 !> \par Ranks
7623 !> The last rank counts the processes
7624 !> \par MPI mapping
7625 !> mpi_allgather
7626 ! **************************************************************************************************
7627  SUBROUTINE mp_allgather_i12(msgout, msgin, comm)
7628  INTEGER(KIND=int_4), INTENT(IN), CONTIGUOUS :: msgout(:)
7629  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
7630  CLASS(mp_comm_type), INTENT(IN) :: comm
7631 
7632  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i12'
7633 
7634  INTEGER :: handle
7635 #if defined(__parallel)
7636  INTEGER :: ierr, rcount, scount
7637 #endif
7638 
7639  CALL mp_timeset(routinen, handle)
7640 
7641 #if defined(__parallel)
7642  scount = SIZE(msgout(:))
7643  rcount = scount
7644  CALL mpi_allgather(msgout, scount, mpi_integer, &
7645  msgin, rcount, mpi_integer, &
7646  comm%handle, ierr)
7647  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7648 #else
7649  mark_used(comm)
7650  msgin(:, 1) = msgout(:)
7651 #endif
7652  CALL mp_timestop(handle)
7653  END SUBROUTINE mp_allgather_i12
7654 
7655 ! **************************************************************************************************
7656 !> \brief Gathers matrix data from all processes and all processes receive the
7657 !> same data
7658 !> \param[in] msgout Rank-2 data to send
7659 !> \param msgin ...
7660 !> \param comm ...
7661 !> \note see mp_allgather_i12
7662 ! **************************************************************************************************
7663  SUBROUTINE mp_allgather_i23(msgout, msgin, comm)
7664  INTEGER(KIND=int_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
7665  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
7666  CLASS(mp_comm_type), INTENT(IN) :: comm
7667 
7668  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i23'
7669 
7670  INTEGER :: handle
7671 #if defined(__parallel)
7672  INTEGER :: ierr, rcount, scount
7673 #endif
7674 
7675  CALL mp_timeset(routinen, handle)
7676 
7677 #if defined(__parallel)
7678  scount = SIZE(msgout(:, :))
7679  rcount = scount
7680  CALL mpi_allgather(msgout, scount, mpi_integer, &
7681  msgin, rcount, mpi_integer, &
7682  comm%handle, ierr)
7683  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7684 #else
7685  mark_used(comm)
7686  msgin(:, :, 1) = msgout(:, :)
7687 #endif
7688  CALL mp_timestop(handle)
7689  END SUBROUTINE mp_allgather_i23
7690 
7691 ! **************************************************************************************************
7692 !> \brief Gathers rank-3 data from all processes and all processes receive the
7693 !> same data
7694 !> \param[in] msgout Rank-3 data to send
7695 !> \param msgin ...
7696 !> \param comm ...
7697 !> \note see mp_allgather_i12
7698 ! **************************************************************************************************
7699  SUBROUTINE mp_allgather_i34(msgout, msgin, comm)
7700  INTEGER(KIND=int_4), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
7701  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
7702  CLASS(mp_comm_type), INTENT(IN) :: comm
7703 
7704  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i34'
7705 
7706  INTEGER :: handle
7707 #if defined(__parallel)
7708  INTEGER :: ierr, rcount, scount
7709 #endif
7710 
7711  CALL mp_timeset(routinen, handle)
7712 
7713 #if defined(__parallel)
7714  scount = SIZE(msgout(:, :, :))
7715  rcount = scount
7716  CALL mpi_allgather(msgout, scount, mpi_integer, &
7717  msgin, rcount, mpi_integer, &
7718  comm%handle, ierr)
7719  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7720 #else
7721  mark_used(comm)
7722  msgin(:, :, :, 1) = msgout(:, :, :)
7723 #endif
7724  CALL mp_timestop(handle)
7725  END SUBROUTINE mp_allgather_i34
7726 
7727 ! **************************************************************************************************
7728 !> \brief Gathers rank-2 data from all processes and all processes receive the
7729 !> same data
7730 !> \param[in] msgout Rank-2 data to send
7731 !> \param msgin ...
7732 !> \param comm ...
7733 !> \note see mp_allgather_i12
7734 ! **************************************************************************************************
7735  SUBROUTINE mp_allgather_i22(msgout, msgin, comm)
7736  INTEGER(KIND=int_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
7737  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
7738  CLASS(mp_comm_type), INTENT(IN) :: comm
7739 
7740  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_i22'
7741 
7742  INTEGER :: handle
7743 #if defined(__parallel)
7744  INTEGER :: ierr, rcount, scount
7745 #endif
7746 
7747  CALL mp_timeset(routinen, handle)
7748 
7749 #if defined(__parallel)
7750  scount = SIZE(msgout(:, :))
7751  rcount = scount
7752  CALL mpi_allgather(msgout, scount, mpi_integer, &
7753  msgin, rcount, mpi_integer, &
7754  comm%handle, ierr)
7755  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
7756 #else
7757  mark_used(comm)
7758  msgin(:, :) = msgout(:, :)
7759 #endif
7760  CALL mp_timestop(handle)
7761  END SUBROUTINE mp_allgather_i22
7762 
7763 ! **************************************************************************************************
7764 !> \brief Gathers rank-1 data from all processes and all processes receive the
7765 !> same data
7766 !> \param[in] msgout Rank-1 data to send
7767 !> \param msgin ...
7768 !> \param comm ...
7769 !> \param request ...
7770 !> \note see mp_allgather_i11
7771 ! **************************************************************************************************
7772  SUBROUTINE mp_iallgather_i11(msgout, msgin, comm, request)
7773  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:)
7774  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:)
7775  CLASS(mp_comm_type), INTENT(IN) :: comm
7776  TYPE(mp_request_type), INTENT(OUT) :: request
7777 
7778  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i11'
7779 
7780  INTEGER :: handle
7781 #if defined(__parallel)
7782  INTEGER :: ierr, rcount, scount
7783 #endif
7784 
7785  CALL mp_timeset(routinen, handle)
7786 
7787 #if defined(__parallel)
7788 #if !defined(__GNUC__) || __GNUC__ >= 9
7789  cpassert(is_contiguous(msgout))
7790  cpassert(is_contiguous(msgin))
7791 #endif
7792  scount = SIZE(msgout(:))
7793  rcount = scount
7794  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7795  msgin, rcount, mpi_integer, &
7796  comm%handle, request%handle, ierr)
7797  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
7798 #else
7799  mark_used(comm)
7800  msgin = msgout
7801  request = mp_request_null
7802 #endif
7803  CALL mp_timestop(handle)
7804  END SUBROUTINE mp_iallgather_i11
7805 
7806 ! **************************************************************************************************
7807 !> \brief Gathers rank-2 data from all processes and all processes receive the
7808 !> same data
7809 !> \param[in] msgout Rank-2 data to send
7810 !> \param msgin ...
7811 !> \param comm ...
7812 !> \param request ...
7813 !> \note see mp_allgather_i12
7814 ! **************************************************************************************************
7815  SUBROUTINE mp_iallgather_i13(msgout, msgin, comm, request)
7816  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:)
7817  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:, :, :)
7818  CLASS(mp_comm_type), INTENT(IN) :: comm
7819  TYPE(mp_request_type), INTENT(OUT) :: request
7820 
7821  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i13'
7822 
7823  INTEGER :: handle
7824 #if defined(__parallel)
7825  INTEGER :: ierr, rcount, scount
7826 #endif
7827 
7828  CALL mp_timeset(routinen, handle)
7829 
7830 #if defined(__parallel)
7831 #if !defined(__GNUC__) || __GNUC__ >= 9
7832  cpassert(is_contiguous(msgout))
7833  cpassert(is_contiguous(msgin))
7834 #endif
7835 
7836  scount = SIZE(msgout(:))
7837  rcount = scount
7838  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7839  msgin, rcount, mpi_integer, &
7840  comm%handle, request%handle, ierr)
7841  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
7842 #else
7843  mark_used(comm)
7844  msgin(:, 1, 1) = msgout(:)
7845  request = mp_request_null
7846 #endif
7847  CALL mp_timestop(handle)
7848  END SUBROUTINE mp_iallgather_i13
7849 
7850 ! **************************************************************************************************
7851 !> \brief Gathers rank-2 data from all processes and all processes receive the
7852 !> same data
7853 !> \param[in] msgout Rank-2 data to send
7854 !> \param msgin ...
7855 !> \param comm ...
7856 !> \param request ...
7857 !> \note see mp_allgather_i12
7858 ! **************************************************************************************************
7859  SUBROUTINE mp_iallgather_i22(msgout, msgin, comm, request)
7860  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:, :)
7861  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:, :)
7862  CLASS(mp_comm_type), INTENT(IN) :: comm
7863  TYPE(mp_request_type), INTENT(OUT) :: request
7864 
7865  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i22'
7866 
7867  INTEGER :: handle
7868 #if defined(__parallel)
7869  INTEGER :: ierr, rcount, scount
7870 #endif
7871 
7872  CALL mp_timeset(routinen, handle)
7873 
7874 #if defined(__parallel)
7875 #if !defined(__GNUC__) || __GNUC__ >= 9
7876  cpassert(is_contiguous(msgout))
7877  cpassert(is_contiguous(msgin))
7878 #endif
7879 
7880  scount = SIZE(msgout(:, :))
7881  rcount = scount
7882  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7883  msgin, rcount, mpi_integer, &
7884  comm%handle, request%handle, ierr)
7885  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
7886 #else
7887  mark_used(comm)
7888  msgin(:, :) = msgout(:, :)
7889  request = mp_request_null
7890 #endif
7891  CALL mp_timestop(handle)
7892  END SUBROUTINE mp_iallgather_i22
7893 
7894 ! **************************************************************************************************
7895 !> \brief Gathers rank-2 data from all processes and all processes receive the
7896 !> same data
7897 !> \param[in] msgout Rank-2 data to send
7898 !> \param msgin ...
7899 !> \param comm ...
7900 !> \param request ...
7901 !> \note see mp_allgather_i12
7902 ! **************************************************************************************************
7903  SUBROUTINE mp_iallgather_i24(msgout, msgin, comm, request)
7904  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:, :)
7905  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:, :, :, :)
7906  CLASS(mp_comm_type), INTENT(IN) :: comm
7907  TYPE(mp_request_type), INTENT(OUT) :: request
7908 
7909  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i24'
7910 
7911  INTEGER :: handle
7912 #if defined(__parallel)
7913  INTEGER :: ierr, rcount, scount
7914 #endif
7915 
7916  CALL mp_timeset(routinen, handle)
7917 
7918 #if defined(__parallel)
7919 #if !defined(__GNUC__) || __GNUC__ >= 9
7920  cpassert(is_contiguous(msgout))
7921  cpassert(is_contiguous(msgin))
7922 #endif
7923 
7924  scount = SIZE(msgout(:, :))
7925  rcount = scount
7926  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7927  msgin, rcount, mpi_integer, &
7928  comm%handle, request%handle, ierr)
7929  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
7930 #else
7931  mark_used(comm)
7932  msgin(:, :, 1, 1) = msgout(:, :)
7933  request = mp_request_null
7934 #endif
7935  CALL mp_timestop(handle)
7936  END SUBROUTINE mp_iallgather_i24
7937 
7938 ! **************************************************************************************************
7939 !> \brief Gathers rank-3 data from all processes and all processes receive the
7940 !> same data
7941 !> \param[in] msgout Rank-3 data to send
7942 !> \param msgin ...
7943 !> \param comm ...
7944 !> \param request ...
7945 !> \note see mp_allgather_i12
7946 ! **************************************************************************************************
7947  SUBROUTINE mp_iallgather_i33(msgout, msgin, comm, request)
7948  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:, :, :)
7949  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:, :, :)
7950  CLASS(mp_comm_type), INTENT(IN) :: comm
7951  TYPE(mp_request_type), INTENT(OUT) :: request
7952 
7953  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_i33'
7954 
7955  INTEGER :: handle
7956 #if defined(__parallel)
7957  INTEGER :: ierr, rcount, scount
7958 #endif
7959 
7960  CALL mp_timeset(routinen, handle)
7961 
7962 #if defined(__parallel)
7963 #if !defined(__GNUC__) || __GNUC__ >= 9
7964  cpassert(is_contiguous(msgout))
7965  cpassert(is_contiguous(msgin))
7966 #endif
7967 
7968  scount = SIZE(msgout(:, :, :))
7969  rcount = scount
7970  CALL mpi_iallgather(msgout, scount, mpi_integer, &
7971  msgin, rcount, mpi_integer, &
7972  comm%handle, request%handle, ierr)
7973  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
7974 #else
7975  mark_used(comm)
7976  msgin(:, :, :) = msgout(:, :, :)
7977  request = mp_request_null
7978 #endif
7979  CALL mp_timestop(handle)
7980  END SUBROUTINE mp_iallgather_i33
7981 
7982 ! **************************************************************************************************
7983 !> \brief Gathers vector data from all processes and all processes receive the
7984 !> same data
7985 !> \param[in] msgout Rank-1 data to send
7986 !> \param[out] msgin Received data
7987 !> \param[in] rcount Size of sent data for every process
7988 !> \param[in] rdispl Offset of sent data for every process
7989 !> \param[in] comm Message passing environment identifier
7990 !> \par Data size
7991 !> Processes can send different-sized data
7992 !> \par Ranks
7993 !> The last rank counts the processes
7994 !> \par Offsets
7995 !> Offsets are from 0
7996 !> \par MPI mapping
7997 !> mpi_allgather
7998 ! **************************************************************************************************
7999  SUBROUTINE mp_allgatherv_iv(msgout, msgin, rcount, rdispl, comm)
8000  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
8001  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
8002  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
8003  CLASS(mp_comm_type), INTENT(IN) :: comm
8004 
8005  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_iv'
8006 
8007  INTEGER :: handle
8008 #if defined(__parallel)
8009  INTEGER :: ierr, scount
8010 #endif
8011 
8012  CALL mp_timeset(routinen, handle)
8013 
8014 #if defined(__parallel)
8015  scount = SIZE(msgout)
8016  CALL mpi_allgatherv(msgout, scount, mpi_integer, msgin, rcount, &
8017  rdispl, mpi_integer, comm%handle, ierr)
8018  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
8019 #else
8020  mark_used(rcount)
8021  mark_used(rdispl)
8022  mark_used(comm)
8023  msgin = msgout
8024 #endif
8025  CALL mp_timestop(handle)
8026  END SUBROUTINE mp_allgatherv_iv
8027 
8028 ! **************************************************************************************************
8029 !> \brief Gathers vector data from all processes and all processes receive the
8030 !> same data
8031 !> \param[in] msgout Rank-1 data to send
8032 !> \param[out] msgin Received data
8033 !> \param[in] rcount Size of sent data for every process
8034 !> \param[in] rdispl Offset of sent data for every process
8035 !> \param[in] comm Message passing environment identifier
8036 !> \par Data size
8037 !> Processes can send different-sized data
8038 !> \par Ranks
8039 !> The last rank counts the processes
8040 !> \par Offsets
8041 !> Offsets are from 0
8042 !> \par MPI mapping
8043 !> mpi_allgather
8044 ! **************************************************************************************************
8045  SUBROUTINE mp_allgatherv_im2(msgout, msgin, rcount, rdispl, comm)
8046  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
8047  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
8048  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
8049  CLASS(mp_comm_type), INTENT(IN) :: comm
8050 
8051  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_iv'
8052 
8053  INTEGER :: handle
8054 #if defined(__parallel)
8055  INTEGER :: ierr, scount
8056 #endif
8057 
8058  CALL mp_timeset(routinen, handle)
8059 
8060 #if defined(__parallel)
8061  scount = SIZE(msgout)
8062  CALL mpi_allgatherv(msgout, scount, mpi_integer, msgin, rcount, &
8063  rdispl, mpi_integer, comm%handle, ierr)
8064  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
8065 #else
8066  mark_used(rcount)
8067  mark_used(rdispl)
8068  mark_used(comm)
8069  msgin = msgout
8070 #endif
8071  CALL mp_timestop(handle)
8072  END SUBROUTINE mp_allgatherv_im2
8073 
8074 ! **************************************************************************************************
8075 !> \brief Gathers vector data from all processes and all processes receive the
8076 !> same data
8077 !> \param[in] msgout Rank-1 data to send
8078 !> \param[out] msgin Received data
8079 !> \param[in] rcount Size of sent data for every process
8080 !> \param[in] rdispl Offset of sent data for every process
8081 !> \param[in] comm Message passing environment identifier
8082 !> \par Data size
8083 !> Processes can send different-sized data
8084 !> \par Ranks
8085 !> The last rank counts the processes
8086 !> \par Offsets
8087 !> Offsets are from 0
8088 !> \par MPI mapping
8089 !> mpi_allgather
8090 ! **************************************************************************************************
8091  SUBROUTINE mp_iallgatherv_iv(msgout, msgin, rcount, rdispl, comm, request)
8092  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:)
8093  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:)
8094  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
8095  CLASS(mp_comm_type), INTENT(IN) :: comm
8096  TYPE(mp_request_type), INTENT(OUT) :: request
8097 
8098  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_iv'
8099 
8100  INTEGER :: handle
8101 #if defined(__parallel)
8102  INTEGER :: ierr, scount, rsize
8103 #endif
8104 
8105  CALL mp_timeset(routinen, handle)
8106 
8107 #if defined(__parallel)
8108 #if !defined(__GNUC__) || __GNUC__ >= 9
8109  cpassert(is_contiguous(msgout))
8110  cpassert(is_contiguous(msgin))
8111  cpassert(is_contiguous(rcount))
8112  cpassert(is_contiguous(rdispl))
8113 #endif
8114 
8115  scount = SIZE(msgout)
8116  rsize = SIZE(rcount)
8117  CALL mp_iallgatherv_iv_internal(msgout, scount, msgin, rsize, rcount, &
8118  rdispl, comm, request, ierr)
8119  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
8120 #else
8121  mark_used(rcount)
8122  mark_used(rdispl)
8123  mark_used(comm)
8124  msgin = msgout
8125  request = mp_request_null
8126 #endif
8127  CALL mp_timestop(handle)
8128  END SUBROUTINE mp_iallgatherv_iv
8129 
8130 ! **************************************************************************************************
8131 !> \brief Gathers vector data from all processes and all processes receive the
8132 !> same data
8133 !> \param[in] msgout Rank-1 data to send
8134 !> \param[out] msgin Received data
8135 !> \param[in] rcount Size of sent data for every process
8136 !> \param[in] rdispl Offset of sent data for every process
8137 !> \param[in] comm Message passing environment identifier
8138 !> \par Data size
8139 !> Processes can send different-sized data
8140 !> \par Ranks
8141 !> The last rank counts the processes
8142 !> \par Offsets
8143 !> Offsets are from 0
8144 !> \par MPI mapping
8145 !> mpi_allgather
8146 ! **************************************************************************************************
8147  SUBROUTINE mp_iallgatherv_iv2(msgout, msgin, rcount, rdispl, comm, request)
8148  INTEGER(KIND=int_4), INTENT(IN) :: msgout(:)
8149  INTEGER(KIND=int_4), INTENT(OUT) :: msgin(:)
8150  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
8151  CLASS(mp_comm_type), INTENT(IN) :: comm
8152  TYPE(mp_request_type), INTENT(OUT) :: request
8153 
8154  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_iv2'
8155 
8156  INTEGER :: handle
8157 #if defined(__parallel)
8158  INTEGER :: ierr, scount, rsize
8159 #endif
8160 
8161  CALL mp_timeset(routinen, handle)
8162 
8163 #if defined(__parallel)
8164 #if !defined(__GNUC__) || __GNUC__ >= 9
8165  cpassert(is_contiguous(msgout))
8166  cpassert(is_contiguous(msgin))
8167  cpassert(is_contiguous(rcount))
8168  cpassert(is_contiguous(rdispl))
8169 #endif
8170 
8171  scount = SIZE(msgout)
8172  rsize = SIZE(rcount)
8173  CALL mp_iallgatherv_iv_internal(msgout, scount, msgin, rsize, rcount, &
8174  rdispl, comm, request, ierr)
8175  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
8176 #else
8177  mark_used(rcount)
8178  mark_used(rdispl)
8179  mark_used(comm)
8180  msgin = msgout
8181  request = mp_request_null
8182 #endif
8183  CALL mp_timestop(handle)
8184  END SUBROUTINE mp_iallgatherv_iv2
8185 
8186 ! **************************************************************************************************
8187 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
8188 !> the issue is with the rank of rcount and rdispl
8189 !> \param count ...
8190 !> \param array_of_requests ...
8191 !> \param array_of_statuses ...
8192 !> \param ierr ...
8193 !> \author Alfio Lazzaro
8194 ! **************************************************************************************************
8195 #if defined(__parallel)
8196  SUBROUTINE mp_iallgatherv_iv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
8197  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
8198  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
8199  INTEGER, INTENT(IN) :: rsize
8200  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
8201  CLASS(mp_comm_type), INTENT(IN) :: comm
8202  TYPE(mp_request_type), INTENT(OUT) :: request
8203  INTEGER, INTENT(INOUT) :: ierr
8204 
8205  CALL mpi_iallgatherv(msgout, scount, mpi_integer, msgin, rcount, &
8206  rdispl, mpi_integer, comm%handle, request%handle, ierr)
8207 
8208  END SUBROUTINE mp_iallgatherv_iv_internal
8209 #endif
8210 
8211 ! **************************************************************************************************
8212 !> \brief Sums a vector and partitions the result among processes
8213 !> \param[in] msgout Data to sum
8214 !> \param[out] msgin Received portion of summed data
8215 !> \param[in] rcount Partition sizes of the summed data for
8216 !> every process
8217 !> \param[in] comm Message passing environment identifier
8218 ! **************************************************************************************************
8219  SUBROUTINE mp_sum_scatter_iv(msgout, msgin, rcount, comm)
8220  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
8221  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
8222  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
8223  CLASS(mp_comm_type), INTENT(IN) :: comm
8224 
8225  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_iv'
8226 
8227  INTEGER :: handle
8228 #if defined(__parallel)
8229  INTEGER :: ierr
8230 #endif
8231 
8232  CALL mp_timeset(routinen, handle)
8233 
8234 #if defined(__parallel)
8235  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_integer, mpi_sum, &
8236  comm%handle, ierr)
8237  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
8238 
8239  CALL add_perf(perf_id=3, count=1, &
8240  msg_size=rcount(1)*2*int_4_size)
8241 #else
8242  mark_used(rcount)
8243  mark_used(comm)
8244  msgin = msgout(:, 1)
8245 #endif
8246  CALL mp_timestop(handle)
8247  END SUBROUTINE mp_sum_scatter_iv
8248 
8249 ! **************************************************************************************************
8250 !> \brief Sends and receives vector data
8251 !> \param[in] msgin Data to send
8252 !> \param[in] dest Process to send data to
8253 !> \param[out] msgout Received data
8254 !> \param[in] source Process from which to receive
8255 !> \param[in] comm Message passing environment identifier
8256 !> \param[in] tag Send and recv tag (default: 0)
8257 ! **************************************************************************************************
8258  SUBROUTINE mp_sendrecv_i (msgin, dest, msgout, source, comm, tag)
8259  INTEGER(KIND=int_4), INTENT(IN) :: msgin
8260  INTEGER, INTENT(IN) :: dest
8261  INTEGER(KIND=int_4), INTENT(OUT) :: msgout
8262  INTEGER, INTENT(IN) :: source
8263  CLASS(mp_comm_type), INTENT(IN) :: comm
8264  INTEGER, INTENT(IN), OPTIONAL :: tag
8265 
8266  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_i'
8267 
8268  INTEGER :: handle
8269 #if defined(__parallel)
8270  INTEGER :: ierr, msglen_in, msglen_out, &
8271  recv_tag, send_tag
8272 #endif
8273 
8274  CALL mp_timeset(routinen, handle)
8275 
8276 #if defined(__parallel)
8277  msglen_in = 1
8278  msglen_out = 1
8279  send_tag = 0 ! cannot think of something better here, this might be dangerous
8280  recv_tag = 0 ! cannot think of something better here, this might be dangerous
8281  IF (PRESENT(tag)) THEN
8282  send_tag = tag
8283  recv_tag = tag
8284  END IF
8285  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer, dest, send_tag, msgout, &
8286  msglen_out, mpi_integer, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
8287  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
8288  CALL add_perf(perf_id=7, count=1, &
8289  msg_size=(msglen_in + msglen_out)*int_4_size/2)
8290 #else
8291  mark_used(dest)
8292  mark_used(source)
8293  mark_used(comm)
8294  mark_used(tag)
8295  msgout = msgin
8296 #endif
8297  CALL mp_timestop(handle)
8298  END SUBROUTINE mp_sendrecv_i
8299 
8300 ! **************************************************************************************************
8301 !> \brief Sends and receives vector data
8302 !> \param[in] msgin Data to send
8303 !> \param[in] dest Process to send data to
8304 !> \param[out] msgout Received data
8305 !> \param[in] source Process from which to receive
8306 !> \param[in] comm Message passing environment identifier
8307 !> \param[in] tag Send and recv tag (default: 0)
8308 ! **************************************************************************************************
8309  SUBROUTINE mp_sendrecv_iv(msgin, dest, msgout, source, comm, tag)
8310  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgin(:)
8311  INTEGER, INTENT(IN) :: dest
8312  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgout(:)
8313  INTEGER, INTENT(IN) :: source
8314  CLASS(mp_comm_type), INTENT(IN) :: comm
8315  INTEGER, INTENT(IN), OPTIONAL :: tag
8316 
8317  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_iv'
8318 
8319  INTEGER :: handle
8320 #if defined(__parallel)
8321  INTEGER :: ierr, msglen_in, msglen_out, &
8322  recv_tag, send_tag
8323 #endif
8324 
8325  CALL mp_timeset(routinen, handle)
8326 
8327 #if defined(__parallel)
8328  msglen_in = SIZE(msgin)
8329  msglen_out = SIZE(msgout)
8330  send_tag = 0 ! cannot think of something better here, this might be dangerous
8331  recv_tag = 0 ! cannot think of something better here, this might be dangerous
8332  IF (PRESENT(tag)) THEN
8333  send_tag = tag
8334  recv_tag = tag
8335  END IF
8336  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer, dest, send_tag, msgout, &
8337  msglen_out, mpi_integer, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
8338  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
8339  CALL add_perf(perf_id=7, count=1, &
8340  msg_size=(msglen_in + msglen_out)*int_4_size/2)
8341 #else
8342  mark_used(dest)
8343  mark_used(source)
8344  mark_used(comm)
8345  mark_used(tag)
8346  msgout = msgin
8347 #endif
8348  CALL mp_timestop(handle)
8349  END SUBROUTINE mp_sendrecv_iv
8350 
8351 ! **************************************************************************************************
8352 !> \brief Sends and receives matrix data
8353 !> \param msgin ...
8354 !> \param dest ...
8355 !> \param msgout ...
8356 !> \param source ...
8357 !> \param comm ...
8358 !> \param tag ...
8359 !> \note see mp_sendrecv_iv
8360 ! **************************************************************************************************
8361  SUBROUTINE mp_sendrecv_im2(msgin, dest, msgout, source, comm, tag)
8362  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
8363  INTEGER, INTENT(IN) :: dest
8364  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
8365  INTEGER, INTENT(IN) :: source
8366  CLASS(mp_comm_type), INTENT(IN) :: comm
8367  INTEGER, INTENT(IN), OPTIONAL :: tag
8368 
8369  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_im2'
8370 
8371  INTEGER :: handle
8372 #if defined(__parallel)
8373  INTEGER :: ierr, msglen_in, msglen_out, &
8374  recv_tag, send_tag
8375 #endif
8376 
8377  CALL mp_timeset(routinen, handle)
8378 
8379 #if defined(__parallel)
8380  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
8381  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
8382  send_tag = 0 ! cannot think of something better here, this might be dangerous
8383  recv_tag = 0 ! cannot think of something better here, this might be dangerous
8384  IF (PRESENT(tag)) THEN
8385  send_tag = tag
8386  recv_tag = tag
8387  END IF
8388  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer, dest, send_tag, msgout, &
8389  msglen_out, mpi_integer, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
8390  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
8391  CALL add_perf(perf_id=7, count=1, &
8392  msg_size=(msglen_in + msglen_out)*int_4_size/2)
8393 #else
8394  mark_used(dest)
8395  mark_used(source)
8396  mark_used(comm)
8397  mark_used(tag)
8398  msgout = msgin
8399 #endif
8400  CALL mp_timestop(handle)
8401  END SUBROUTINE mp_sendrecv_im2
8402 
8403 ! **************************************************************************************************
8404 !> \brief Sends and receives rank-3 data
8405 !> \param msgin ...
8406 !> \param dest ...
8407 !> \param msgout ...
8408 !> \param source ...
8409 !> \param comm ...
8410 !> \note see mp_sendrecv_iv
8411 ! **************************************************************************************************
8412  SUBROUTINE mp_sendrecv_im3(msgin, dest, msgout, source, comm, tag)
8413  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
8414  INTEGER, INTENT(IN) :: dest
8415  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
8416  INTEGER, INTENT(IN) :: source
8417  CLASS(mp_comm_type), INTENT(IN) :: comm
8418  INTEGER, INTENT(IN), OPTIONAL :: tag
8419 
8420  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_im3'
8421 
8422  INTEGER :: handle
8423 #if defined(__parallel)
8424  INTEGER :: ierr, msglen_in, msglen_out, &
8425  recv_tag, send_tag
8426 #endif
8427 
8428  CALL mp_timeset(routinen, handle)
8429 
8430 #if defined(__parallel)
8431  msglen_in = SIZE(msgin)
8432  msglen_out = SIZE(msgout)
8433  send_tag = 0 ! cannot think of something better here, this might be dangerous
8434  recv_tag = 0 ! cannot think of something better here, this might be dangerous
8435  IF (PRESENT(tag)) THEN
8436  send_tag = tag
8437  recv_tag = tag
8438  END IF
8439  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer, dest, send_tag, msgout, &
8440  msglen_out, mpi_integer, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
8441  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
8442  CALL add_perf(perf_id=7, count=1, &
8443  msg_size=(msglen_in + msglen_out)*int_4_size/2)
8444 #else
8445  mark_used(dest)
8446  mark_used(source)
8447  mark_used(comm)
8448  mark_used(tag)
8449  msgout = msgin
8450 #endif
8451  CALL mp_timestop(handle)
8452  END SUBROUTINE mp_sendrecv_im3
8453 
8454 ! **************************************************************************************************
8455 !> \brief Sends and receives rank-4 data
8456 !> \param msgin ...
8457 !> \param dest ...
8458 !> \param msgout ...
8459 !> \param source ...
8460 !> \param comm ...
8461 !> \note see mp_sendrecv_iv
8462 ! **************************************************************************************************
8463  SUBROUTINE mp_sendrecv_im4(msgin, dest, msgout, source, comm, tag)
8464  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
8465  INTEGER, INTENT(IN) :: dest
8466  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
8467  INTEGER, INTENT(IN) :: source
8468  CLASS(mp_comm_type), INTENT(IN) :: comm
8469  INTEGER, INTENT(IN), OPTIONAL :: tag
8470 
8471  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_im4'
8472 
8473  INTEGER :: handle
8474 #if defined(__parallel)
8475  INTEGER :: ierr, msglen_in, msglen_out, &
8476  recv_tag, send_tag
8477 #endif
8478 
8479  CALL mp_timeset(routinen, handle)
8480 
8481 #if defined(__parallel)
8482  msglen_in = SIZE(msgin)
8483  msglen_out = SIZE(msgout)
8484  send_tag = 0 ! cannot think of something better here, this might be dangerous
8485  recv_tag = 0 ! cannot think of something better here, this might be dangerous
8486  IF (PRESENT(tag)) THEN
8487  send_tag = tag
8488  recv_tag = tag
8489  END IF
8490  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer, dest, send_tag, msgout, &
8491  msglen_out, mpi_integer, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
8492  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
8493  CALL add_perf(perf_id=7, count=1, &
8494  msg_size=(msglen_in + msglen_out)*int_4_size/2)
8495 #else
8496  mark_used(dest)
8497  mark_used(source)
8498  mark_used(comm)
8499  mark_used(tag)
8500  msgout = msgin
8501 #endif
8502  CALL mp_timestop(handle)
8503  END SUBROUTINE mp_sendrecv_im4
8504 
8505 ! **************************************************************************************************
8506 !> \brief Non-blocking send and receive of a scalar
8507 !> \param[in] msgin Scalar data to send
8508 !> \param[in] dest Which process to send to
8509 !> \param[out] msgout Receive data into this pointer
8510 !> \param[in] source Process to receive from
8511 !> \param[in] comm Message passing environment identifier
8512 !> \param[out] send_request Request handle for the send
8513 !> \param[out] recv_request Request handle for the receive
8514 !> \param[in] tag (optional) tag to differentiate requests
8515 !> \par Implementation
8516 !> Calls mpi_isend and mpi_irecv.
8517 !> \par History
8518 !> 02.2005 created [Alfio Lazzaro]
8519 ! **************************************************************************************************
8520  SUBROUTINE mp_isendrecv_i (msgin, dest, msgout, source, comm, send_request, &
8521  recv_request, tag)
8522  INTEGER(KIND=int_4), INTENT(IN) :: msgin
8523  INTEGER, INTENT(IN) :: dest
8524  INTEGER(KIND=int_4), INTENT(INOUT) :: msgout
8525  INTEGER, INTENT(IN) :: source
8526  CLASS(mp_comm_type), INTENT(IN) :: comm
8527  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
8528  INTEGER, INTENT(in), OPTIONAL :: tag
8529 
8530  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_i'
8531 
8532  INTEGER :: handle
8533 #if defined(__parallel)
8534  INTEGER :: ierr, my_tag
8535 #endif
8536 
8537  CALL mp_timeset(routinen, handle)
8538 
8539 #if defined(__parallel)
8540  my_tag = 0
8541  IF (PRESENT(tag)) my_tag = tag
8542 
8543  CALL mpi_irecv(msgout, 1, mpi_integer, source, my_tag, &
8544  comm%handle, recv_request%handle, ierr)
8545  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
8546 
8547  CALL mpi_isend(msgin, 1, mpi_integer, dest, my_tag, &
8548  comm%handle, send_request%handle, ierr)
8549  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8550 
8551  CALL add_perf(perf_id=8, count=1, msg_size=2*int_4_size)
8552 #else
8553  mark_used(dest)
8554  mark_used(source)
8555  mark_used(comm)
8556  mark_used(tag)
8557  send_request = mp_request_null
8558  recv_request = mp_request_null
8559  msgout = msgin
8560 #endif
8561  CALL mp_timestop(handle)
8562  END SUBROUTINE mp_isendrecv_i
8563 
8564 ! **************************************************************************************************
8565 !> \brief Non-blocking send and receive of a vector
8566 !> \param[in] msgin Vector data to send
8567 !> \param[in] dest Which process to send to
8568 !> \param[out] msgout Receive data into this pointer
8569 !> \param[in] source Process to receive from
8570 !> \param[in] comm Message passing environment identifier
8571 !> \param[out] send_request Request handle for the send
8572 !> \param[out] recv_request Request handle for the receive
8573 !> \param[in] tag (optional) tag to differentiate requests
8574 !> \par Implementation
8575 !> Calls mpi_isend and mpi_irecv.
8576 !> \par History
8577 !> 11.2004 created [Joost VandeVondele]
8578 !> \note
8579 !> arrays can be pointers or assumed shape, but they must be contiguous!
8580 ! **************************************************************************************************
8581  SUBROUTINE mp_isendrecv_iv(msgin, dest, msgout, source, comm, send_request, &
8582  recv_request, tag)
8583  INTEGER(KIND=int_4), DIMENSION(:), INTENT(IN) :: msgin
8584  INTEGER, INTENT(IN) :: dest
8585  INTEGER(KIND=int_4), DIMENSION(:), INTENT(INOUT) :: msgout
8586  INTEGER, INTENT(IN) :: source
8587  CLASS(mp_comm_type), INTENT(IN) :: comm
8588  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
8589  INTEGER, INTENT(in), OPTIONAL :: tag
8590 
8591  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_iv'
8592 
8593  INTEGER :: handle
8594 #if defined(__parallel)
8595  INTEGER :: ierr, msglen, my_tag
8596  INTEGER(KIND=int_4) :: foo
8597 #endif
8598 
8599  CALL mp_timeset(routinen, handle)
8600 
8601 #if defined(__parallel)
8602 #if !defined(__GNUC__) || __GNUC__ >= 9
8603  cpassert(is_contiguous(msgout))
8604  cpassert(is_contiguous(msgin))
8605 #endif
8606 
8607  my_tag = 0
8608  IF (PRESENT(tag)) my_tag = tag
8609 
8610  msglen = SIZE(msgout, 1)
8611  IF (msglen > 0) THEN
8612  CALL mpi_irecv(msgout(1), msglen, mpi_integer, source, my_tag, &
8613  comm%handle, recv_request%handle, ierr)
8614  ELSE
8615  CALL mpi_irecv(foo, msglen, mpi_integer, source, my_tag, &
8616  comm%handle, recv_request%handle, ierr)
8617  END IF
8618  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
8619 
8620  msglen = SIZE(msgin, 1)
8621  IF (msglen > 0) THEN
8622  CALL mpi_isend(msgin(1), msglen, mpi_integer, dest, my_tag, &
8623  comm%handle, send_request%handle, ierr)
8624  ELSE
8625  CALL mpi_isend(foo, msglen, mpi_integer, dest, my_tag, &
8626  comm%handle, send_request%handle, ierr)
8627  END IF
8628  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8629 
8630  msglen = (msglen + SIZE(msgout, 1) + 1)/2
8631  CALL add_perf(perf_id=8, count=1, msg_size=msglen*int_4_size)
8632 #else
8633  mark_used(dest)
8634  mark_used(source)
8635  mark_used(comm)
8636  mark_used(tag)
8637  send_request = mp_request_null
8638  recv_request = mp_request_null
8639  msgout = msgin
8640 #endif
8641  CALL mp_timestop(handle)
8642  END SUBROUTINE mp_isendrecv_iv
8643 
8644 ! **************************************************************************************************
8645 !> \brief Non-blocking send of vector data
8646 !> \param msgin ...
8647 !> \param dest ...
8648 !> \param comm ...
8649 !> \param request ...
8650 !> \param tag ...
8651 !> \par History
8652 !> 08.2003 created [f&j]
8653 !> \note see mp_isendrecv_iv
8654 !> \note
8655 !> arrays can be pointers or assumed shape, but they must be contiguous!
8656 ! **************************************************************************************************
8657  SUBROUTINE mp_isend_iv(msgin, dest, comm, request, tag)
8658  INTEGER(KIND=int_4), DIMENSION(:), INTENT(IN) :: msgin
8659  INTEGER, INTENT(IN) :: dest
8660  CLASS(mp_comm_type), INTENT(IN) :: comm
8661  TYPE(mp_request_type), INTENT(out) :: request
8662  INTEGER, INTENT(in), OPTIONAL :: tag
8663 
8664  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_iv'
8665 
8666  INTEGER :: handle, ierr
8667 #if defined(__parallel)
8668  INTEGER :: msglen, my_tag
8669  INTEGER(KIND=int_4) :: foo(1)
8670 #endif
8671 
8672  CALL mp_timeset(routinen, handle)
8673 
8674 #if defined(__parallel)
8675 #if !defined(__GNUC__) || __GNUC__ >= 9
8676  cpassert(is_contiguous(msgin))
8677 #endif
8678  my_tag = 0
8679  IF (PRESENT(tag)) my_tag = tag
8680 
8681  msglen = SIZE(msgin)
8682  IF (msglen > 0) THEN
8683  CALL mpi_isend(msgin(1), msglen, mpi_integer, dest, my_tag, &
8684  comm%handle, request%handle, ierr)
8685  ELSE
8686  CALL mpi_isend(foo, msglen, mpi_integer, dest, my_tag, &
8687  comm%handle, request%handle, ierr)
8688  END IF
8689  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8690 
8691  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_4_size)
8692 #else
8693  mark_used(msgin)
8694  mark_used(dest)
8695  mark_used(comm)
8696  mark_used(request)
8697  mark_used(tag)
8698  ierr = 1
8699  request = mp_request_null
8700  CALL mp_stop(ierr, "mp_isend called in non parallel case")
8701 #endif
8702  CALL mp_timestop(handle)
8703  END SUBROUTINE mp_isend_iv
8704 
8705 ! **************************************************************************************************
8706 !> \brief Non-blocking send of matrix data
8707 !> \param msgin ...
8708 !> \param dest ...
8709 !> \param comm ...
8710 !> \param request ...
8711 !> \param tag ...
8712 !> \par History
8713 !> 2009-11-25 [UB] Made type-generic for templates
8714 !> \author fawzi
8715 !> \note see mp_isendrecv_iv
8716 !> \note see mp_isend_iv
8717 !> \note
8718 !> arrays can be pointers or assumed shape, but they must be contiguous!
8719 ! **************************************************************************************************
8720  SUBROUTINE mp_isend_im2(msgin, dest, comm, request, tag)
8721  INTEGER(KIND=int_4), DIMENSION(:, :), INTENT(IN) :: msgin
8722  INTEGER, INTENT(IN) :: dest
8723  CLASS(mp_comm_type), INTENT(IN) :: comm
8724  TYPE(mp_request_type), INTENT(out) :: request
8725  INTEGER, INTENT(in), OPTIONAL :: tag
8726 
8727  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_im2'
8728 
8729  INTEGER :: handle, ierr
8730 #if defined(__parallel)
8731  INTEGER :: msglen, my_tag
8732  INTEGER(KIND=int_4) :: foo(1)
8733 #endif
8734 
8735  CALL mp_timeset(routinen, handle)
8736 
8737 #if defined(__parallel)
8738 #if !defined(__GNUC__) || __GNUC__ >= 9
8739  cpassert(is_contiguous(msgin))
8740 #endif
8741 
8742  my_tag = 0
8743  IF (PRESENT(tag)) my_tag = tag
8744 
8745  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
8746  IF (msglen > 0) THEN
8747  CALL mpi_isend(msgin(1, 1), msglen, mpi_integer, dest, my_tag, &
8748  comm%handle, request%handle, ierr)
8749  ELSE
8750  CALL mpi_isend(foo, msglen, mpi_integer, dest, my_tag, &
8751  comm%handle, request%handle, ierr)
8752  END IF
8753  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8754 
8755  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_4_size)
8756 #else
8757  mark_used(msgin)
8758  mark_used(dest)
8759  mark_used(comm)
8760  mark_used(request)
8761  mark_used(tag)
8762  ierr = 1
8763  request = mp_request_null
8764  CALL mp_stop(ierr, "mp_isend called in non parallel case")
8765 #endif
8766  CALL mp_timestop(handle)
8767  END SUBROUTINE mp_isend_im2
8768 
8769 ! **************************************************************************************************
8770 !> \brief Non-blocking send of rank-3 data
8771 !> \param msgin ...
8772 !> \param dest ...
8773 !> \param comm ...
8774 !> \param request ...
8775 !> \param tag ...
8776 !> \par History
8777 !> 9.2008 added _rm3 subroutine [Iain Bethune]
8778 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
8779 !> 2009-11-25 [UB] Made type-generic for templates
8780 !> \author fawzi
8781 !> \note see mp_isendrecv_iv
8782 !> \note see mp_isend_iv
8783 !> \note
8784 !> arrays can be pointers or assumed shape, but they must be contiguous!
8785 ! **************************************************************************************************
8786  SUBROUTINE mp_isend_im3(msgin, dest, comm, request, tag)
8787  INTEGER(KIND=int_4), DIMENSION(:, :, :), INTENT(IN) :: msgin
8788  INTEGER, INTENT(IN) :: dest
8789  CLASS(mp_comm_type), INTENT(IN) :: comm
8790  TYPE(mp_request_type), INTENT(out) :: request
8791  INTEGER, INTENT(in), OPTIONAL :: tag
8792 
8793  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_im3'
8794 
8795  INTEGER :: handle, ierr
8796 #if defined(__parallel)
8797  INTEGER :: msglen, my_tag
8798  INTEGER(KIND=int_4) :: foo(1)
8799 #endif
8800 
8801  CALL mp_timeset(routinen, handle)
8802 
8803 #if defined(__parallel)
8804 #if !defined(__GNUC__) || __GNUC__ >= 9
8805  cpassert(is_contiguous(msgin))
8806 #endif
8807 
8808  my_tag = 0
8809  IF (PRESENT(tag)) my_tag = tag
8810 
8811  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
8812  IF (msglen > 0) THEN
8813  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_integer, dest, my_tag, &
8814  comm%handle, request%handle, ierr)
8815  ELSE
8816  CALL mpi_isend(foo, msglen, mpi_integer, dest, my_tag, &
8817  comm%handle, request%handle, ierr)
8818  END IF
8819  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8820 
8821  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_4_size)
8822 #else
8823  mark_used(msgin)
8824  mark_used(dest)
8825  mark_used(comm)
8826  mark_used(request)
8827  mark_used(tag)
8828  ierr = 1
8829  request = mp_request_null
8830  CALL mp_stop(ierr, "mp_isend called in non parallel case")
8831 #endif
8832  CALL mp_timestop(handle)
8833  END SUBROUTINE mp_isend_im3
8834 
8835 ! **************************************************************************************************
8836 !> \brief Non-blocking send of rank-4 data
8837 !> \param msgin the input message
8838 !> \param dest the destination processor
8839 !> \param comm the communicator object
8840 !> \param request the communication request id
8841 !> \param tag the message tag
8842 !> \par History
8843 !> 2.2016 added _im4 subroutine [Nico Holmberg]
8844 !> \author fawzi
8845 !> \note see mp_isend_iv
8846 !> \note
8847 !> arrays can be pointers or assumed shape, but they must be contiguous!
8848 ! **************************************************************************************************
8849  SUBROUTINE mp_isend_im4(msgin, dest, comm, request, tag)
8850  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
8851  INTEGER, INTENT(IN) :: dest
8852  CLASS(mp_comm_type), INTENT(IN) :: comm
8853  TYPE(mp_request_type), INTENT(out) :: request
8854  INTEGER, INTENT(in), OPTIONAL :: tag
8855 
8856  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_im4'
8857 
8858  INTEGER :: handle, ierr
8859 #if defined(__parallel)
8860  INTEGER :: msglen, my_tag
8861  INTEGER(KIND=int_4) :: foo(1)
8862 #endif
8863 
8864  CALL mp_timeset(routinen, handle)
8865 
8866 #if defined(__parallel)
8867 #if !defined(__GNUC__) || __GNUC__ >= 9
8868  cpassert(is_contiguous(msgin))
8869 #endif
8870 
8871  my_tag = 0
8872  IF (PRESENT(tag)) my_tag = tag
8873 
8874  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
8875  IF (msglen > 0) THEN
8876  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_integer, dest, my_tag, &
8877  comm%handle, request%handle, ierr)
8878  ELSE
8879  CALL mpi_isend(foo, msglen, mpi_integer, dest, my_tag, &
8880  comm%handle, request%handle, ierr)
8881  END IF
8882  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
8883 
8884  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_4_size)
8885 #else
8886  mark_used(msgin)
8887  mark_used(dest)
8888  mark_used(comm)
8889  mark_used(request)
8890  mark_used(tag)
8891  ierr = 1
8892  request = mp_request_null
8893  CALL mp_stop(ierr, "mp_isend called in non parallel case")
8894 #endif
8895  CALL mp_timestop(handle)
8896  END SUBROUTINE mp_isend_im4
8897 
8898 ! **************************************************************************************************
8899 !> \brief Non-blocking receive of vector data
8900 !> \param msgout ...
8901 !> \param source ...
8902 !> \param comm ...
8903 !> \param request ...
8904 !> \param tag ...
8905 !> \par History
8906 !> 08.2003 created [f&j]
8907 !> 2009-11-25 [UB] Made type-generic for templates
8908 !> \note see mp_isendrecv_iv
8909 !> \note
8910 !> arrays can be pointers or assumed shape, but they must be contiguous!
8911 ! **************************************************************************************************
8912  SUBROUTINE mp_irecv_iv(msgout, source, comm, request, tag)
8913  INTEGER(KIND=int_4), DIMENSION(:), INTENT(INOUT) :: msgout
8914  INTEGER, INTENT(IN) :: source
8915  CLASS(mp_comm_type), INTENT(IN) :: comm
8916  TYPE(mp_request_type), INTENT(out) :: request
8917  INTEGER, INTENT(in), OPTIONAL :: tag
8918 
8919  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_iv'
8920 
8921  INTEGER :: handle
8922 #if defined(__parallel)
8923  INTEGER :: ierr, msglen, my_tag
8924  INTEGER(KIND=int_4) :: foo(1)
8925 #endif
8926 
8927  CALL mp_timeset(routinen, handle)
8928 
8929 #if defined(__parallel)
8930 #if !defined(__GNUC__) || __GNUC__ >= 9
8931  cpassert(is_contiguous(msgout))
8932 #endif
8933 
8934  my_tag = 0
8935  IF (PRESENT(tag)) my_tag = tag
8936 
8937  msglen = SIZE(msgout)
8938  IF (msglen > 0) THEN
8939  CALL mpi_irecv(msgout(1), msglen, mpi_integer, source, my_tag, &
8940  comm%handle, request%handle, ierr)
8941  ELSE
8942  CALL mpi_irecv(foo, msglen, mpi_integer, source, my_tag, &
8943  comm%handle, request%handle, ierr)
8944  END IF
8945  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
8946 
8947  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_4_size)
8948 #else
8949  cpabort("mp_irecv called in non parallel case")
8950  mark_used(msgout)
8951  mark_used(source)
8952  mark_used(comm)
8953  mark_used(tag)
8954  request = mp_request_null
8955 #endif
8956  CALL mp_timestop(handle)
8957  END SUBROUTINE mp_irecv_iv
8958 
8959 ! **************************************************************************************************
8960 !> \brief Non-blocking receive of matrix data
8961 !> \param msgout ...
8962 !> \param source ...
8963 !> \param comm ...
8964 !> \param request ...
8965 !> \param tag ...
8966 !> \par History
8967 !> 2009-11-25 [UB] Made type-generic for templates
8968 !> \author fawzi
8969 !> \note see mp_isendrecv_iv
8970 !> \note see mp_irecv_iv
8971 !> \note
8972 !> arrays can be pointers or assumed shape, but they must be contiguous!
8973 ! **************************************************************************************************
8974  SUBROUTINE mp_irecv_im2(msgout, source, comm, request, tag)
8975  INTEGER(KIND=int_4), DIMENSION(:, :), INTENT(INOUT) :: msgout
8976  INTEGER, INTENT(IN) :: source
8977  CLASS(mp_comm_type), INTENT(IN) :: comm
8978  TYPE(mp_request_type), INTENT(out) :: request
8979  INTEGER, INTENT(in), OPTIONAL :: tag
8980 
8981  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_im2'
8982 
8983  INTEGER :: handle
8984 #if defined(__parallel)
8985  INTEGER :: ierr, msglen, my_tag
8986  INTEGER(KIND=int_4) :: foo(1)
8987 #endif
8988 
8989  CALL mp_timeset(routinen, handle)
8990 
8991 #if defined(__parallel)
8992 #if !defined(__GNUC__) || __GNUC__ >= 9
8993  cpassert(is_contiguous(msgout))
8994 #endif
8995 
8996  my_tag = 0
8997  IF (PRESENT(tag)) my_tag = tag
8998 
8999  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
9000  IF (msglen > 0) THEN
9001  CALL mpi_irecv(msgout(1, 1), msglen, mpi_integer, source, my_tag, &
9002  comm%handle, request%handle, ierr)
9003  ELSE
9004  CALL mpi_irecv(foo, msglen, mpi_integer, source, my_tag, &
9005  comm%handle, request%handle, ierr)
9006  END IF
9007  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
9008 
9009  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_4_size)
9010 #else
9011  mark_used(msgout)
9012  mark_used(source)
9013  mark_used(comm)
9014  mark_used(tag)
9015  request = mp_request_null
9016  cpabort("mp_irecv called in non parallel case")
9017 #endif
9018  CALL mp_timestop(handle)
9019  END SUBROUTINE mp_irecv_im2
9020 
9021 ! **************************************************************************************************
9022 !> \brief Non-blocking send of rank-3 data
9023 !> \param msgout ...
9024 !> \param source ...
9025 !> \param comm ...
9026 !> \param request ...
9027 !> \param tag ...
9028 !> \par History
9029 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
9030 !> 2009-11-25 [UB] Made type-generic for templates
9031 !> \author fawzi
9032 !> \note see mp_isendrecv_iv
9033 !> \note see mp_irecv_iv
9034 !> \note
9035 !> arrays can be pointers or assumed shape, but they must be contiguous!
9036 ! **************************************************************************************************
9037  SUBROUTINE mp_irecv_im3(msgout, source, comm, request, tag)
9038  INTEGER(KIND=int_4), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
9039  INTEGER, INTENT(IN) :: source
9040  CLASS(mp_comm_type), INTENT(IN) :: comm
9041  TYPE(mp_request_type), INTENT(out) :: request
9042  INTEGER, INTENT(in), OPTIONAL :: tag
9043 
9044  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_im3'
9045 
9046  INTEGER :: handle
9047 #if defined(__parallel)
9048  INTEGER :: ierr, msglen, my_tag
9049  INTEGER(KIND=int_4) :: foo(1)
9050 #endif
9051 
9052  CALL mp_timeset(routinen, handle)
9053 
9054 #if defined(__parallel)
9055 #if !defined(__GNUC__) || __GNUC__ >= 9
9056  cpassert(is_contiguous(msgout))
9057 #endif
9058 
9059  my_tag = 0
9060  IF (PRESENT(tag)) my_tag = tag
9061 
9062  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
9063  IF (msglen > 0) THEN
9064  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_integer, source, my_tag, &
9065  comm%handle, request%handle, ierr)
9066  ELSE
9067  CALL mpi_irecv(foo, msglen, mpi_integer, source, my_tag, &
9068  comm%handle, request%handle, ierr)
9069  END IF
9070  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
9071 
9072  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_4_size)
9073 #else
9074  mark_used(msgout)
9075  mark_used(source)
9076  mark_used(comm)
9077  mark_used(tag)
9078  request = mp_request_null
9079  cpabort("mp_irecv called in non parallel case")
9080 #endif
9081  CALL mp_timestop(handle)
9082  END SUBROUTINE mp_irecv_im3
9083 
9084 ! **************************************************************************************************
9085 !> \brief Non-blocking receive of rank-4 data
9086 !> \param msgout the output message
9087 !> \param source the source processor
9088 !> \param comm the communicator object
9089 !> \param request the communication request id
9090 !> \param tag the message tag
9091 !> \par History
9092 !> 2.2016 added _im4 subroutine [Nico Holmberg]
9093 !> \author fawzi
9094 !> \note see mp_irecv_iv
9095 !> \note
9096 !> arrays can be pointers or assumed shape, but they must be contiguous!
9097 ! **************************************************************************************************
9098  SUBROUTINE mp_irecv_im4(msgout, source, comm, request, tag)
9099  INTEGER(KIND=int_4), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
9100  INTEGER, INTENT(IN) :: source
9101  CLASS(mp_comm_type), INTENT(IN) :: comm
9102  TYPE(mp_request_type), INTENT(out) :: request
9103  INTEGER, INTENT(in), OPTIONAL :: tag
9104 
9105  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_im4'
9106 
9107  INTEGER :: handle
9108 #if defined(__parallel)
9109  INTEGER :: ierr, msglen, my_tag
9110  INTEGER(KIND=int_4) :: foo(1)
9111 #endif
9112 
9113  CALL mp_timeset(routinen, handle)
9114 
9115 #if defined(__parallel)
9116 #if !defined(__GNUC__) || __GNUC__ >= 9
9117  cpassert(is_contiguous(msgout))
9118 #endif
9119 
9120  my_tag = 0
9121  IF (PRESENT(tag)) my_tag = tag
9122 
9123  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
9124  IF (msglen > 0) THEN
9125  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_integer, source, my_tag, &
9126  comm%handle, request%handle, ierr)
9127  ELSE
9128  CALL mpi_irecv(foo, msglen, mpi_integer, source, my_tag, &
9129  comm%handle, request%handle, ierr)
9130  END IF
9131  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
9132 
9133  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_4_size)
9134 #else
9135  mark_used(msgout)
9136  mark_used(source)
9137  mark_used(comm)
9138  mark_used(tag)
9139  request = mp_request_null
9140  cpabort("mp_irecv called in non parallel case")
9141 #endif
9142  CALL mp_timestop(handle)
9143  END SUBROUTINE mp_irecv_im4
9144 
9145 ! **************************************************************************************************
9146 !> \brief Window initialization function for vector data
9147 !> \param base ...
9148 !> \param comm ...
9149 !> \param win ...
9150 !> \par History
9151 !> 02.2015 created [Alfio Lazzaro]
9152 !> \note
9153 !> arrays can be pointers or assumed shape, but they must be contiguous!
9154 ! **************************************************************************************************
9155  SUBROUTINE mp_win_create_iv(base, comm, win)
9156  INTEGER(KIND=int_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
9157  TYPE(mp_comm_type), INTENT(IN) :: comm
9158  CLASS(mp_win_type), INTENT(INOUT) :: win
9159 
9160  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_iv'
9161 
9162  INTEGER :: handle
9163 #if defined(__parallel)
9164  INTEGER :: ierr
9165  INTEGER(kind=mpi_address_kind) :: len
9166  INTEGER(KIND=int_4) :: foo(1)
9167 #endif
9168 
9169  CALL mp_timeset(routinen, handle)
9170 
9171 #if defined(__parallel)
9172 
9173  len = SIZE(base)*int_4_size
9174  IF (len > 0) THEN
9175  CALL mpi_win_create(base(1), len, int_4_size, mpi_info_null, comm%handle, win%handle, ierr)
9176  ELSE
9177  CALL mpi_win_create(foo, len, int_4_size, mpi_info_null, comm%handle, win%handle, ierr)
9178  END IF
9179  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
9180 
9181  CALL add_perf(perf_id=20, count=1)
9182 #else
9183  mark_used(base)
9184  mark_used(comm)
9185  win%handle = mp_win_null_handle
9186 #endif
9187  CALL mp_timestop(handle)
9188  END SUBROUTINE mp_win_create_iv
9189 
9190 ! **************************************************************************************************
9191 !> \brief Single-sided get function for vector data
9192 !> \param base ...
9193 !> \param comm ...
9194 !> \param win ...
9195 !> \par History
9196 !> 02.2015 created [Alfio Lazzaro]
9197 !> \note
9198 !> arrays can be pointers or assumed shape, but they must be contiguous!
9199 ! **************************************************************************************************
9200  SUBROUTINE mp_rget_iv(base, source, win, win_data, myproc, disp, request, &
9201  origin_datatype, target_datatype)
9202  INTEGER(KIND=int_4), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
9203  INTEGER, INTENT(IN) :: source
9204  CLASS(mp_win_type), INTENT(IN) :: win
9205  INTEGER(KIND=int_4), DIMENSION(:), INTENT(IN) :: win_data
9206  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
9207  TYPE(mp_request_type), INTENT(OUT) :: request
9208  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
9209 
9210  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_iv'
9211 
9212  INTEGER :: handle
9213 #if defined(__parallel)
9214  INTEGER :: ierr, len, &
9215  origin_len, target_len
9216  LOGICAL :: do_local_copy
9217  INTEGER(kind=mpi_address_kind) :: disp_aint
9218  mpi_data_type :: handle_origin_datatype, handle_target_datatype
9219 #endif
9220 
9221  CALL mp_timeset(routinen, handle)
9222 
9223 #if defined(__parallel)
9224  len = SIZE(base)
9225  disp_aint = 0
9226  IF (PRESENT(disp)) THEN
9227  disp_aint = int(disp, kind=mpi_address_kind)
9228  END IF
9229  handle_origin_datatype = mpi_integer
9230  origin_len = len
9231  IF (PRESENT(origin_datatype)) THEN
9232  handle_origin_datatype = origin_datatype%type_handle
9233  origin_len = 1
9234  END IF
9235  handle_target_datatype = mpi_integer
9236  target_len = len
9237  IF (PRESENT(target_datatype)) THEN
9238  handle_target_datatype = target_datatype%type_handle
9239  target_len = 1
9240  END IF
9241  IF (len > 0) THEN
9242  do_local_copy = .false.
9243  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
9244  IF (myproc .EQ. source) do_local_copy = .true.
9245  END IF
9246  IF (do_local_copy) THEN
9247  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
9248  base(:) = win_data(disp_aint + 1:disp_aint + len)
9249  !$OMP END PARALLEL WORKSHARE
9250  request = mp_request_null
9251  ierr = 0
9252  ELSE
9253  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
9254  target_len, handle_target_datatype, win%handle, request%handle, ierr)
9255  END IF
9256  ELSE
9257  request = mp_request_null
9258  ierr = 0
9259  END IF
9260  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
9261 
9262  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*int_4_size)
9263 #else
9264  mark_used(source)
9265  mark_used(win)
9266  mark_used(myproc)
9267  mark_used(origin_datatype)
9268  mark_used(target_datatype)
9269 
9270  request = mp_request_null
9271  !
9272  IF (PRESENT(disp)) THEN
9273  base(:) = win_data(disp + 1:disp + SIZE(base))
9274  ELSE
9275  base(:) = win_data(:SIZE(base))
9276  END IF
9277 
9278 #endif
9279  CALL mp_timestop(handle)
9280  END SUBROUTINE mp_rget_iv
9281 
9282 ! **************************************************************************************************
9283 !> \brief ...
9284 !> \param count ...
9285 !> \param lengths ...
9286 !> \param displs ...
9287 !> \return ...
9288 ! ***************************************************************************
9289  FUNCTION mp_type_indexed_make_i (count, lengths, displs) &
9290  result(type_descriptor)
9291  INTEGER, INTENT(IN) :: count
9292  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
9293  TYPE(mp_type_descriptor_type) :: type_descriptor
9294 
9295  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_i'
9296 
9297  INTEGER :: handle
9298 #if defined(__parallel)
9299  INTEGER :: ierr
9300 #endif
9301 
9302  CALL mp_timeset(routinen, handle)
9303 
9304 #if defined(__parallel)
9305  CALL mpi_type_indexed(count, lengths, displs, mpi_integer, &
9306  type_descriptor%type_handle, ierr)
9307  IF (ierr /= 0) &
9308  cpabort("MPI_Type_Indexed @ "//routinen)
9309  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
9310  IF (ierr /= 0) &
9311  cpabort("MPI_Type_commit @ "//routinen)
9312 #else
9313  type_descriptor%type_handle = 17
9314 #endif
9315  type_descriptor%length = count
9316  NULLIFY (type_descriptor%subtype)
9317  type_descriptor%vector_descriptor(1:2) = 1
9318  type_descriptor%has_indexing = .true.
9319  type_descriptor%index_descriptor%index => lengths
9320  type_descriptor%index_descriptor%chunks => displs
9321 
9322  CALL mp_timestop(handle)
9323 
9324  END FUNCTION mp_type_indexed_make_i
9325 
9326 ! **************************************************************************************************
9327 !> \brief Allocates special parallel memory
9328 !> \param[in] DATA pointer to integer array to allocate
9329 !> \param[in] len number of integers to allocate
9330 !> \param[out] stat (optional) allocation status result
9331 !> \author UB
9332 ! **************************************************************************************************
9333  SUBROUTINE mp_allocate_i (DATA, len, stat)
9334  INTEGER(KIND=int_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
9335  INTEGER, INTENT(IN) :: len
9336  INTEGER, INTENT(OUT), OPTIONAL :: stat
9337 
9338  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_i'
9339 
9340  INTEGER :: handle, ierr
9341 
9342  CALL mp_timeset(routinen, handle)
9343 
9344 #if defined(__parallel)
9345  NULLIFY (data)
9346  CALL mp_alloc_mem(DATA, len, stat=ierr)
9347  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
9348  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
9349  CALL add_perf(perf_id=15, count=1)
9350 #else
9351  ALLOCATE (DATA(len), stat=ierr)
9352  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
9353  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
9354 #endif
9355  IF (PRESENT(stat)) stat = ierr
9356  CALL mp_timestop(handle)
9357  END SUBROUTINE mp_allocate_i
9358 
9359 ! **************************************************************************************************
9360 !> \brief Deallocates special parallel memory
9361 !> \param[in] DATA pointer to special memory to deallocate
9362 !> \param stat ...
9363 !> \author UB
9364 ! **************************************************************************************************
9365  SUBROUTINE mp_deallocate_i (DATA, stat)
9366  INTEGER(KIND=int_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
9367  INTEGER, INTENT(OUT), OPTIONAL :: stat
9368 
9369  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_i'
9370 
9371  INTEGER :: handle
9372 #if defined(__parallel)
9373  INTEGER :: ierr
9374 #endif
9375 
9376  CALL mp_timeset(routinen, handle)
9377 
9378 #if defined(__parallel)
9379  CALL mp_free_mem(DATA, ierr)
9380  IF (PRESENT(stat)) THEN
9381  stat = ierr
9382  ELSE
9383  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
9384  END IF
9385  NULLIFY (data)
9386  CALL add_perf(perf_id=15, count=1)
9387 #else
9388  DEALLOCATE (data)
9389  IF (PRESENT(stat)) stat = 0
9390 #endif
9391  CALL mp_timestop(handle)
9392  END SUBROUTINE mp_deallocate_i
9393 
9394 ! **************************************************************************************************
9395 !> \brief (parallel) Blocking individual file write using explicit offsets
9396 !> (serial) Unformatted stream write
9397 !> \param[in] fh file handle (file storage unit)
9398 !> \param[in] offset file offset (position)
9399 !> \param[in] msg data to be written to the file
9400 !> \param msglen ...
9401 !> \par MPI-I/O mapping mpi_file_write_at
9402 !> \par STREAM-I/O mapping WRITE
9403 !> \param[in](optional) msglen number of the elements of data
9404 ! **************************************************************************************************
9405  SUBROUTINE mp_file_write_at_iv(fh, offset, msg, msglen)
9406  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:)
9407  CLASS(mp_file_type), INTENT(IN) :: fh
9408  INTEGER, INTENT(IN), OPTIONAL :: msglen
9409  INTEGER(kind=file_offset), INTENT(IN) :: offset
9410 
9411  INTEGER :: msg_len
9412 #if defined(__parallel)
9413  INTEGER :: ierr
9414 #endif
9415 
9416  msg_len = SIZE(msg)
9417  IF (PRESENT(msglen)) msg_len = msglen
9418 #if defined(__parallel)
9419  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_integer, mpi_status_ignore, ierr)
9420  IF (ierr .NE. 0) &
9421  cpabort("mpi_file_write_at_iv @ mp_file_write_at_iv")
9422 #else
9423  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
9424 #endif
9425  END SUBROUTINE mp_file_write_at_iv
9426 
9427 ! **************************************************************************************************
9428 !> \brief ...
9429 !> \param fh ...
9430 !> \param offset ...
9431 !> \param msg ...
9432 ! **************************************************************************************************
9433  SUBROUTINE mp_file_write_at_i (fh, offset, msg)
9434  INTEGER(KIND=int_4), INTENT(IN) :: msg
9435  CLASS(mp_file_type), INTENT(IN) :: fh
9436  INTEGER(kind=file_offset), INTENT(IN) :: offset
9437 
9438 #if defined(__parallel)
9439  INTEGER :: ierr
9440 
9441  ierr = 0
9442  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_integer, mpi_status_ignore, ierr)
9443  IF (ierr .NE. 0) &
9444  cpabort("mpi_file_write_at_i @ mp_file_write_at_i")
9445 #else
9446  WRITE (unit=fh%handle, pos=offset + 1) msg
9447 #endif
9448  END SUBROUTINE mp_file_write_at_i
9449 
9450 ! **************************************************************************************************
9451 !> \brief (parallel) Blocking collective file write using explicit offsets
9452 !> (serial) Unformatted stream write
9453 !> \param fh ...
9454 !> \param offset ...
9455 !> \param msg ...
9456 !> \param msglen ...
9457 !> \par MPI-I/O mapping mpi_file_write_at_all
9458 !> \par STREAM-I/O mapping WRITE
9459 ! **************************************************************************************************
9460  SUBROUTINE mp_file_write_at_all_iv(fh, offset, msg, msglen)
9461  INTEGER(KIND=int_4), CONTIGUOUS, INTENT(IN) :: msg(:)
9462  CLASS(mp_file_type), INTENT(IN) :: fh
9463  INTEGER, INTENT(IN), OPTIONAL :: msglen
9464  INTEGER(kind=file_offset), INTENT(IN) :: offset
9465 
9466  INTEGER :: msg_len
9467 #if defined(__parallel)
9468  INTEGER :: ierr
9469 #endif
9470 
9471  msg_len = SIZE(msg)
9472  IF (PRESENT(msglen)) msg_len = msglen
9473 #if defined(__parallel)
9474  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_integer, mpi_status_ignore, ierr)
9475  IF (ierr .NE. 0) &
9476  cpabort("mpi_file_write_at_all_iv @ mp_file_write_at_all_iv")
9477 #else
9478  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
9479 #endif
9480  END SUBROUTINE mp_file_write_at_all_iv
9481 
9482 ! **************************************************************************************************
9483 !> \brief ...
9484 !> \param fh ...
9485 !> \param offset ...
9486 !> \param msg ...
9487 ! **************************************************************************************************
9488  SUBROUTINE mp_file_write_at_all_i (fh, offset, msg)
9489  INTEGER(KIND=int_4), INTENT(IN) :: msg
9490  CLASS(mp_file_type), INTENT(IN) :: fh
9491  INTEGER(kind=file_offset), INTENT(IN) :: offset
9492 
9493 #if defined(__parallel)
9494  INTEGER :: ierr
9495 
9496  ierr = 0
9497  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_integer, mpi_status_ignore, ierr)
9498  IF (ierr .NE. 0) &
9499  cpabort("mpi_file_write_at_all_i @ mp_file_write_at_all_i")
9500 #else
9501  WRITE (unit=fh%handle, pos=offset + 1) msg
9502 #endif
9503  END SUBROUTINE mp_file_write_at_all_i
9504 
9505 ! **************************************************************************************************
9506 !> \brief (parallel) Blocking individual file read using explicit offsets
9507 !> (serial) Unformatted stream read
9508 !> \param[in] fh file handle (file storage unit)
9509 !> \param[in] offset file offset (position)
9510 !> \param[out] msg data to be read from the file
9511 !> \param msglen ...
9512 !> \par MPI-I/O mapping mpi_file_read_at
9513 !> \par STREAM-I/O mapping READ
9514 !> \param[in](optional) msglen number of elements of data
9515 ! **************************************************************************************************
9516  SUBROUTINE mp_file_read_at_iv(fh, offset, msg, msglen)
9517  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msg(:)
9518  CLASS(mp_file_type), INTENT(IN) :: fh
9519  INTEGER, INTENT(IN), OPTIONAL :: msglen
9520  INTEGER(kind=file_offset), INTENT(IN) :: offset
9521 
9522  INTEGER :: msg_len
9523 #if defined(__parallel)
9524  INTEGER :: ierr
9525 #endif
9526 
9527  msg_len = SIZE(msg)
9528  IF (PRESENT(msglen)) msg_len = msglen
9529 #if defined(__parallel)
9530  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_integer, mpi_status_ignore, ierr)
9531  IF (ierr .NE. 0) &
9532  cpabort("mpi_file_read_at_iv @ mp_file_read_at_iv")
9533 #else
9534  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
9535 #endif
9536  END SUBROUTINE mp_file_read_at_iv
9537 
9538 ! **************************************************************************************************
9539 !> \brief ...
9540 !> \param fh ...
9541 !> \param offset ...
9542 !> \param msg ...
9543 ! **************************************************************************************************
9544  SUBROUTINE mp_file_read_at_i (fh, offset, msg)
9545  INTEGER(KIND=int_4), INTENT(OUT) :: msg
9546  CLASS(mp_file_type), INTENT(IN) :: fh
9547  INTEGER(kind=file_offset), INTENT(IN) :: offset
9548 
9549 #if defined(__parallel)
9550  INTEGER :: ierr
9551 
9552  ierr = 0
9553  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_integer, mpi_status_ignore, ierr)
9554  IF (ierr .NE. 0) &
9555  cpabort("mpi_file_read_at_i @ mp_file_read_at_i")
9556 #else
9557  READ (unit=fh%handle, pos=offset + 1) msg
9558 #endif
9559  END SUBROUTINE mp_file_read_at_i
9560 
9561 ! **************************************************************************************************
9562 !> \brief (parallel) Blocking collective file read using explicit offsets
9563 !> (serial) Unformatted stream read
9564 !> \param fh ...
9565 !> \param offset ...
9566 !> \param msg ...
9567 !> \param msglen ...
9568 !> \par MPI-I/O mapping mpi_file_read_at_all
9569 !> \par STREAM-I/O mapping READ
9570 ! **************************************************************************************************
9571  SUBROUTINE mp_file_read_at_all_iv(fh, offset, msg, msglen)
9572  INTEGER(KIND=int_4), INTENT(OUT), CONTIGUOUS :: msg(:)
9573  CLASS(mp_file_type), INTENT(IN) :: fh
9574  INTEGER, INTENT(IN), OPTIONAL :: msglen
9575  INTEGER(kind=file_offset), INTENT(IN) :: offset
9576 
9577  INTEGER :: msg_len
9578 #if defined(__parallel)
9579  INTEGER :: ierr
9580 #endif
9581 
9582  msg_len = SIZE(msg)
9583  IF (PRESENT(msglen)) msg_len = msglen
9584 #if defined(__parallel)
9585  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_integer, mpi_status_ignore, ierr)
9586  IF (ierr .NE. 0) &
9587  cpabort("mpi_file_read_at_all_iv @ mp_file_read_at_all_iv")
9588 #else
9589  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
9590 #endif
9591  END SUBROUTINE mp_file_read_at_all_iv
9592 
9593 ! **************************************************************************************************
9594 !> \brief ...
9595 !> \param fh ...
9596 !> \param offset ...
9597 !> \param msg ...
9598 ! **************************************************************************************************
9599  SUBROUTINE mp_file_read_at_all_i (fh, offset, msg)
9600  INTEGER(KIND=int_4), INTENT(OUT) :: msg
9601  CLASS(mp_file_type), INTENT(IN) :: fh
9602  INTEGER(kind=file_offset), INTENT(IN) :: offset
9603 
9604 #if defined(__parallel)
9605  INTEGER :: ierr
9606 
9607  ierr = 0
9608  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_integer, mpi_status_ignore, ierr)
9609  IF (ierr .NE. 0) &
9610  cpabort("mpi_file_read_at_all_i @ mp_file_read_at_all_i")
9611 #else
9612  READ (unit=fh%handle, pos=offset + 1) msg
9613 #endif
9614  END SUBROUTINE mp_file_read_at_all_i
9615 
9616 ! **************************************************************************************************
9617 !> \brief ...
9618 !> \param ptr ...
9619 !> \param vector_descriptor ...
9620 !> \param index_descriptor ...
9621 !> \return ...
9622 ! **************************************************************************************************
9623  FUNCTION mp_type_make_i (ptr, &
9624  vector_descriptor, index_descriptor) &
9625  result(type_descriptor)
9626  INTEGER(KIND=int_4), DIMENSION(:), TARGET, asynchronous :: ptr
9627  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
9628  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
9629  TYPE(mp_type_descriptor_type) :: type_descriptor
9630 
9631  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_i'
9632 
9633 #if defined(__parallel)
9634  INTEGER :: ierr
9635 #endif
9636 
9637  NULLIFY (type_descriptor%subtype)
9638  type_descriptor%length = SIZE(ptr)
9639 #if defined(__parallel)
9640  type_descriptor%type_handle = mpi_integer
9641  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
9642  IF (ierr /= 0) &
9643  cpabort("MPI_Get_address @ "//routinen)
9644 #else
9645  type_descriptor%type_handle = 17
9646 #endif
9647  type_descriptor%vector_descriptor(1:2) = 1
9648  type_descriptor%has_indexing = .false.
9649  type_descriptor%data_i => ptr
9650  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
9651  cpabort(routinen//": Vectors and indices NYI")
9652  END IF
9653  END FUNCTION mp_type_make_i
9654 
9655 ! **************************************************************************************************
9656 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
9657 !> as the Fortran version returns an integer, which we take to be a C_PTR
9658 !> \param DATA data array to allocate
9659 !> \param[in] len length (in data elements) of data array allocation
9660 !> \param[out] stat (optional) allocation status result
9661 ! **************************************************************************************************
9662  SUBROUTINE mp_alloc_mem_i (DATA, len, stat)
9663  INTEGER(KIND=int_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
9664  INTEGER, INTENT(IN) :: len
9665  INTEGER, INTENT(OUT), OPTIONAL :: stat
9666 
9667 #if defined(__parallel)
9668  INTEGER :: size, ierr, length, &
9669  mp_res
9670  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
9671  TYPE(c_ptr) :: mp_baseptr
9672  mpi_info_type :: mp_info
9673 
9674  length = max(len, 1)
9675  CALL mpi_type_size(mpi_integer, size, ierr)
9676  mp_size = int(length, kind=mpi_address_kind)*size
9677  IF (mp_size .GT. mp_max_memory_size) THEN
9678  cpabort("MPI cannot allocate more than 2 GiByte")
9679  END IF
9680  mp_info = mpi_info_null
9681  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
9682  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
9683  IF (PRESENT(stat)) stat = mp_res
9684 #else
9685  INTEGER :: length, mystat
9686  length = max(len, 1)
9687  IF (PRESENT(stat)) THEN
9688  ALLOCATE (DATA(length), stat=mystat)
9689  stat = mystat ! show to convention checker that stat is used
9690  ELSE
9691  ALLOCATE (DATA(length))
9692  END IF
9693 #endif
9694  END SUBROUTINE mp_alloc_mem_i
9695 
9696 ! **************************************************************************************************
9697 !> \brief Deallocates am array, ... this is hackish
9698 !> as the Fortran version takes an integer, which we hope to get by reference
9699 !> \param DATA data array to allocate
9700 !> \param[out] stat (optional) allocation status result
9701 ! **************************************************************************************************
9702  SUBROUTINE mp_free_mem_i (DATA, stat)
9703  INTEGER(KIND=int_4), DIMENSION(:), &
9704  POINTER, asynchronous :: data
9705  INTEGER, INTENT(OUT), OPTIONAL :: stat
9706 
9707 #if defined(__parallel)
9708  INTEGER :: mp_res
9709  CALL mpi_free_mem(DATA, mp_res)
9710  IF (PRESENT(stat)) stat = mp_res
9711 #else
9712  DEALLOCATE (data)
9713  IF (PRESENT(stat)) stat = 0
9714 #endif
9715  END SUBROUTINE mp_free_mem_i
9716 ! **************************************************************************************************
9717 !> \brief Shift around the data in msg
9718 !> \param[in,out] msg Rank-2 data to shift
9719 !> \param[in] comm message passing environment identifier
9720 !> \param[in] displ_in displacements (?)
9721 !> \par Example
9722 !> msg will be moved from rank to rank+displ_in (in a circular way)
9723 !> \par Limitations
9724 !> * displ_in will be 1 by default (others not tested)
9725 !> * the message array needs to be the same size on all processes
9726 ! **************************************************************************************************
9727  SUBROUTINE mp_shift_lm(msg, comm, displ_in)
9728 
9729  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
9730  CLASS(mp_comm_type), INTENT(IN) :: comm
9731  INTEGER, INTENT(IN), OPTIONAL :: displ_in
9732 
9733  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_lm'
9734 
9735  INTEGER :: handle, ierror
9736 #if defined(__parallel)
9737  INTEGER :: displ, left, &
9738  msglen, myrank, nprocs, &
9739  right, tag
9740 #endif
9741 
9742  ierror = 0
9743  CALL mp_timeset(routinen, handle)
9744 
9745 #if defined(__parallel)
9746  CALL mpi_comm_rank(comm%handle, myrank, ierror)
9747  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
9748  CALL mpi_comm_size(comm%handle, nprocs, ierror)
9749  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
9750  IF (PRESENT(displ_in)) THEN
9751  displ = displ_in
9752  ELSE
9753  displ = 1
9754  END IF
9755  right = modulo(myrank + displ, nprocs)
9756  left = modulo(myrank - displ, nprocs)
9757  tag = 17
9758  msglen = SIZE(msg)
9759  CALL mpi_sendrecv_replace(msg, msglen, mpi_integer8, right, tag, left, tag, &
9760  comm%handle, mpi_status_ignore, ierror)
9761  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
9762  CALL add_perf(perf_id=7, count=1, msg_size=msglen*int_8_size)
9763 #else
9764  mark_used(msg)
9765  mark_used(comm)
9766  mark_used(displ_in)
9767 #endif
9768  CALL mp_timestop(handle)
9769 
9770  END SUBROUTINE mp_shift_lm
9771 
9772 ! **************************************************************************************************
9773 !> \brief Shift around the data in msg
9774 !> \param[in,out] msg Data to shift
9775 !> \param[in] comm message passing environment identifier
9776 !> \param[in] displ_in displacements (?)
9777 !> \par Example
9778 !> msg will be moved from rank to rank+displ_in (in a circular way)
9779 !> \par Limitations
9780 !> * displ_in will be 1 by default (others not tested)
9781 !> * the message array needs to be the same size on all processes
9782 ! **************************************************************************************************
9783  SUBROUTINE mp_shift_l (msg, comm, displ_in)
9784 
9785  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
9786  CLASS(mp_comm_type), INTENT(IN) :: comm
9787  INTEGER, INTENT(IN), OPTIONAL :: displ_in
9788 
9789  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_l'
9790 
9791  INTEGER :: handle, ierror
9792 #if defined(__parallel)
9793  INTEGER :: displ, left, &
9794  msglen, myrank, nprocs, &
9795  right, tag
9796 #endif
9797 
9798  ierror = 0
9799  CALL mp_timeset(routinen, handle)
9800 
9801 #if defined(__parallel)
9802  CALL mpi_comm_rank(comm%handle, myrank, ierror)
9803  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
9804  CALL mpi_comm_size(comm%handle, nprocs, ierror)
9805  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
9806  IF (PRESENT(displ_in)) THEN
9807  displ = displ_in
9808  ELSE
9809  displ = 1
9810  END IF
9811  right = modulo(myrank + displ, nprocs)
9812  left = modulo(myrank - displ, nprocs)
9813  tag = 19
9814  msglen = SIZE(msg)
9815  CALL mpi_sendrecv_replace(msg, msglen, mpi_integer8, right, tag, left, &
9816  tag, comm%handle, mpi_status_ignore, ierror)
9817  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
9818  CALL add_perf(perf_id=7, count=1, msg_size=msglen*int_8_size)
9819 #else
9820  mark_used(msg)
9821  mark_used(comm)
9822  mark_used(displ_in)
9823 #endif
9824  CALL mp_timestop(handle)
9825 
9826  END SUBROUTINE mp_shift_l
9827 
9828 ! **************************************************************************************************
9829 !> \brief All-to-all data exchange, rank-1 data of different sizes
9830 !> \param[in] sb Data to send
9831 !> \param[in] scount Data counts for data sent to other processes
9832 !> \param[in] sdispl Respective data offsets for data sent to process
9833 !> \param[in,out] rb Buffer into which to receive data
9834 !> \param[in] rcount Data counts for data received from other
9835 !> processes
9836 !> \param[in] rdispl Respective data offsets for data received from
9837 !> other processes
9838 !> \param[in] comm Message passing environment identifier
9839 !> \par MPI mapping
9840 !> mpi_alltoallv
9841 !> \par Array sizes
9842 !> The scount, rcount, and the sdispl and rdispl arrays have a
9843 !> size equal to the number of processes.
9844 !> \par Offsets
9845 !> Values in sdispl and rdispl start with 0.
9846 ! **************************************************************************************************
9847  SUBROUTINE mp_alltoall_l11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
9848 
9849  INTEGER(KIND=int_8), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
9850  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
9851  INTEGER(KIND=int_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
9852  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
9853  CLASS(mp_comm_type), INTENT(IN) :: comm
9854 
9855  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l11v'
9856 
9857  INTEGER :: handle
9858 #if defined(__parallel)
9859  INTEGER :: ierr, msglen
9860 #else
9861  INTEGER :: i
9862 #endif
9863 
9864  CALL mp_timeset(routinen, handle)
9865 
9866 #if defined(__parallel)
9867  CALL mpi_alltoallv(sb, scount, sdispl, mpi_integer8, &
9868  rb, rcount, rdispl, mpi_integer8, comm%handle, ierr)
9869  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
9870  msglen = sum(scount) + sum(rcount)
9871  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
9872 #else
9873  mark_used(comm)
9874  mark_used(scount)
9875  mark_used(sdispl)
9876  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
9877  DO i = 1, rcount(1)
9878  rb(rdispl(1) + i) = sb(sdispl(1) + i)
9879  END DO
9880 #endif
9881  CALL mp_timestop(handle)
9882 
9883  END SUBROUTINE mp_alltoall_l11v
9884 
9885 ! **************************************************************************************************
9886 !> \brief All-to-all data exchange, rank-2 data of different sizes
9887 !> \param sb ...
9888 !> \param scount ...
9889 !> \param sdispl ...
9890 !> \param rb ...
9891 !> \param rcount ...
9892 !> \param rdispl ...
9893 !> \param comm ...
9894 !> \par MPI mapping
9895 !> mpi_alltoallv
9896 !> \note see mp_alltoall_l11v
9897 ! **************************************************************************************************
9898  SUBROUTINE mp_alltoall_l22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
9899 
9900  INTEGER(KIND=int_8), DIMENSION(:, :), &
9901  INTENT(IN), CONTIGUOUS :: sb
9902  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
9903  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, &
9904  INTENT(INOUT) :: rb
9905  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
9906  CLASS(mp_comm_type), INTENT(IN) :: comm
9907 
9908  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l22v'
9909 
9910  INTEGER :: handle
9911 #if defined(__parallel)
9912  INTEGER :: ierr, msglen
9913 #endif
9914 
9915  CALL mp_timeset(routinen, handle)
9916 
9917 #if defined(__parallel)
9918  CALL mpi_alltoallv(sb, scount, sdispl, mpi_integer8, &
9919  rb, rcount, rdispl, mpi_integer8, comm%handle, ierr)
9920  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
9921  msglen = sum(scount) + sum(rcount)
9922  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*int_8_size)
9923 #else
9924  mark_used(comm)
9925  mark_used(scount)
9926  mark_used(sdispl)
9927  mark_used(rcount)
9928  mark_used(rdispl)
9929  rb = sb
9930 #endif
9931  CALL mp_timestop(handle)
9932 
9933  END SUBROUTINE mp_alltoall_l22v
9934 
9935 ! **************************************************************************************************
9936 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
9937 !> \param[in] sb array with data to send
9938 !> \param[out] rb array into which data is received
9939 !> \param[in] count number of elements to send/receive (product of the
9940 !> extents of the first two dimensions)
9941 !> \param[in] comm Message passing environment identifier
9942 !> \par Index meaning
9943 !> \par The first two indices specify the data while the last index counts
9944 !> the processes
9945 !> \par Sizes of ranks
9946 !> All processes have the same data size.
9947 !> \par MPI mapping
9948 !> mpi_alltoall
9949 ! **************************************************************************************************
9950  SUBROUTINE mp_alltoall_l (sb, rb, count, comm)
9951 
9952  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
9953  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
9954  INTEGER, INTENT(IN) :: count
9955  CLASS(mp_comm_type), INTENT(IN) :: comm
9956 
9957  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l'
9958 
9959  INTEGER :: handle
9960 #if defined(__parallel)
9961  INTEGER :: ierr, msglen, np
9962 #endif
9963 
9964  CALL mp_timeset(routinen, handle)
9965 
9966 #if defined(__parallel)
9967  CALL mpi_alltoall(sb, count, mpi_integer8, &
9968  rb, count, mpi_integer8, comm%handle, ierr)
9969  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
9970  CALL mpi_comm_size(comm%handle, np, ierr)
9971  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
9972  msglen = 2*count*np
9973  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
9974 #else
9975  mark_used(count)
9976  mark_used(comm)
9977  rb = sb
9978 #endif
9979  CALL mp_timestop(handle)
9980 
9981  END SUBROUTINE mp_alltoall_l
9982 
9983 ! **************************************************************************************************
9984 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
9985 !> \param sb ...
9986 !> \param rb ...
9987 !> \param count ...
9988 !> \param commp ...
9989 !> \note see mp_alltoall_l
9990 ! **************************************************************************************************
9991  SUBROUTINE mp_alltoall_l22(sb, rb, count, comm)
9992 
9993  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
9994  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
9995  INTEGER, INTENT(IN) :: count
9996  CLASS(mp_comm_type), INTENT(IN) :: comm
9997 
9998  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l22'
9999 
10000  INTEGER :: handle
10001 #if defined(__parallel)
10002  INTEGER :: ierr, msglen, np
10003 #endif
10004 
10005  CALL mp_timeset(routinen, handle)
10006 
10007 #if defined(__parallel)
10008  CALL mpi_alltoall(sb, count, mpi_integer8, &
10009  rb, count, mpi_integer8, comm%handle, ierr)
10010  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10011  CALL mpi_comm_size(comm%handle, np, ierr)
10012  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10013  msglen = 2*SIZE(sb)*np
10014  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10015 #else
10016  mark_used(count)
10017  mark_used(comm)
10018  rb = sb
10019 #endif
10020  CALL mp_timestop(handle)
10021 
10022  END SUBROUTINE mp_alltoall_l22
10023 
10024 ! **************************************************************************************************
10025 !> \brief All-to-all data exchange, rank-3 data with equal sizes
10026 !> \param sb ...
10027 !> \param rb ...
10028 !> \param count ...
10029 !> \param comm ...
10030 !> \note see mp_alltoall_l
10031 ! **************************************************************************************************
10032  SUBROUTINE mp_alltoall_l33(sb, rb, count, comm)
10033 
10034  INTEGER(KIND=int_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
10035  INTEGER(KIND=int_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
10036  INTEGER, INTENT(IN) :: count
10037  CLASS(mp_comm_type), INTENT(IN) :: comm
10038 
10039  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l33'
10040 
10041  INTEGER :: handle
10042 #if defined(__parallel)
10043  INTEGER :: ierr, msglen, np
10044 #endif
10045 
10046  CALL mp_timeset(routinen, handle)
10047 
10048 #if defined(__parallel)
10049  CALL mpi_alltoall(sb, count, mpi_integer8, &
10050  rb, count, mpi_integer8, comm%handle, ierr)
10051  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10052  CALL mpi_comm_size(comm%handle, np, ierr)
10053  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10054  msglen = 2*count*np
10055  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10056 #else
10057  mark_used(count)
10058  mark_used(comm)
10059  rb = sb
10060 #endif
10061  CALL mp_timestop(handle)
10062 
10063  END SUBROUTINE mp_alltoall_l33
10064 
10065 ! **************************************************************************************************
10066 !> \brief All-to-all data exchange, rank 4 data, equal sizes
10067 !> \param sb ...
10068 !> \param rb ...
10069 !> \param count ...
10070 !> \param comm ...
10071 !> \note see mp_alltoall_l
10072 ! **************************************************************************************************
10073  SUBROUTINE mp_alltoall_l44(sb, rb, count, comm)
10074 
10075  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
10076  INTENT(IN) :: sb
10077  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
10078  INTENT(OUT) :: rb
10079  INTEGER, INTENT(IN) :: count
10080  CLASS(mp_comm_type), INTENT(IN) :: comm
10081 
10082  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l44'
10083 
10084  INTEGER :: handle
10085 #if defined(__parallel)
10086  INTEGER :: ierr, msglen, np
10087 #endif
10088 
10089  CALL mp_timeset(routinen, handle)
10090 
10091 #if defined(__parallel)
10092  CALL mpi_alltoall(sb, count, mpi_integer8, &
10093  rb, count, mpi_integer8, comm%handle, ierr)
10094  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10095  CALL mpi_comm_size(comm%handle, np, ierr)
10096  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10097  msglen = 2*count*np
10098  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10099 #else
10100  mark_used(count)
10101  mark_used(comm)
10102  rb = sb
10103 #endif
10104  CALL mp_timestop(handle)
10105 
10106  END SUBROUTINE mp_alltoall_l44
10107 
10108 ! **************************************************************************************************
10109 !> \brief All-to-all data exchange, rank 5 data, equal sizes
10110 !> \param sb ...
10111 !> \param rb ...
10112 !> \param count ...
10113 !> \param comm ...
10114 !> \note see mp_alltoall_l
10115 ! **************************************************************************************************
10116  SUBROUTINE mp_alltoall_l55(sb, rb, count, comm)
10117 
10118  INTEGER(KIND=int_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
10119  INTENT(IN) :: sb
10120  INTEGER(KIND=int_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
10121  INTENT(OUT) :: rb
10122  INTEGER, INTENT(IN) :: count
10123  CLASS(mp_comm_type), INTENT(IN) :: comm
10124 
10125  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l55'
10126 
10127  INTEGER :: handle
10128 #if defined(__parallel)
10129  INTEGER :: ierr, msglen, np
10130 #endif
10131 
10132  CALL mp_timeset(routinen, handle)
10133 
10134 #if defined(__parallel)
10135  CALL mpi_alltoall(sb, count, mpi_integer8, &
10136  rb, count, mpi_integer8, comm%handle, ierr)
10137  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10138  CALL mpi_comm_size(comm%handle, np, ierr)
10139  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10140  msglen = 2*count*np
10141  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10142 #else
10143  mark_used(count)
10144  mark_used(comm)
10145  rb = sb
10146 #endif
10147  CALL mp_timestop(handle)
10148 
10149  END SUBROUTINE mp_alltoall_l55
10150 
10151 ! **************************************************************************************************
10152 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
10153 !> \param sb ...
10154 !> \param rb ...
10155 !> \param count ...
10156 !> \param comm ...
10157 !> \note see mp_alltoall_l
10158 !> \note User must ensure size consistency.
10159 ! **************************************************************************************************
10160  SUBROUTINE mp_alltoall_l45(sb, rb, count, comm)
10161 
10162  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
10163  INTENT(IN) :: sb
10164  INTEGER(KIND=int_8), &
10165  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
10166  INTEGER, INTENT(IN) :: count
10167  CLASS(mp_comm_type), INTENT(IN) :: comm
10168 
10169  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l45'
10170 
10171  INTEGER :: handle
10172 #if defined(__parallel)
10173  INTEGER :: ierr, msglen, np
10174 #endif
10175 
10176  CALL mp_timeset(routinen, handle)
10177 
10178 #if defined(__parallel)
10179  CALL mpi_alltoall(sb, count, mpi_integer8, &
10180  rb, count, mpi_integer8, comm%handle, ierr)
10181  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10182  CALL mpi_comm_size(comm%handle, np, ierr)
10183  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10184  msglen = 2*count*np
10185  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10186 #else
10187  mark_used(count)
10188  mark_used(comm)
10189  rb = reshape(sb, shape(rb))
10190 #endif
10191  CALL mp_timestop(handle)
10192 
10193  END SUBROUTINE mp_alltoall_l45
10194 
10195 ! **************************************************************************************************
10196 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
10197 !> \param sb ...
10198 !> \param rb ...
10199 !> \param count ...
10200 !> \param comm ...
10201 !> \note see mp_alltoall_l
10202 !> \note User must ensure size consistency.
10203 ! **************************************************************************************************
10204  SUBROUTINE mp_alltoall_l34(sb, rb, count, comm)
10205 
10206  INTEGER(KIND=int_8), DIMENSION(:, :, :), CONTIGUOUS, &
10207  INTENT(IN) :: sb
10208  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
10209  INTENT(OUT) :: rb
10210  INTEGER, INTENT(IN) :: count
10211  CLASS(mp_comm_type), INTENT(IN) :: comm
10212 
10213  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l34'
10214 
10215  INTEGER :: handle
10216 #if defined(__parallel)
10217  INTEGER :: ierr, msglen, np
10218 #endif
10219 
10220  CALL mp_timeset(routinen, handle)
10221 
10222 #if defined(__parallel)
10223  CALL mpi_alltoall(sb, count, mpi_integer8, &
10224  rb, count, mpi_integer8, comm%handle, ierr)
10225  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10226  CALL mpi_comm_size(comm%handle, np, ierr)
10227  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10228  msglen = 2*count*np
10229  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10230 #else
10231  mark_used(count)
10232  mark_used(comm)
10233  rb = reshape(sb, shape(rb))
10234 #endif
10235  CALL mp_timestop(handle)
10236 
10237  END SUBROUTINE mp_alltoall_l34
10238 
10239 ! **************************************************************************************************
10240 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
10241 !> \param sb ...
10242 !> \param rb ...
10243 !> \param count ...
10244 !> \param comm ...
10245 !> \note see mp_alltoall_l
10246 !> \note User must ensure size consistency.
10247 ! **************************************************************************************************
10248  SUBROUTINE mp_alltoall_l54(sb, rb, count, comm)
10249 
10250  INTEGER(KIND=int_8), &
10251  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
10252  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
10253  INTENT(OUT) :: rb
10254  INTEGER, INTENT(IN) :: count
10255  CLASS(mp_comm_type), INTENT(IN) :: comm
10256 
10257  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_l54'
10258 
10259  INTEGER :: handle
10260 #if defined(__parallel)
10261  INTEGER :: ierr, msglen, np
10262 #endif
10263 
10264  CALL mp_timeset(routinen, handle)
10265 
10266 #if defined(__parallel)
10267  CALL mpi_alltoall(sb, count, mpi_integer8, &
10268  rb, count, mpi_integer8, comm%handle, ierr)
10269  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
10270  CALL mpi_comm_size(comm%handle, np, ierr)
10271  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
10272  msglen = 2*count*np
10273  CALL add_perf(perf_id=6, count=1, msg_size=msglen*int_8_size)
10274 #else
10275  mark_used(count)
10276  mark_used(comm)
10277  rb = reshape(sb, shape(rb))
10278 #endif
10279  CALL mp_timestop(handle)
10280 
10281  END SUBROUTINE mp_alltoall_l54
10282 
10283 ! **************************************************************************************************
10284 !> \brief Send one datum to another process
10285 !> \param[in] msg Scalar to send
10286 !> \param[in] dest Destination process
10287 !> \param[in] tag Transfer identifier
10288 !> \param[in] comm Message passing environment identifier
10289 !> \par MPI mapping
10290 !> mpi_send
10291 ! **************************************************************************************************
10292  SUBROUTINE mp_send_l (msg, dest, tag, comm)
10293  INTEGER(KIND=int_8), INTENT(IN) :: msg
10294  INTEGER, INTENT(IN) :: dest, tag
10295  CLASS(mp_comm_type), INTENT(IN) :: comm
10296 
10297  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_l'
10298 
10299  INTEGER :: handle
10300 #if defined(__parallel)
10301  INTEGER :: ierr, msglen
10302 #endif
10303 
10304  CALL mp_timeset(routinen, handle)
10305 
10306 #if defined(__parallel)
10307  msglen = 1
10308  CALL mpi_send(msg, msglen, mpi_integer8, dest, tag, comm%handle, ierr)
10309  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
10310  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_8_size)
10311 #else
10312  mark_used(msg)
10313  mark_used(dest)
10314  mark_used(tag)
10315  mark_used(comm)
10316  ! only defined in parallel
10317  cpabort("not in parallel mode")
10318 #endif
10319  CALL mp_timestop(handle)
10320  END SUBROUTINE mp_send_l
10321 
10322 ! **************************************************************************************************
10323 !> \brief Send rank-1 data to another process
10324 !> \param[in] msg Rank-1 data to send
10325 !> \param dest ...
10326 !> \param tag ...
10327 !> \param comm ...
10328 !> \note see mp_send_l
10329 ! **************************************************************************************************
10330  SUBROUTINE mp_send_lv(msg, dest, tag, comm)
10331  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:)
10332  INTEGER, INTENT(IN) :: dest, tag
10333  CLASS(mp_comm_type), INTENT(IN) :: comm
10334 
10335  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_lv'
10336 
10337  INTEGER :: handle
10338 #if defined(__parallel)
10339  INTEGER :: ierr, msglen
10340 #endif
10341 
10342  CALL mp_timeset(routinen, handle)
10343 
10344 #if defined(__parallel)
10345  msglen = SIZE(msg)
10346  CALL mpi_send(msg, msglen, mpi_integer8, dest, tag, comm%handle, ierr)
10347  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
10348  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_8_size)
10349 #else
10350  mark_used(msg)
10351  mark_used(dest)
10352  mark_used(tag)
10353  mark_used(comm)
10354  ! only defined in parallel
10355  cpabort("not in parallel mode")
10356 #endif
10357  CALL mp_timestop(handle)
10358  END SUBROUTINE mp_send_lv
10359 
10360 ! **************************************************************************************************
10361 !> \brief Send rank-2 data to another process
10362 !> \param[in] msg Rank-2 data to send
10363 !> \param dest ...
10364 !> \param tag ...
10365 !> \param comm ...
10366 !> \note see mp_send_l
10367 ! **************************************************************************************************
10368  SUBROUTINE mp_send_lm2(msg, dest, tag, comm)
10369  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
10370  INTEGER, INTENT(IN) :: dest, tag
10371  CLASS(mp_comm_type), INTENT(IN) :: comm
10372 
10373  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_lm2'
10374 
10375  INTEGER :: handle
10376 #if defined(__parallel)
10377  INTEGER :: ierr, msglen
10378 #endif
10379 
10380  CALL mp_timeset(routinen, handle)
10381 
10382 #if defined(__parallel)
10383  msglen = SIZE(msg)
10384  CALL mpi_send(msg, msglen, mpi_integer8, dest, tag, comm%handle, ierr)
10385  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
10386  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_8_size)
10387 #else
10388  mark_used(msg)
10389  mark_used(dest)
10390  mark_used(tag)
10391  mark_used(comm)
10392  ! only defined in parallel
10393  cpabort("not in parallel mode")
10394 #endif
10395  CALL mp_timestop(handle)
10396  END SUBROUTINE mp_send_lm2
10397 
10398 ! **************************************************************************************************
10399 !> \brief Send rank-3 data to another process
10400 !> \param[in] msg Rank-3 data to send
10401 !> \param dest ...
10402 !> \param tag ...
10403 !> \param comm ...
10404 !> \note see mp_send_l
10405 ! **************************************************************************************************
10406  SUBROUTINE mp_send_lm3(msg, dest, tag, comm)
10407  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
10408  INTEGER, INTENT(IN) :: dest, tag
10409  CLASS(mp_comm_type), INTENT(IN) :: comm
10410 
10411  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
10412 
10413  INTEGER :: handle
10414 #if defined(__parallel)
10415  INTEGER :: ierr, msglen
10416 #endif
10417 
10418  CALL mp_timeset(routinen, handle)
10419 
10420 #if defined(__parallel)
10421  msglen = SIZE(msg)
10422  CALL mpi_send(msg, msglen, mpi_integer8, dest, tag, comm%handle, ierr)
10423  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
10424  CALL add_perf(perf_id=13, count=1, msg_size=msglen*int_8_size)
10425 #else
10426  mark_used(msg)
10427  mark_used(dest)
10428  mark_used(tag)
10429  mark_used(comm)
10430  ! only defined in parallel
10431  cpabort("not in parallel mode")
10432 #endif
10433  CALL mp_timestop(handle)
10434  END SUBROUTINE mp_send_lm3
10435 
10436 ! **************************************************************************************************
10437 !> \brief Receive one datum from another process
10438 !> \param[in,out] msg Place received data into this variable
10439 !> \param[in,out] source Process to receive from
10440 !> \param[in,out] tag Transfer identifier
10441 !> \param[in] comm Message passing environment identifier
10442 !> \par MPI mapping
10443 !> mpi_send
10444 ! **************************************************************************************************
10445  SUBROUTINE mp_recv_l (msg, source, tag, comm)
10446  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
10447  INTEGER, INTENT(INOUT) :: source, tag
10448  CLASS(mp_comm_type), INTENT(IN) :: comm
10449 
10450  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_l'
10451 
10452  INTEGER :: handle
10453 #if defined(__parallel)
10454  INTEGER :: ierr, msglen
10455  mpi_status_type :: status
10456 #endif
10457 
10458  CALL mp_timeset(routinen, handle)
10459 
10460 #if defined(__parallel)
10461  msglen = 1
10462  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
10463  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, mpi_status_ignore, ierr)
10464  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10465  ELSE
10466  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, status, ierr)
10467  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10468  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_8_size)
10469  source = status mpi_status_extract(mpi_source)
10470  tag = status mpi_status_extract(mpi_tag)
10471  END IF
10472 #else
10473  mark_used(msg)
10474  mark_used(source)
10475  mark_used(tag)
10476  mark_used(comm)
10477  ! only defined in parallel
10478  cpabort("not in parallel mode")
10479 #endif
10480  CALL mp_timestop(handle)
10481  END SUBROUTINE mp_recv_l
10482 
10483 ! **************************************************************************************************
10484 !> \brief Receive rank-1 data from another process
10485 !> \param[in,out] msg Place received data into this rank-1 array
10486 !> \param source ...
10487 !> \param tag ...
10488 !> \param comm ...
10489 !> \note see mp_recv_l
10490 ! **************************************************************************************************
10491  SUBROUTINE mp_recv_lv(msg, source, tag, comm)
10492  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
10493  INTEGER, INTENT(INOUT) :: source, tag
10494  CLASS(mp_comm_type), INTENT(IN) :: comm
10495 
10496  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_lv'
10497 
10498  INTEGER :: handle
10499 #if defined(__parallel)
10500  INTEGER :: ierr, msglen
10501  mpi_status_type :: status
10502 #endif
10503 
10504  CALL mp_timeset(routinen, handle)
10505 
10506 #if defined(__parallel)
10507  msglen = SIZE(msg)
10508  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
10509  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, mpi_status_ignore, ierr)
10510  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10511  ELSE
10512  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, status, ierr)
10513  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10514  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_8_size)
10515  source = status mpi_status_extract(mpi_source)
10516  tag = status mpi_status_extract(mpi_tag)
10517  END IF
10518 #else
10519  mark_used(msg)
10520  mark_used(source)
10521  mark_used(tag)
10522  mark_used(comm)
10523  ! only defined in parallel
10524  cpabort("not in parallel mode")
10525 #endif
10526  CALL mp_timestop(handle)
10527  END SUBROUTINE mp_recv_lv
10528 
10529 ! **************************************************************************************************
10530 !> \brief Receive rank-2 data from another process
10531 !> \param[in,out] msg Place received data into this rank-2 array
10532 !> \param source ...
10533 !> \param tag ...
10534 !> \param comm ...
10535 !> \note see mp_recv_l
10536 ! **************************************************************************************************
10537  SUBROUTINE mp_recv_lm2(msg, source, tag, comm)
10538  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
10539  INTEGER, INTENT(INOUT) :: source, tag
10540  CLASS(mp_comm_type), INTENT(IN) :: comm
10541 
10542  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_lm2'
10543 
10544  INTEGER :: handle
10545 #if defined(__parallel)
10546  INTEGER :: ierr, msglen
10547  mpi_status_type :: status
10548 #endif
10549 
10550  CALL mp_timeset(routinen, handle)
10551 
10552 #if defined(__parallel)
10553  msglen = SIZE(msg)
10554  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
10555  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, mpi_status_ignore, ierr)
10556  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10557  ELSE
10558  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, status, ierr)
10559  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10560  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_8_size)
10561  source = status mpi_status_extract(mpi_source)
10562  tag = status mpi_status_extract(mpi_tag)
10563  END IF
10564 #else
10565  mark_used(msg)
10566  mark_used(source)
10567  mark_used(tag)
10568  mark_used(comm)
10569  ! only defined in parallel
10570  cpabort("not in parallel mode")
10571 #endif
10572  CALL mp_timestop(handle)
10573  END SUBROUTINE mp_recv_lm2
10574 
10575 ! **************************************************************************************************
10576 !> \brief Receive rank-3 data from another process
10577 !> \param[in,out] msg Place received data into this rank-3 array
10578 !> \param source ...
10579 !> \param tag ...
10580 !> \param comm ...
10581 !> \note see mp_recv_l
10582 ! **************************************************************************************************
10583  SUBROUTINE mp_recv_lm3(msg, source, tag, comm)
10584  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
10585  INTEGER, INTENT(INOUT) :: source, tag
10586  CLASS(mp_comm_type), INTENT(IN) :: comm
10587 
10588  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_lm3'
10589 
10590  INTEGER :: handle
10591 #if defined(__parallel)
10592  INTEGER :: ierr, msglen
10593  mpi_status_type :: status
10594 #endif
10595 
10596  CALL mp_timeset(routinen, handle)
10597 
10598 #if defined(__parallel)
10599  msglen = SIZE(msg)
10600  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
10601  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, mpi_status_ignore, ierr)
10602  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10603  ELSE
10604  CALL mpi_recv(msg, msglen, mpi_integer8, source, tag, comm%handle, status, ierr)
10605  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
10606  CALL add_perf(perf_id=14, count=1, msg_size=msglen*int_8_size)
10607  source = status mpi_status_extract(mpi_source)
10608  tag = status mpi_status_extract(mpi_tag)
10609  END IF
10610 #else
10611  mark_used(msg)
10612  mark_used(source)
10613  mark_used(tag)
10614  mark_used(comm)
10615  ! only defined in parallel
10616  cpabort("not in parallel mode")
10617 #endif
10618  CALL mp_timestop(handle)
10619  END SUBROUTINE mp_recv_lm3
10620 
10621 ! **************************************************************************************************
10622 !> \brief Broadcasts a datum to all processes.
10623 !> \param[in] msg Datum to broadcast
10624 !> \param[in] source Processes which broadcasts
10625 !> \param[in] comm Message passing environment identifier
10626 !> \par MPI mapping
10627 !> mpi_bcast
10628 ! **************************************************************************************************
10629  SUBROUTINE mp_bcast_l (msg, source, comm)
10630  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
10631  INTEGER, INTENT(IN) :: source
10632  CLASS(mp_comm_type), INTENT(IN) :: comm
10633 
10634  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_l'
10635 
10636  INTEGER :: handle
10637 #if defined(__parallel)
10638  INTEGER :: ierr, msglen
10639 #endif
10640 
10641  CALL mp_timeset(routinen, handle)
10642 
10643 #if defined(__parallel)
10644  msglen = 1
10645  CALL mpi_bcast(msg, msglen, mpi_integer8, source, comm%handle, ierr)
10646  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10647  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10648 #else
10649  mark_used(msg)
10650  mark_used(source)
10651  mark_used(comm)
10652 #endif
10653  CALL mp_timestop(handle)
10654  END SUBROUTINE mp_bcast_l
10655 
10656 ! **************************************************************************************************
10657 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
10658 !> \param[in] msg Datum to broadcast
10659 !> \param[in] comm Message passing environment identifier
10660 !> \par MPI mapping
10661 !> mpi_bcast
10662 ! **************************************************************************************************
10663  SUBROUTINE mp_bcast_l_src(msg, comm)
10664  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
10665  CLASS(mp_comm_type), INTENT(IN) :: comm
10666 
10667  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_l_src'
10668 
10669  INTEGER :: handle
10670 #if defined(__parallel)
10671  INTEGER :: ierr, msglen
10672 #endif
10673 
10674  CALL mp_timeset(routinen, handle)
10675 
10676 #if defined(__parallel)
10677  msglen = 1
10678  CALL mpi_bcast(msg, msglen, mpi_integer8, comm%source, comm%handle, ierr)
10679  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10680  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10681 #else
10682  mark_used(msg)
10683  mark_used(comm)
10684 #endif
10685  CALL mp_timestop(handle)
10686  END SUBROUTINE mp_bcast_l_src
10687 
10688 ! **************************************************************************************************
10689 !> \brief Broadcasts a datum to all processes.
10690 !> \param[in] msg Datum to broadcast
10691 !> \param[in] source Processes which broadcasts
10692 !> \param[in] comm Message passing environment identifier
10693 !> \par MPI mapping
10694 !> mpi_bcast
10695 ! **************************************************************************************************
10696  SUBROUTINE mp_ibcast_l (msg, source, comm, request)
10697  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
10698  INTEGER, INTENT(IN) :: source
10699  CLASS(mp_comm_type), INTENT(IN) :: comm
10700  TYPE(mp_request_type), INTENT(OUT) :: request
10701 
10702  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_l'
10703 
10704  INTEGER :: handle
10705 #if defined(__parallel)
10706  INTEGER :: ierr, msglen
10707 #endif
10708 
10709  CALL mp_timeset(routinen, handle)
10710 
10711 #if defined(__parallel)
10712  msglen = 1
10713  CALL mpi_ibcast(msg, msglen, mpi_integer8, source, comm%handle, request%handle, ierr)
10714  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
10715  CALL add_perf(perf_id=22, count=1, msg_size=msglen*int_8_size)
10716 #else
10717  mark_used(msg)
10718  mark_used(source)
10719  mark_used(comm)
10720  request = mp_request_null
10721 #endif
10722  CALL mp_timestop(handle)
10723  END SUBROUTINE mp_ibcast_l
10724 
10725 ! **************************************************************************************************
10726 !> \brief Broadcasts rank-1 data to all processes
10727 !> \param[in] msg Data to broadcast
10728 !> \param source ...
10729 !> \param comm ...
10730 !> \note see mp_bcast_l1
10731 ! **************************************************************************************************
10732  SUBROUTINE mp_bcast_lv(msg, source, comm)
10733  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
10734  INTEGER, INTENT(IN) :: source
10735  CLASS(mp_comm_type), INTENT(IN) :: comm
10736 
10737  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_lv'
10738 
10739  INTEGER :: handle
10740 #if defined(__parallel)
10741  INTEGER :: ierr, msglen
10742 #endif
10743 
10744  CALL mp_timeset(routinen, handle)
10745 
10746 #if defined(__parallel)
10747  msglen = SIZE(msg)
10748  CALL mpi_bcast(msg, msglen, mpi_integer8, source, comm%handle, ierr)
10749  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10750  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10751 #else
10752  mark_used(msg)
10753  mark_used(source)
10754  mark_used(comm)
10755 #endif
10756  CALL mp_timestop(handle)
10757  END SUBROUTINE mp_bcast_lv
10758 
10759 ! **************************************************************************************************
10760 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
10761 !> \param[in] msg Data to broadcast
10762 !> \param comm ...
10763 !> \note see mp_bcast_l1
10764 ! **************************************************************************************************
10765  SUBROUTINE mp_bcast_lv_src(msg, comm)
10766  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
10767  CLASS(mp_comm_type), INTENT(IN) :: comm
10768 
10769  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_lv_src'
10770 
10771  INTEGER :: handle
10772 #if defined(__parallel)
10773  INTEGER :: ierr, msglen
10774 #endif
10775 
10776  CALL mp_timeset(routinen, handle)
10777 
10778 #if defined(__parallel)
10779  msglen = SIZE(msg)
10780  CALL mpi_bcast(msg, msglen, mpi_integer8, comm%source, comm%handle, ierr)
10781  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10782  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10783 #else
10784  mark_used(msg)
10785  mark_used(comm)
10786 #endif
10787  CALL mp_timestop(handle)
10788  END SUBROUTINE mp_bcast_lv_src
10789 
10790 ! **************************************************************************************************
10791 !> \brief Broadcasts rank-1 data to all processes
10792 !> \param[in] msg Data to broadcast
10793 !> \param source ...
10794 !> \param comm ...
10795 !> \note see mp_bcast_l1
10796 ! **************************************************************************************************
10797  SUBROUTINE mp_ibcast_lv(msg, source, comm, request)
10798  INTEGER(KIND=int_8), INTENT(INOUT) :: msg(:)
10799  INTEGER, INTENT(IN) :: source
10800  CLASS(mp_comm_type), INTENT(IN) :: comm
10801  TYPE(mp_request_type) :: request
10802 
10803  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_lv'
10804 
10805  INTEGER :: handle
10806 #if defined(__parallel)
10807  INTEGER :: ierr, msglen
10808 #endif
10809 
10810  CALL mp_timeset(routinen, handle)
10811 
10812 #if defined(__parallel)
10813 #if !defined(__GNUC__) || __GNUC__ >= 9
10814  cpassert(is_contiguous(msg))
10815 #endif
10816  msglen = SIZE(msg)
10817  CALL mpi_ibcast(msg, msglen, mpi_integer8, source, comm%handle, request%handle, ierr)
10818  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
10819  CALL add_perf(perf_id=22, count=1, msg_size=msglen*int_8_size)
10820 #else
10821  mark_used(msg)
10822  mark_used(source)
10823  mark_used(comm)
10824  request = mp_request_null
10825 #endif
10826  CALL mp_timestop(handle)
10827  END SUBROUTINE mp_ibcast_lv
10828 
10829 ! **************************************************************************************************
10830 !> \brief Broadcasts rank-2 data to all processes
10831 !> \param[in] msg Data to broadcast
10832 !> \param source ...
10833 !> \param comm ...
10834 !> \note see mp_bcast_l1
10835 ! **************************************************************************************************
10836  SUBROUTINE mp_bcast_lm(msg, source, comm)
10837  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
10838  INTEGER, INTENT(IN) :: source
10839  CLASS(mp_comm_type), INTENT(IN) :: comm
10840 
10841  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_lm'
10842 
10843  INTEGER :: handle
10844 #if defined(__parallel)
10845  INTEGER :: ierr, msglen
10846 #endif
10847 
10848  CALL mp_timeset(routinen, handle)
10849 
10850 #if defined(__parallel)
10851  msglen = SIZE(msg)
10852  CALL mpi_bcast(msg, msglen, mpi_integer8, source, comm%handle, ierr)
10853  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10854  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10855 #else
10856  mark_used(msg)
10857  mark_used(source)
10858  mark_used(comm)
10859 #endif
10860  CALL mp_timestop(handle)
10861  END SUBROUTINE mp_bcast_lm
10862 
10863 ! **************************************************************************************************
10864 !> \brief Broadcasts rank-2 data to all processes
10865 !> \param[in] msg Data to broadcast
10866 !> \param source ...
10867 !> \param comm ...
10868 !> \note see mp_bcast_l1
10869 ! **************************************************************************************************
10870  SUBROUTINE mp_bcast_lm_src(msg, comm)
10871  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
10872  CLASS(mp_comm_type), INTENT(IN) :: comm
10873 
10874  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_lm_src'
10875 
10876  INTEGER :: handle
10877 #if defined(__parallel)
10878  INTEGER :: ierr, msglen
10879 #endif
10880 
10881  CALL mp_timeset(routinen, handle)
10882 
10883 #if defined(__parallel)
10884  msglen = SIZE(msg)
10885  CALL mpi_bcast(msg, msglen, mpi_integer8, comm%source, comm%handle, ierr)
10886  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10887  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10888 #else
10889  mark_used(msg)
10890  mark_used(comm)
10891 #endif
10892  CALL mp_timestop(handle)
10893  END SUBROUTINE mp_bcast_lm_src
10894 
10895 ! **************************************************************************************************
10896 !> \brief Broadcasts rank-3 data to all processes
10897 !> \param[in] msg Data to broadcast
10898 !> \param source ...
10899 !> \param comm ...
10900 !> \note see mp_bcast_l1
10901 ! **************************************************************************************************
10902  SUBROUTINE mp_bcast_l3(msg, source, comm)
10903  INTEGER(KIND=int_8), CONTIGUOUS :: msg(:, :, :)
10904  INTEGER, INTENT(IN) :: source
10905  CLASS(mp_comm_type), INTENT(IN) :: comm
10906 
10907  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_l3'
10908 
10909  INTEGER :: handle
10910 #if defined(__parallel)
10911  INTEGER :: ierr, msglen
10912 #endif
10913 
10914  CALL mp_timeset(routinen, handle)
10915 
10916 #if defined(__parallel)
10917  msglen = SIZE(msg)
10918  CALL mpi_bcast(msg, msglen, mpi_integer8, source, comm%handle, ierr)
10919  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10920  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10921 #else
10922  mark_used(msg)
10923  mark_used(source)
10924  mark_used(comm)
10925 #endif
10926  CALL mp_timestop(handle)
10927  END SUBROUTINE mp_bcast_l3
10928 
10929 ! **************************************************************************************************
10930 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
10931 !> \param[in] msg Data to broadcast
10932 !> \param source ...
10933 !> \param comm ...
10934 !> \note see mp_bcast_l1
10935 ! **************************************************************************************************
10936  SUBROUTINE mp_bcast_l3_src(msg, comm)
10937  INTEGER(KIND=int_8), CONTIGUOUS :: msg(:, :, :)
10938  CLASS(mp_comm_type), INTENT(IN) :: comm
10939 
10940  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_l3_src'
10941 
10942  INTEGER :: handle
10943 #if defined(__parallel)
10944  INTEGER :: ierr, msglen
10945 #endif
10946 
10947  CALL mp_timeset(routinen, handle)
10948 
10949 #if defined(__parallel)
10950  msglen = SIZE(msg)
10951  CALL mpi_bcast(msg, msglen, mpi_integer8, comm%source, comm%handle, ierr)
10952  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
10953  CALL add_perf(perf_id=2, count=1, msg_size=msglen*int_8_size)
10954 #else
10955  mark_used(msg)
10956  mark_used(comm)
10957 #endif
10958  CALL mp_timestop(handle)
10959  END SUBROUTINE mp_bcast_l3_src
10960 
10961 ! **************************************************************************************************
10962 !> \brief Sums a datum from all processes with result left on all processes.
10963 !> \param[in,out] msg Datum to sum (input) and result (output)
10964 !> \param[in] comm Message passing environment identifier
10965 !> \par MPI mapping
10966 !> mpi_allreduce
10967 ! **************************************************************************************************
10968  SUBROUTINE mp_sum_l (msg, comm)
10969  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
10970  CLASS(mp_comm_type), INTENT(IN) :: comm
10971 
10972  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_l'
10973 
10974  INTEGER :: handle
10975 #if defined(__parallel)
10976  INTEGER :: ierr, msglen
10977 #endif
10978 
10979  CALL mp_timeset(routinen, handle)
10980 
10981 #if defined(__parallel)
10982  msglen = 1
10983  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
10984  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
10985  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
10986 #else
10987  mark_used(msg)
10988  mark_used(comm)
10989 #endif
10990  CALL mp_timestop(handle)
10991  END SUBROUTINE mp_sum_l
10992 
10993 ! **************************************************************************************************
10994 !> \brief Element-wise sum of a rank-1 array on all processes.
10995 !> \param[in,out] msg Vector to sum and result
10996 !> \param comm ...
10997 !> \note see mp_sum_l
10998 ! **************************************************************************************************
10999  SUBROUTINE mp_sum_lv(msg, comm)
11000  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
11001  CLASS(mp_comm_type), INTENT(IN) :: comm
11002 
11003  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_lv'
11004 
11005  INTEGER :: handle
11006 #if defined(__parallel)
11007  INTEGER :: ierr, msglen
11008 #endif
11009 
11010  CALL mp_timeset(routinen, handle)
11011 
11012 #if defined(__parallel)
11013  msglen = SIZE(msg)
11014  IF (msglen > 0) THEN
11015  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
11016  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11017  END IF
11018  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11019 #else
11020  mark_used(msg)
11021  mark_used(comm)
11022 #endif
11023  CALL mp_timestop(handle)
11024  END SUBROUTINE mp_sum_lv
11025 
11026 ! **************************************************************************************************
11027 !> \brief Element-wise sum of a rank-1 array on all processes.
11028 !> \param[in,out] msg Vector to sum and result
11029 !> \param comm ...
11030 !> \note see mp_sum_l
11031 ! **************************************************************************************************
11032  SUBROUTINE mp_isum_lv(msg, comm, request)
11033  INTEGER(KIND=int_8), INTENT(INOUT) :: msg(:)
11034  CLASS(mp_comm_type), INTENT(IN) :: comm
11035  TYPE(mp_request_type), INTENT(OUT) :: request
11036 
11037  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_lv'
11038 
11039  INTEGER :: handle
11040 #if defined(__parallel)
11041  INTEGER :: ierr, msglen
11042 #endif
11043 
11044  CALL mp_timeset(routinen, handle)
11045 
11046 #if defined(__parallel)
11047 #if !defined(__GNUC__) || __GNUC__ >= 9
11048  cpassert(is_contiguous(msg))
11049 #endif
11050  msglen = SIZE(msg)
11051  IF (msglen > 0) THEN
11052  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_sum, comm%handle, request%handle, ierr)
11053  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
11054  ELSE
11055  request = mp_request_null
11056  END IF
11057  CALL add_perf(perf_id=23, count=1, msg_size=msglen*int_8_size)
11058 #else
11059  mark_used(msg)
11060  mark_used(comm)
11061  request = mp_request_null
11062 #endif
11063  CALL mp_timestop(handle)
11064  END SUBROUTINE mp_isum_lv
11065 
11066 ! **************************************************************************************************
11067 !> \brief Element-wise sum of a rank-2 array on all processes.
11068 !> \param[in] msg Matrix to sum and result
11069 !> \param comm ...
11070 !> \note see mp_sum_l
11071 ! **************************************************************************************************
11072  SUBROUTINE mp_sum_lm(msg, comm)
11073  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
11074  CLASS(mp_comm_type), INTENT(IN) :: comm
11075 
11076  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_lm'
11077 
11078  INTEGER :: handle
11079 #if defined(__parallel)
11080  INTEGER, PARAMETER :: max_msg = 2**25
11081  INTEGER :: ierr, m1, msglen, step, msglensum
11082 #endif
11083 
11084  CALL mp_timeset(routinen, handle)
11085 
11086 #if defined(__parallel)
11087  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
11088  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
11089  msglensum = 0
11090  DO m1 = lbound(msg, 2), ubound(msg, 2), step
11091  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
11092  msglensum = msglensum + msglen
11093  IF (msglen > 0) THEN
11094  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
11095  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11096  END IF
11097  END DO
11098  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*int_8_size)
11099 #else
11100  mark_used(msg)
11101  mark_used(comm)
11102 #endif
11103  CALL mp_timestop(handle)
11104  END SUBROUTINE mp_sum_lm
11105 
11106 ! **************************************************************************************************
11107 !> \brief Element-wise sum of a rank-3 array on all processes.
11108 !> \param[in] msg Array to sum and result
11109 !> \param comm ...
11110 !> \note see mp_sum_l
11111 ! **************************************************************************************************
11112  SUBROUTINE mp_sum_lm3(msg, comm)
11113  INTEGER(KIND=int_8), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
11114  CLASS(mp_comm_type), INTENT(IN) :: comm
11115 
11116  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_lm3'
11117 
11118  INTEGER :: handle
11119 #if defined(__parallel)
11120  INTEGER :: ierr, msglen
11121 #endif
11122 
11123  CALL mp_timeset(routinen, handle)
11124 
11125 #if defined(__parallel)
11126  msglen = SIZE(msg)
11127  IF (msglen > 0) THEN
11128  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
11129  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11130  END IF
11131  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11132 #else
11133  mark_used(msg)
11134  mark_used(comm)
11135 #endif
11136  CALL mp_timestop(handle)
11137  END SUBROUTINE mp_sum_lm3
11138 
11139 ! **************************************************************************************************
11140 !> \brief Element-wise sum of a rank-4 array on all processes.
11141 !> \param[in] msg Array to sum and result
11142 !> \param comm ...
11143 !> \note see mp_sum_l
11144 ! **************************************************************************************************
11145  SUBROUTINE mp_sum_lm4(msg, comm)
11146  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
11147  CLASS(mp_comm_type), INTENT(IN) :: comm
11148 
11149  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_lm4'
11150 
11151  INTEGER :: handle
11152 #if defined(__parallel)
11153  INTEGER :: ierr, msglen
11154 #endif
11155 
11156  CALL mp_timeset(routinen, handle)
11157 
11158 #if defined(__parallel)
11159  msglen = SIZE(msg)
11160  IF (msglen > 0) THEN
11161  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
11162  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11163  END IF
11164  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11165 #else
11166  mark_used(msg)
11167  mark_used(comm)
11168 #endif
11169  CALL mp_timestop(handle)
11170  END SUBROUTINE mp_sum_lm4
11171 
11172 ! **************************************************************************************************
11173 !> \brief Element-wise sum of data from all processes with result left only on
11174 !> one.
11175 !> \param[in,out] msg Vector to sum (input) and (only on process root)
11176 !> result (output)
11177 !> \param root ...
11178 !> \param[in] comm Message passing environment identifier
11179 !> \par MPI mapping
11180 !> mpi_reduce
11181 ! **************************************************************************************************
11182  SUBROUTINE mp_sum_root_lv(msg, root, comm)
11183  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
11184  INTEGER, INTENT(IN) :: root
11185  CLASS(mp_comm_type), INTENT(IN) :: comm
11186 
11187  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_lv'
11188 
11189  INTEGER :: handle
11190 #if defined(__parallel)
11191  INTEGER :: ierr, m1, msglen, taskid
11192  INTEGER(KIND=int_8), ALLOCATABLE :: res(:)
11193 #endif
11194 
11195  CALL mp_timeset(routinen, handle)
11196 
11197 #if defined(__parallel)
11198  msglen = SIZE(msg)
11199  CALL mpi_comm_rank(comm%handle, taskid, ierr)
11200  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
11201  IF (msglen > 0) THEN
11202  m1 = SIZE(msg, 1)
11203  ALLOCATE (res(m1))
11204  CALL mpi_reduce(msg, res, msglen, mpi_integer8, mpi_sum, &
11205  root, comm%handle, ierr)
11206  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
11207  IF (taskid == root) THEN
11208  msg = res
11209  END IF
11210  DEALLOCATE (res)
11211  END IF
11212  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11213 #else
11214  mark_used(msg)
11215  mark_used(root)
11216  mark_used(comm)
11217 #endif
11218  CALL mp_timestop(handle)
11219  END SUBROUTINE mp_sum_root_lv
11220 
11221 ! **************************************************************************************************
11222 !> \brief Element-wise sum of data from all processes with result left only on
11223 !> one.
11224 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
11225 !> result (output)
11226 !> \param root ...
11227 !> \param comm ...
11228 !> \note see mp_sum_root_lv
11229 ! **************************************************************************************************
11230  SUBROUTINE mp_sum_root_lm(msg, root, comm)
11231  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
11232  INTEGER, INTENT(IN) :: root
11233  CLASS(mp_comm_type), INTENT(IN) :: comm
11234 
11235  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
11236 
11237  INTEGER :: handle
11238 #if defined(__parallel)
11239  INTEGER :: ierr, m1, m2, msglen, taskid
11240  INTEGER(KIND=int_8), ALLOCATABLE :: res(:, :)
11241 #endif
11242 
11243  CALL mp_timeset(routinen, handle)
11244 
11245 #if defined(__parallel)
11246  msglen = SIZE(msg)
11247  CALL mpi_comm_rank(comm%handle, taskid, ierr)
11248  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
11249  IF (msglen > 0) THEN
11250  m1 = SIZE(msg, 1)
11251  m2 = SIZE(msg, 2)
11252  ALLOCATE (res(m1, m2))
11253  CALL mpi_reduce(msg, res, msglen, mpi_integer8, mpi_sum, root, comm%handle, ierr)
11254  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
11255  IF (taskid == root) THEN
11256  msg = res
11257  END IF
11258  DEALLOCATE (res)
11259  END IF
11260  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11261 #else
11262  mark_used(root)
11263  mark_used(msg)
11264  mark_used(comm)
11265 #endif
11266  CALL mp_timestop(handle)
11267  END SUBROUTINE mp_sum_root_lm
11268 
11269 ! **************************************************************************************************
11270 !> \brief Partial sum of data from all processes with result on each process.
11271 !> \param[in] msg Matrix to sum (input)
11272 !> \param[out] res Matrix containing result (output)
11273 !> \param[in] comm Message passing environment identifier
11274 ! **************************************************************************************************
11275  SUBROUTINE mp_sum_partial_lm(msg, res, comm)
11276  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
11277  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: res(:, :)
11278  CLASS(mp_comm_type), INTENT(IN) :: comm
11279 
11280  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_lm'
11281 
11282  INTEGER :: handle
11283 #if defined(__parallel)
11284  INTEGER :: ierr, msglen, taskid
11285 #endif
11286 
11287  CALL mp_timeset(routinen, handle)
11288 
11289 #if defined(__parallel)
11290  msglen = SIZE(msg)
11291  CALL mpi_comm_rank(comm%handle, taskid, ierr)
11292  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
11293  IF (msglen > 0) THEN
11294  CALL mpi_scan(msg, res, msglen, mpi_integer8, mpi_sum, comm%handle, ierr)
11295  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
11296  END IF
11297  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11298  ! perf_id is same as for other summation routines
11299 #else
11300  res = msg
11301  mark_used(comm)
11302 #endif
11303  CALL mp_timestop(handle)
11304  END SUBROUTINE mp_sum_partial_lm
11305 
11306 ! **************************************************************************************************
11307 !> \brief Finds the maximum of a datum with the result left on all processes.
11308 !> \param[in,out] msg Find maximum among these data (input) and
11309 !> maximum (output)
11310 !> \param[in] comm Message passing environment identifier
11311 !> \par MPI mapping
11312 !> mpi_allreduce
11313 ! **************************************************************************************************
11314  SUBROUTINE mp_max_l (msg, comm)
11315  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
11316  CLASS(mp_comm_type), INTENT(IN) :: comm
11317 
11318  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_l'
11319 
11320  INTEGER :: handle
11321 #if defined(__parallel)
11322  INTEGER :: ierr, msglen
11323 #endif
11324 
11325  CALL mp_timeset(routinen, handle)
11326 
11327 #if defined(__parallel)
11328  msglen = 1
11329  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_max, comm%handle, ierr)
11330  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11331  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11332 #else
11333  mark_used(msg)
11334  mark_used(comm)
11335 #endif
11336  CALL mp_timestop(handle)
11337  END SUBROUTINE mp_max_l
11338 
11339 ! **************************************************************************************************
11340 !> \brief Finds the maximum of a datum with the result left on all processes.
11341 !> \param[in,out] msg Find maximum among these data (input) and
11342 !> maximum (output)
11343 !> \param[in] comm Message passing environment identifier
11344 !> \par MPI mapping
11345 !> mpi_allreduce
11346 ! **************************************************************************************************
11347  SUBROUTINE mp_max_root_l (msg, root, comm)
11348  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
11349  INTEGER, INTENT(IN) :: root
11350  CLASS(mp_comm_type), INTENT(IN) :: comm
11351 
11352  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_l'
11353 
11354  INTEGER :: handle
11355 #if defined(__parallel)
11356  INTEGER :: ierr, msglen
11357  INTEGER(KIND=int_8) :: res
11358 #endif
11359 
11360  CALL mp_timeset(routinen, handle)
11361 
11362 #if defined(__parallel)
11363  msglen = 1
11364  CALL mpi_reduce(msg, res, msglen, mpi_integer8, mpi_max, root, comm%handle, ierr)
11365  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
11366  IF (root == comm%mepos) msg = res
11367  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11368 #else
11369  mark_used(msg)
11370  mark_used(comm)
11371  mark_used(root)
11372 #endif
11373  CALL mp_timestop(handle)
11374  END SUBROUTINE mp_max_root_l
11375 
11376 ! **************************************************************************************************
11377 !> \brief Finds the element-wise maximum of a vector with the result left on
11378 !> all processes.
11379 !> \param[in,out] msg Find maximum among these data (input) and
11380 !> maximum (output)
11381 !> \param comm ...
11382 !> \note see mp_max_l
11383 ! **************************************************************************************************
11384  SUBROUTINE mp_max_lv(msg, comm)
11385  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
11386  CLASS(mp_comm_type), INTENT(IN) :: comm
11387 
11388  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_lv'
11389 
11390  INTEGER :: handle
11391 #if defined(__parallel)
11392  INTEGER :: ierr, msglen
11393 #endif
11394 
11395  CALL mp_timeset(routinen, handle)
11396 
11397 #if defined(__parallel)
11398  msglen = SIZE(msg)
11399  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_max, comm%handle, ierr)
11400  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11401  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11402 #else
11403  mark_used(msg)
11404  mark_used(comm)
11405 #endif
11406  CALL mp_timestop(handle)
11407  END SUBROUTINE mp_max_lv
11408 
11409 ! **************************************************************************************************
11410 !> \brief Finds the element-wise maximum of a vector with the result left on
11411 !> all processes.
11412 !> \param[in,out] msg Find maximum among these data (input) and
11413 !> maximum (output)
11414 !> \param comm ...
11415 !> \note see mp_max_l
11416 ! **************************************************************************************************
11417  SUBROUTINE mp_max_root_lm(msg, root, comm)
11418  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
11419  INTEGER :: root
11420  CLASS(mp_comm_type), INTENT(IN) :: comm
11421 
11422  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_lm'
11423 
11424  INTEGER :: handle
11425 #if defined(__parallel)
11426  INTEGER :: ierr, msglen
11427  INTEGER(KIND=int_8) :: res(size(msg, 1), size(msg, 2))
11428 #endif
11429 
11430  CALL mp_timeset(routinen, handle)
11431 
11432 #if defined(__parallel)
11433  msglen = SIZE(msg)
11434  CALL mpi_reduce(msg, res, msglen, mpi_integer8, mpi_max, root, comm%handle, ierr)
11435  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11436  IF (root == comm%mepos) msg = res
11437  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11438 #else
11439  mark_used(msg)
11440  mark_used(comm)
11441  mark_used(root)
11442 #endif
11443  CALL mp_timestop(handle)
11444  END SUBROUTINE mp_max_root_lm
11445 
11446 ! **************************************************************************************************
11447 !> \brief Finds the minimum of a datum with the result left on all processes.
11448 !> \param[in,out] msg Find minimum among these data (input) and
11449 !> maximum (output)
11450 !> \param[in] comm Message passing environment identifier
11451 !> \par MPI mapping
11452 !> mpi_allreduce
11453 ! **************************************************************************************************
11454  SUBROUTINE mp_min_l (msg, comm)
11455  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
11456  CLASS(mp_comm_type), INTENT(IN) :: comm
11457 
11458  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_l'
11459 
11460  INTEGER :: handle
11461 #if defined(__parallel)
11462  INTEGER :: ierr, msglen
11463 #endif
11464 
11465  CALL mp_timeset(routinen, handle)
11466 
11467 #if defined(__parallel)
11468  msglen = 1
11469  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_min, comm%handle, ierr)
11470  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11471  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11472 #else
11473  mark_used(msg)
11474  mark_used(comm)
11475 #endif
11476  CALL mp_timestop(handle)
11477  END SUBROUTINE mp_min_l
11478 
11479 ! **************************************************************************************************
11480 !> \brief Finds the element-wise minimum of vector with the result left on
11481 !> all processes.
11482 !> \param[in,out] msg Find minimum among these data (input) and
11483 !> maximum (output)
11484 !> \param comm ...
11485 !> \par MPI mapping
11486 !> mpi_allreduce
11487 !> \note see mp_min_l
11488 ! **************************************************************************************************
11489  SUBROUTINE mp_min_lv(msg, comm)
11490  INTEGER(KIND=int_8), INTENT(INOUT), CONTIGUOUS :: msg(:)
11491  CLASS(mp_comm_type), INTENT(IN) :: comm
11492 
11493  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_lv'
11494 
11495  INTEGER :: handle
11496 #if defined(__parallel)
11497  INTEGER :: ierr, msglen
11498 #endif
11499 
11500  CALL mp_timeset(routinen, handle)
11501 
11502 #if defined(__parallel)
11503  msglen = SIZE(msg)
11504  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_min, comm%handle, ierr)
11505  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11506  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11507 #else
11508  mark_used(msg)
11509  mark_used(comm)
11510 #endif
11511  CALL mp_timestop(handle)
11512  END SUBROUTINE mp_min_lv
11513 
11514 ! **************************************************************************************************
11515 !> \brief Multiplies a set of numbers scattered across a number of processes,
11516 !> then replicates the result.
11517 !> \param[in,out] msg a number to multiply (input) and result (output)
11518 !> \param[in] comm message passing environment identifier
11519 !> \par MPI mapping
11520 !> mpi_allreduce
11521 ! **************************************************************************************************
11522  SUBROUTINE mp_prod_l (msg, comm)
11523  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
11524  CLASS(mp_comm_type), INTENT(IN) :: comm
11525 
11526  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_l'
11527 
11528  INTEGER :: handle
11529 #if defined(__parallel)
11530  INTEGER :: ierr, msglen
11531 #endif
11532 
11533  CALL mp_timeset(routinen, handle)
11534 
11535 #if defined(__parallel)
11536  msglen = 1
11537  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_integer8, mpi_prod, comm%handle, ierr)
11538  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
11539  CALL add_perf(perf_id=3, count=1, msg_size=msglen*int_8_size)
11540 #else
11541  mark_used(msg)
11542  mark_used(comm)
11543 #endif
11544  CALL mp_timestop(handle)
11545  END SUBROUTINE mp_prod_l
11546 
11547 ! **************************************************************************************************
11548 !> \brief Scatters data from one processes to all others
11549 !> \param[in] msg_scatter Data to scatter (for root process)
11550 !> \param[out] msg Received data
11551 !> \param[in] root Process which scatters data
11552 !> \param[in] comm Message passing environment identifier
11553 !> \par MPI mapping
11554 !> mpi_scatter
11555 ! **************************************************************************************************
11556  SUBROUTINE mp_scatter_lv(msg_scatter, msg, root, comm)
11557  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
11558  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg(:)
11559  INTEGER, INTENT(IN) :: root
11560  CLASS(mp_comm_type), INTENT(IN) :: comm
11561 
11562  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_lv'
11563 
11564  INTEGER :: handle
11565 #if defined(__parallel)
11566  INTEGER :: ierr, msglen
11567 #endif
11568 
11569  CALL mp_timeset(routinen, handle)
11570 
11571 #if defined(__parallel)
11572  msglen = SIZE(msg)
11573  CALL mpi_scatter(msg_scatter, msglen, mpi_integer8, msg, &
11574  msglen, mpi_integer8, root, comm%handle, ierr)
11575  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
11576  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11577 #else
11578  mark_used(root)
11579  mark_used(comm)
11580  msg = msg_scatter
11581 #endif
11582  CALL mp_timestop(handle)
11583  END SUBROUTINE mp_scatter_lv
11584 
11585 ! **************************************************************************************************
11586 !> \brief Scatters data from one processes to all others
11587 !> \param[in] msg_scatter Data to scatter (for root process)
11588 !> \param[in] root Process which scatters data
11589 !> \param[in] comm Message passing environment identifier
11590 !> \par MPI mapping
11591 !> mpi_scatter
11592 ! **************************************************************************************************
11593  SUBROUTINE mp_iscatter_l (msg_scatter, msg, root, comm, request)
11594  INTEGER(KIND=int_8), INTENT(IN) :: msg_scatter(:)
11595  INTEGER(KIND=int_8), INTENT(INOUT) :: msg
11596  INTEGER, INTENT(IN) :: root
11597  CLASS(mp_comm_type), INTENT(IN) :: comm
11598  TYPE(mp_request_type), INTENT(OUT) :: request
11599 
11600  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_l'
11601 
11602  INTEGER :: handle
11603 #if defined(__parallel)
11604  INTEGER :: ierr, msglen
11605 #endif
11606 
11607  CALL mp_timeset(routinen, handle)
11608 
11609 #if defined(__parallel)
11610 #if !defined(__GNUC__) || __GNUC__ >= 9
11611  cpassert(is_contiguous(msg_scatter))
11612 #endif
11613  msglen = 1
11614  CALL mpi_iscatter(msg_scatter, msglen, mpi_integer8, msg, &
11615  msglen, mpi_integer8, root, comm%handle, request%handle, ierr)
11616  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
11617  CALL add_perf(perf_id=24, count=1, msg_size=1*int_8_size)
11618 #else
11619  mark_used(root)
11620  mark_used(comm)
11621  msg = msg_scatter(1)
11622  request = mp_request_null
11623 #endif
11624  CALL mp_timestop(handle)
11625  END SUBROUTINE mp_iscatter_l
11626 
11627 ! **************************************************************************************************
11628 !> \brief Scatters data from one processes to all others
11629 !> \param[in] msg_scatter Data to scatter (for root process)
11630 !> \param[in] root Process which scatters data
11631 !> \param[in] comm Message passing environment identifier
11632 !> \par MPI mapping
11633 !> mpi_scatter
11634 ! **************************************************************************************************
11635  SUBROUTINE mp_iscatter_lv2(msg_scatter, msg, root, comm, request)
11636  INTEGER(KIND=int_8), INTENT(IN) :: msg_scatter(:, :)
11637  INTEGER(KIND=int_8), INTENT(INOUT) :: msg(:)
11638  INTEGER, INTENT(IN) :: root
11639  CLASS(mp_comm_type), INTENT(IN) :: comm
11640  TYPE(mp_request_type), INTENT(OUT) :: request
11641 
11642  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_lv2'
11643 
11644  INTEGER :: handle
11645 #if defined(__parallel)
11646  INTEGER :: ierr, msglen
11647 #endif
11648 
11649  CALL mp_timeset(routinen, handle)
11650 
11651 #if defined(__parallel)
11652 #if !defined(__GNUC__) || __GNUC__ >= 9
11653  cpassert(is_contiguous(msg_scatter))
11654 #endif
11655  msglen = SIZE(msg)
11656  CALL mpi_iscatter(msg_scatter, msglen, mpi_integer8, msg, &
11657  msglen, mpi_integer8, root, comm%handle, request%handle, ierr)
11658  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
11659  CALL add_perf(perf_id=24, count=1, msg_size=1*int_8_size)
11660 #else
11661  mark_used(root)
11662  mark_used(comm)
11663  msg(:) = msg_scatter(:, 1)
11664  request = mp_request_null
11665 #endif
11666  CALL mp_timestop(handle)
11667  END SUBROUTINE mp_iscatter_lv2
11668 
11669 ! **************************************************************************************************
11670 !> \brief Scatters data from one processes to all others
11671 !> \param[in] msg_scatter Data to scatter (for root process)
11672 !> \param[in] root Process which scatters data
11673 !> \param[in] comm Message passing environment identifier
11674 !> \par MPI mapping
11675 !> mpi_scatter
11676 ! **************************************************************************************************
11677  SUBROUTINE mp_iscatterv_lv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
11678  INTEGER(KIND=int_8), INTENT(IN) :: msg_scatter(:)
11679  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
11680  INTEGER(KIND=int_8), INTENT(INOUT) :: msg(:)
11681  INTEGER, INTENT(IN) :: recvcount, root
11682  CLASS(mp_comm_type), INTENT(IN) :: comm
11683  TYPE(mp_request_type), INTENT(OUT) :: request
11684 
11685  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_lv'
11686 
11687  INTEGER :: handle
11688 #if defined(__parallel)
11689  INTEGER :: ierr
11690 #endif
11691 
11692  CALL mp_timeset(routinen, handle)
11693 
11694 #if defined(__parallel)
11695 #if !defined(__GNUC__) || __GNUC__ >= 9
11696  cpassert(is_contiguous(msg_scatter))
11697  cpassert(is_contiguous(msg))
11698  cpassert(is_contiguous(sendcounts))
11699  cpassert(is_contiguous(displs))
11700 #endif
11701  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_integer8, msg, &
11702  recvcount, mpi_integer8, root, comm%handle, request%handle, ierr)
11703  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
11704  CALL add_perf(perf_id=24, count=1, msg_size=1*int_8_size)
11705 #else
11706  mark_used(sendcounts)
11707  mark_used(displs)
11708  mark_used(recvcount)
11709  mark_used(root)
11710  mark_used(comm)
11711  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
11712  request = mp_request_null
11713 #endif
11714  CALL mp_timestop(handle)
11715  END SUBROUTINE mp_iscatterv_lv
11716 
11717 ! **************************************************************************************************
11718 !> \brief Gathers a datum from all processes to one
11719 !> \param[in] msg Datum to send to root
11720 !> \param[out] msg_gather Received data (on root)
11721 !> \param[in] root Process which gathers the data
11722 !> \param[in] comm Message passing environment identifier
11723 !> \par MPI mapping
11724 !> mpi_gather
11725 ! **************************************************************************************************
11726  SUBROUTINE mp_gather_l (msg, msg_gather, root, comm)
11727  INTEGER(KIND=int_8), INTENT(IN) :: msg
11728  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
11729  INTEGER, INTENT(IN) :: root
11730  CLASS(mp_comm_type), INTENT(IN) :: comm
11731 
11732  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_l'
11733 
11734  INTEGER :: handle
11735 #if defined(__parallel)
11736  INTEGER :: ierr, msglen
11737 #endif
11738 
11739  CALL mp_timeset(routinen, handle)
11740 
11741 #if defined(__parallel)
11742  msglen = 1
11743  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11744  msglen, mpi_integer8, root, comm%handle, ierr)
11745  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11746  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11747 #else
11748  mark_used(root)
11749  mark_used(comm)
11750  msg_gather(1) = msg
11751 #endif
11752  CALL mp_timestop(handle)
11753  END SUBROUTINE mp_gather_l
11754 
11755 ! **************************************************************************************************
11756 !> \brief Gathers a datum from all processes to one, uses the source process of comm
11757 !> \param[in] msg Datum to send to root
11758 !> \param[out] msg_gather Received data (on root)
11759 !> \param[in] comm Message passing environment identifier
11760 !> \par MPI mapping
11761 !> mpi_gather
11762 ! **************************************************************************************************
11763  SUBROUTINE mp_gather_l_src(msg, msg_gather, comm)
11764  INTEGER(KIND=int_8), INTENT(IN) :: msg
11765  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
11766  CLASS(mp_comm_type), INTENT(IN) :: comm
11767 
11768  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_l_src'
11769 
11770  INTEGER :: handle
11771 #if defined(__parallel)
11772  INTEGER :: ierr, msglen
11773 #endif
11774 
11775  CALL mp_timeset(routinen, handle)
11776 
11777 #if defined(__parallel)
11778  msglen = 1
11779  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11780  msglen, mpi_integer8, comm%source, comm%handle, ierr)
11781  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11782  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11783 #else
11784  mark_used(comm)
11785  msg_gather(1) = msg
11786 #endif
11787  CALL mp_timestop(handle)
11788  END SUBROUTINE mp_gather_l_src
11789 
11790 ! **************************************************************************************************
11791 !> \brief Gathers data from all processes to one
11792 !> \param[in] msg Datum to send to root
11793 !> \param msg_gather ...
11794 !> \param root ...
11795 !> \param comm ...
11796 !> \par Data length
11797 !> All data (msg) is equal-sized
11798 !> \par MPI mapping
11799 !> mpi_gather
11800 !> \note see mp_gather_l
11801 ! **************************************************************************************************
11802  SUBROUTINE mp_gather_lv(msg, msg_gather, root, comm)
11803  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:)
11804  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
11805  INTEGER, INTENT(IN) :: root
11806  CLASS(mp_comm_type), INTENT(IN) :: comm
11807 
11808  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_lv'
11809 
11810  INTEGER :: handle
11811 #if defined(__parallel)
11812  INTEGER :: ierr, msglen
11813 #endif
11814 
11815  CALL mp_timeset(routinen, handle)
11816 
11817 #if defined(__parallel)
11818  msglen = SIZE(msg)
11819  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11820  msglen, mpi_integer8, root, comm%handle, ierr)
11821  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11822  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11823 #else
11824  mark_used(root)
11825  mark_used(comm)
11826  msg_gather = msg
11827 #endif
11828  CALL mp_timestop(handle)
11829  END SUBROUTINE mp_gather_lv
11830 
11831 ! **************************************************************************************************
11832 !> \brief Gathers data from all processes to one. Gathers from comm%source
11833 !> \param[in] msg Datum to send to root
11834 !> \param msg_gather ...
11835 !> \param comm ...
11836 !> \par Data length
11837 !> All data (msg) is equal-sized
11838 !> \par MPI mapping
11839 !> mpi_gather
11840 !> \note see mp_gather_l
11841 ! **************************************************************************************************
11842  SUBROUTINE mp_gather_lv_src(msg, msg_gather, comm)
11843  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:)
11844  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
11845  CLASS(mp_comm_type), INTENT(IN) :: comm
11846 
11847  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_lv_src'
11848 
11849  INTEGER :: handle
11850 #if defined(__parallel)
11851  INTEGER :: ierr, msglen
11852 #endif
11853 
11854  CALL mp_timeset(routinen, handle)
11855 
11856 #if defined(__parallel)
11857  msglen = SIZE(msg)
11858  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11859  msglen, mpi_integer8, comm%source, comm%handle, ierr)
11860  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11861  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11862 #else
11863  mark_used(comm)
11864  msg_gather = msg
11865 #endif
11866  CALL mp_timestop(handle)
11867  END SUBROUTINE mp_gather_lv_src
11868 
11869 ! **************************************************************************************************
11870 !> \brief Gathers data from all processes to one
11871 !> \param[in] msg Datum to send to root
11872 !> \param msg_gather ...
11873 !> \param root ...
11874 !> \param comm ...
11875 !> \par Data length
11876 !> All data (msg) is equal-sized
11877 !> \par MPI mapping
11878 !> mpi_gather
11879 !> \note see mp_gather_l
11880 ! **************************************************************************************************
11881  SUBROUTINE mp_gather_lm(msg, msg_gather, root, comm)
11882  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
11883  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
11884  INTEGER, INTENT(IN) :: root
11885  CLASS(mp_comm_type), INTENT(IN) :: comm
11886 
11887  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_lm'
11888 
11889  INTEGER :: handle
11890 #if defined(__parallel)
11891  INTEGER :: ierr, msglen
11892 #endif
11893 
11894  CALL mp_timeset(routinen, handle)
11895 
11896 #if defined(__parallel)
11897  msglen = SIZE(msg)
11898  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11899  msglen, mpi_integer8, root, comm%handle, ierr)
11900  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11901  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11902 #else
11903  mark_used(root)
11904  mark_used(comm)
11905  msg_gather = msg
11906 #endif
11907  CALL mp_timestop(handle)
11908  END SUBROUTINE mp_gather_lm
11909 
11910 ! **************************************************************************************************
11911 !> \brief Gathers data from all processes to one. Gathers from comm%source
11912 !> \param[in] msg Datum to send to root
11913 !> \param msg_gather ...
11914 !> \param comm ...
11915 !> \par Data length
11916 !> All data (msg) is equal-sized
11917 !> \par MPI mapping
11918 !> mpi_gather
11919 !> \note see mp_gather_l
11920 ! **************************************************************************************************
11921  SUBROUTINE mp_gather_lm_src(msg, msg_gather, comm)
11922  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
11923  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
11924  CLASS(mp_comm_type), INTENT(IN) :: comm
11925 
11926  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_lm_src'
11927 
11928  INTEGER :: handle
11929 #if defined(__parallel)
11930  INTEGER :: ierr, msglen
11931 #endif
11932 
11933  CALL mp_timeset(routinen, handle)
11934 
11935 #if defined(__parallel)
11936  msglen = SIZE(msg)
11937  CALL mpi_gather(msg, msglen, mpi_integer8, msg_gather, &
11938  msglen, mpi_integer8, comm%source, comm%handle, ierr)
11939  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
11940  CALL add_perf(perf_id=4, count=1, msg_size=msglen*int_8_size)
11941 #else
11942  mark_used(comm)
11943  msg_gather = msg
11944 #endif
11945  CALL mp_timestop(handle)
11946  END SUBROUTINE mp_gather_lm_src
11947 
11948 ! **************************************************************************************************
11949 !> \brief Gathers data from all processes to one.
11950 !> \param[in] sendbuf Data to send to root
11951 !> \param[out] recvbuf Received data (on root)
11952 !> \param[in] recvcounts Sizes of data received from processes
11953 !> \param[in] displs Offsets of data received from processes
11954 !> \param[in] root Process which gathers the data
11955 !> \param[in] comm Message passing environment identifier
11956 !> \par Data length
11957 !> Data can have different lengths
11958 !> \par Offsets
11959 !> Offsets start at 0
11960 !> \par MPI mapping
11961 !> mpi_gather
11962 ! **************************************************************************************************
11963  SUBROUTINE mp_gatherv_lv(sendbuf, recvbuf, recvcounts, displs, root, comm)
11964 
11965  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
11966  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
11967  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
11968  INTEGER, INTENT(IN) :: root
11969  CLASS(mp_comm_type), INTENT(IN) :: comm
11970 
11971  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_lv'
11972 
11973  INTEGER :: handle
11974 #if defined(__parallel)
11975  INTEGER :: ierr, sendcount
11976 #endif
11977 
11978  CALL mp_timeset(routinen, handle)
11979 
11980 #if defined(__parallel)
11981  sendcount = SIZE(sendbuf)
11982  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer8, &
11983  recvbuf, recvcounts, displs, mpi_integer8, &
11984  root, comm%handle, ierr)
11985  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
11986  CALL add_perf(perf_id=4, &
11987  count=1, &
11988  msg_size=sendcount*int_8_size)
11989 #else
11990  mark_used(recvcounts)
11991  mark_used(root)
11992  mark_used(comm)
11993  recvbuf(1 + displs(1):) = sendbuf
11994 #endif
11995  CALL mp_timestop(handle)
11996  END SUBROUTINE mp_gatherv_lv
11997 
11998 ! **************************************************************************************************
11999 !> \brief Gathers data from all processes to one. Gathers from comm%source
12000 !> \param[in] sendbuf Data to send to root
12001 !> \param[out] recvbuf Received data (on root)
12002 !> \param[in] recvcounts Sizes of data received from processes
12003 !> \param[in] displs Offsets of data received from processes
12004 !> \param[in] comm Message passing environment identifier
12005 !> \par Data length
12006 !> Data can have different lengths
12007 !> \par Offsets
12008 !> Offsets start at 0
12009 !> \par MPI mapping
12010 !> mpi_gather
12011 ! **************************************************************************************************
12012  SUBROUTINE mp_gatherv_lv_src(sendbuf, recvbuf, recvcounts, displs, comm)
12013 
12014  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
12015  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
12016  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
12017  CLASS(mp_comm_type), INTENT(IN) :: comm
12018 
12019  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_lv_src'
12020 
12021  INTEGER :: handle
12022 #if defined(__parallel)
12023  INTEGER :: ierr, sendcount
12024 #endif
12025 
12026  CALL mp_timeset(routinen, handle)
12027 
12028 #if defined(__parallel)
12029  sendcount = SIZE(sendbuf)
12030  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer8, &
12031  recvbuf, recvcounts, displs, mpi_integer8, &
12032  comm%source, comm%handle, ierr)
12033  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
12034  CALL add_perf(perf_id=4, &
12035  count=1, &
12036  msg_size=sendcount*int_8_size)
12037 #else
12038  mark_used(recvcounts)
12039  mark_used(comm)
12040  recvbuf(1 + displs(1):) = sendbuf
12041 #endif
12042  CALL mp_timestop(handle)
12043  END SUBROUTINE mp_gatherv_lv_src
12044 
12045 ! **************************************************************************************************
12046 !> \brief Gathers data from all processes to one.
12047 !> \param[in] sendbuf Data to send to root
12048 !> \param[out] recvbuf Received data (on root)
12049 !> \param[in] recvcounts Sizes of data received from processes
12050 !> \param[in] displs Offsets of data received from processes
12051 !> \param[in] root Process which gathers the data
12052 !> \param[in] comm Message passing environment identifier
12053 !> \par Data length
12054 !> Data can have different lengths
12055 !> \par Offsets
12056 !> Offsets start at 0
12057 !> \par MPI mapping
12058 !> mpi_gather
12059 ! **************************************************************************************************
12060  SUBROUTINE mp_gatherv_lm2(sendbuf, recvbuf, recvcounts, displs, root, comm)
12061 
12062  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
12063  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
12064  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
12065  INTEGER, INTENT(IN) :: root
12066  CLASS(mp_comm_type), INTENT(IN) :: comm
12067 
12068  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_lm2'
12069 
12070  INTEGER :: handle
12071 #if defined(__parallel)
12072  INTEGER :: ierr, sendcount
12073 #endif
12074 
12075  CALL mp_timeset(routinen, handle)
12076 
12077 #if defined(__parallel)
12078  sendcount = SIZE(sendbuf)
12079  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer8, &
12080  recvbuf, recvcounts, displs, mpi_integer8, &
12081  root, comm%handle, ierr)
12082  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
12083  CALL add_perf(perf_id=4, &
12084  count=1, &
12085  msg_size=sendcount*int_8_size)
12086 #else
12087  mark_used(recvcounts)
12088  mark_used(root)
12089  mark_used(comm)
12090  recvbuf(:, 1 + displs(1):) = sendbuf
12091 #endif
12092  CALL mp_timestop(handle)
12093  END SUBROUTINE mp_gatherv_lm2
12094 
12095 ! **************************************************************************************************
12096 !> \brief Gathers data from all processes to one.
12097 !> \param[in] sendbuf Data to send to root
12098 !> \param[out] recvbuf Received data (on root)
12099 !> \param[in] recvcounts Sizes of data received from processes
12100 !> \param[in] displs Offsets of data received from processes
12101 !> \param[in] comm Message passing environment identifier
12102 !> \par Data length
12103 !> Data can have different lengths
12104 !> \par Offsets
12105 !> Offsets start at 0
12106 !> \par MPI mapping
12107 !> mpi_gather
12108 ! **************************************************************************************************
12109  SUBROUTINE mp_gatherv_lm2_src(sendbuf, recvbuf, recvcounts, displs, comm)
12110 
12111  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
12112  INTEGER(KIND=int_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
12113  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
12114  CLASS(mp_comm_type), INTENT(IN) :: comm
12115 
12116  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_lm2_src'
12117 
12118  INTEGER :: handle
12119 #if defined(__parallel)
12120  INTEGER :: ierr, sendcount
12121 #endif
12122 
12123  CALL mp_timeset(routinen, handle)
12124 
12125 #if defined(__parallel)
12126  sendcount = SIZE(sendbuf)
12127  CALL mpi_gatherv(sendbuf, sendcount, mpi_integer8, &
12128  recvbuf, recvcounts, displs, mpi_integer8, &
12129  comm%source, comm%handle, ierr)
12130  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
12131  CALL add_perf(perf_id=4, &
12132  count=1, &
12133  msg_size=sendcount*int_8_size)
12134 #else
12135  mark_used(recvcounts)
12136  mark_used(comm)
12137  recvbuf(:, 1 + displs(1):) = sendbuf
12138 #endif
12139  CALL mp_timestop(handle)
12140  END SUBROUTINE mp_gatherv_lm2_src
12141 
12142 ! **************************************************************************************************
12143 !> \brief Gathers data from all processes to one.
12144 !> \param[in] sendbuf Data to send to root
12145 !> \param[out] recvbuf Received data (on root)
12146 !> \param[in] recvcounts Sizes of data received from processes
12147 !> \param[in] displs Offsets of data received from processes
12148 !> \param[in] root Process which gathers the data
12149 !> \param[in] comm Message passing environment identifier
12150 !> \par Data length
12151 !> Data can have different lengths
12152 !> \par Offsets
12153 !> Offsets start at 0
12154 !> \par MPI mapping
12155 !> mpi_gather
12156 ! **************************************************************************************************
12157  SUBROUTINE mp_igatherv_lv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
12158  INTEGER(KIND=int_8), DIMENSION(:), INTENT(IN) :: sendbuf
12159  INTEGER(KIND=int_8), DIMENSION(:), INTENT(OUT) :: recvbuf
12160  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
12161  INTEGER, INTENT(IN) :: sendcount, root
12162  CLASS(mp_comm_type), INTENT(IN) :: comm
12163  TYPE(mp_request_type), INTENT(OUT) :: request
12164 
12165  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_lv'
12166 
12167  INTEGER :: handle
12168 #if defined(__parallel)
12169  INTEGER :: ierr
12170 #endif
12171 
12172  CALL mp_timeset(routinen, handle)
12173 
12174 #if defined(__parallel)
12175 #if !defined(__GNUC__) || __GNUC__ >= 9
12176  cpassert(is_contiguous(sendbuf))
12177  cpassert(is_contiguous(recvbuf))
12178  cpassert(is_contiguous(recvcounts))
12179  cpassert(is_contiguous(displs))
12180 #endif
12181  CALL mpi_igatherv(sendbuf, sendcount, mpi_integer8, &
12182  recvbuf, recvcounts, displs, mpi_integer8, &
12183  root, comm%handle, request%handle, ierr)
12184  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
12185  CALL add_perf(perf_id=24, &
12186  count=1, &
12187  msg_size=sendcount*int_8_size)
12188 #else
12189  mark_used(sendcount)
12190  mark_used(recvcounts)
12191  mark_used(root)
12192  mark_used(comm)
12193  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
12194  request = mp_request_null
12195 #endif
12196  CALL mp_timestop(handle)
12197  END SUBROUTINE mp_igatherv_lv
12198 
12199 ! **************************************************************************************************
12200 !> \brief Gathers a datum from all processes and all processes receive the
12201 !> same data
12202 !> \param[in] msgout Datum to send
12203 !> \param[out] msgin Received data
12204 !> \param[in] comm Message passing environment identifier
12205 !> \par Data size
12206 !> All processes send equal-sized data
12207 !> \par MPI mapping
12208 !> mpi_allgather
12209 ! **************************************************************************************************
12210  SUBROUTINE mp_allgather_l (msgout, msgin, comm)
12211  INTEGER(KIND=int_8), INTENT(IN) :: msgout
12212  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:)
12213  CLASS(mp_comm_type), INTENT(IN) :: comm
12214 
12215  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l'
12216 
12217  INTEGER :: handle
12218 #if defined(__parallel)
12219  INTEGER :: ierr, rcount, scount
12220 #endif
12221 
12222  CALL mp_timeset(routinen, handle)
12223 
12224 #if defined(__parallel)
12225  scount = 1
12226  rcount = 1
12227  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12228  msgin, rcount, mpi_integer8, &
12229  comm%handle, ierr)
12230  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12231 #else
12232  mark_used(comm)
12233  msgin = msgout
12234 #endif
12235  CALL mp_timestop(handle)
12236  END SUBROUTINE mp_allgather_l
12237 
12238 ! **************************************************************************************************
12239 !> \brief Gathers a datum from all processes and all processes receive the
12240 !> same data
12241 !> \param[in] msgout Datum to send
12242 !> \param[out] msgin Received data
12243 !> \param[in] comm Message passing environment identifier
12244 !> \par Data size
12245 !> All processes send equal-sized data
12246 !> \par MPI mapping
12247 !> mpi_allgather
12248 ! **************************************************************************************************
12249  SUBROUTINE mp_allgather_l2(msgout, msgin, comm)
12250  INTEGER(KIND=int_8), INTENT(IN) :: msgout
12251  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
12252  CLASS(mp_comm_type), INTENT(IN) :: comm
12253 
12254  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l2'
12255 
12256  INTEGER :: handle
12257 #if defined(__parallel)
12258  INTEGER :: ierr, rcount, scount
12259 #endif
12260 
12261  CALL mp_timeset(routinen, handle)
12262 
12263 #if defined(__parallel)
12264  scount = 1
12265  rcount = 1
12266  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12267  msgin, rcount, mpi_integer8, &
12268  comm%handle, ierr)
12269  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12270 #else
12271  mark_used(comm)
12272  msgin = msgout
12273 #endif
12274  CALL mp_timestop(handle)
12275  END SUBROUTINE mp_allgather_l2
12276 
12277 ! **************************************************************************************************
12278 !> \brief Gathers a datum from all processes and all processes receive the
12279 !> same data
12280 !> \param[in] msgout Datum to send
12281 !> \param[out] msgin Received data
12282 !> \param[in] comm Message passing environment identifier
12283 !> \par Data size
12284 !> All processes send equal-sized data
12285 !> \par MPI mapping
12286 !> mpi_allgather
12287 ! **************************************************************************************************
12288  SUBROUTINE mp_iallgather_l (msgout, msgin, comm, request)
12289  INTEGER(KIND=int_8), INTENT(IN) :: msgout
12290  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:)
12291  CLASS(mp_comm_type), INTENT(IN) :: comm
12292  TYPE(mp_request_type), INTENT(OUT) :: request
12293 
12294  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l'
12295 
12296  INTEGER :: handle
12297 #if defined(__parallel)
12298  INTEGER :: ierr, rcount, scount
12299 #endif
12300 
12301  CALL mp_timeset(routinen, handle)
12302 
12303 #if defined(__parallel)
12304 #if !defined(__GNUC__) || __GNUC__ >= 9
12305  cpassert(is_contiguous(msgin))
12306 #endif
12307  scount = 1
12308  rcount = 1
12309  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12310  msgin, rcount, mpi_integer8, &
12311  comm%handle, request%handle, ierr)
12312  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12313 #else
12314  mark_used(comm)
12315  msgin = msgout
12316  request = mp_request_null
12317 #endif
12318  CALL mp_timestop(handle)
12319  END SUBROUTINE mp_iallgather_l
12320 
12321 ! **************************************************************************************************
12322 !> \brief Gathers vector data from all processes and all processes receive the
12323 !> same data
12324 !> \param[in] msgout Rank-1 data to send
12325 !> \param[out] msgin Received data
12326 !> \param[in] comm Message passing environment identifier
12327 !> \par Data size
12328 !> All processes send equal-sized data
12329 !> \par Ranks
12330 !> The last rank counts the processes
12331 !> \par MPI mapping
12332 !> mpi_allgather
12333 ! **************************************************************************************************
12334  SUBROUTINE mp_allgather_l12(msgout, msgin, comm)
12335  INTEGER(KIND=int_8), INTENT(IN), CONTIGUOUS :: msgout(:)
12336  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
12337  CLASS(mp_comm_type), INTENT(IN) :: comm
12338 
12339  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l12'
12340 
12341  INTEGER :: handle
12342 #if defined(__parallel)
12343  INTEGER :: ierr, rcount, scount
12344 #endif
12345 
12346  CALL mp_timeset(routinen, handle)
12347 
12348 #if defined(__parallel)
12349  scount = SIZE(msgout(:))
12350  rcount = scount
12351  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12352  msgin, rcount, mpi_integer8, &
12353  comm%handle, ierr)
12354  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12355 #else
12356  mark_used(comm)
12357  msgin(:, 1) = msgout(:)
12358 #endif
12359  CALL mp_timestop(handle)
12360  END SUBROUTINE mp_allgather_l12
12361 
12362 ! **************************************************************************************************
12363 !> \brief Gathers matrix data from all processes and all processes receive the
12364 !> same data
12365 !> \param[in] msgout Rank-2 data to send
12366 !> \param msgin ...
12367 !> \param comm ...
12368 !> \note see mp_allgather_l12
12369 ! **************************************************************************************************
12370  SUBROUTINE mp_allgather_l23(msgout, msgin, comm)
12371  INTEGER(KIND=int_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
12372  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
12373  CLASS(mp_comm_type), INTENT(IN) :: comm
12374 
12375  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l23'
12376 
12377  INTEGER :: handle
12378 #if defined(__parallel)
12379  INTEGER :: ierr, rcount, scount
12380 #endif
12381 
12382  CALL mp_timeset(routinen, handle)
12383 
12384 #if defined(__parallel)
12385  scount = SIZE(msgout(:, :))
12386  rcount = scount
12387  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12388  msgin, rcount, mpi_integer8, &
12389  comm%handle, ierr)
12390  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12391 #else
12392  mark_used(comm)
12393  msgin(:, :, 1) = msgout(:, :)
12394 #endif
12395  CALL mp_timestop(handle)
12396  END SUBROUTINE mp_allgather_l23
12397 
12398 ! **************************************************************************************************
12399 !> \brief Gathers rank-3 data from all processes and all processes receive the
12400 !> same data
12401 !> \param[in] msgout Rank-3 data to send
12402 !> \param msgin ...
12403 !> \param comm ...
12404 !> \note see mp_allgather_l12
12405 ! **************************************************************************************************
12406  SUBROUTINE mp_allgather_l34(msgout, msgin, comm)
12407  INTEGER(KIND=int_8), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
12408  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
12409  CLASS(mp_comm_type), INTENT(IN) :: comm
12410 
12411  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l34'
12412 
12413  INTEGER :: handle
12414 #if defined(__parallel)
12415  INTEGER :: ierr, rcount, scount
12416 #endif
12417 
12418  CALL mp_timeset(routinen, handle)
12419 
12420 #if defined(__parallel)
12421  scount = SIZE(msgout(:, :, :))
12422  rcount = scount
12423  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12424  msgin, rcount, mpi_integer8, &
12425  comm%handle, ierr)
12426  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12427 #else
12428  mark_used(comm)
12429  msgin(:, :, :, 1) = msgout(:, :, :)
12430 #endif
12431  CALL mp_timestop(handle)
12432  END SUBROUTINE mp_allgather_l34
12433 
12434 ! **************************************************************************************************
12435 !> \brief Gathers rank-2 data from all processes and all processes receive the
12436 !> same data
12437 !> \param[in] msgout Rank-2 data to send
12438 !> \param msgin ...
12439 !> \param comm ...
12440 !> \note see mp_allgather_l12
12441 ! **************************************************************************************************
12442  SUBROUTINE mp_allgather_l22(msgout, msgin, comm)
12443  INTEGER(KIND=int_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
12444  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
12445  CLASS(mp_comm_type), INTENT(IN) :: comm
12446 
12447  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_l22'
12448 
12449  INTEGER :: handle
12450 #if defined(__parallel)
12451  INTEGER :: ierr, rcount, scount
12452 #endif
12453 
12454  CALL mp_timeset(routinen, handle)
12455 
12456 #if defined(__parallel)
12457  scount = SIZE(msgout(:, :))
12458  rcount = scount
12459  CALL mpi_allgather(msgout, scount, mpi_integer8, &
12460  msgin, rcount, mpi_integer8, &
12461  comm%handle, ierr)
12462  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
12463 #else
12464  mark_used(comm)
12465  msgin(:, :) = msgout(:, :)
12466 #endif
12467  CALL mp_timestop(handle)
12468  END SUBROUTINE mp_allgather_l22
12469 
12470 ! **************************************************************************************************
12471 !> \brief Gathers rank-1 data from all processes and all processes receive the
12472 !> same data
12473 !> \param[in] msgout Rank-1 data to send
12474 !> \param msgin ...
12475 !> \param comm ...
12476 !> \param request ...
12477 !> \note see mp_allgather_l11
12478 ! **************************************************************************************************
12479  SUBROUTINE mp_iallgather_l11(msgout, msgin, comm, request)
12480  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:)
12481  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:)
12482  CLASS(mp_comm_type), INTENT(IN) :: comm
12483  TYPE(mp_request_type), INTENT(OUT) :: request
12484 
12485  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l11'
12486 
12487  INTEGER :: handle
12488 #if defined(__parallel)
12489  INTEGER :: ierr, rcount, scount
12490 #endif
12491 
12492  CALL mp_timeset(routinen, handle)
12493 
12494 #if defined(__parallel)
12495 #if !defined(__GNUC__) || __GNUC__ >= 9
12496  cpassert(is_contiguous(msgout))
12497  cpassert(is_contiguous(msgin))
12498 #endif
12499  scount = SIZE(msgout(:))
12500  rcount = scount
12501  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12502  msgin, rcount, mpi_integer8, &
12503  comm%handle, request%handle, ierr)
12504  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
12505 #else
12506  mark_used(comm)
12507  msgin = msgout
12508  request = mp_request_null
12509 #endif
12510  CALL mp_timestop(handle)
12511  END SUBROUTINE mp_iallgather_l11
12512 
12513 ! **************************************************************************************************
12514 !> \brief Gathers rank-2 data from all processes and all processes receive the
12515 !> same data
12516 !> \param[in] msgout Rank-2 data to send
12517 !> \param msgin ...
12518 !> \param comm ...
12519 !> \param request ...
12520 !> \note see mp_allgather_l12
12521 ! **************************************************************************************************
12522  SUBROUTINE mp_iallgather_l13(msgout, msgin, comm, request)
12523  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:)
12524  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:, :, :)
12525  CLASS(mp_comm_type), INTENT(IN) :: comm
12526  TYPE(mp_request_type), INTENT(OUT) :: request
12527 
12528  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l13'
12529 
12530  INTEGER :: handle
12531 #if defined(__parallel)
12532  INTEGER :: ierr, rcount, scount
12533 #endif
12534 
12535  CALL mp_timeset(routinen, handle)
12536 
12537 #if defined(__parallel)
12538 #if !defined(__GNUC__) || __GNUC__ >= 9
12539  cpassert(is_contiguous(msgout))
12540  cpassert(is_contiguous(msgin))
12541 #endif
12542 
12543  scount = SIZE(msgout(:))
12544  rcount = scount
12545  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12546  msgin, rcount, mpi_integer8, &
12547  comm%handle, request%handle, ierr)
12548  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
12549 #else
12550  mark_used(comm)
12551  msgin(:, 1, 1) = msgout(:)
12552  request = mp_request_null
12553 #endif
12554  CALL mp_timestop(handle)
12555  END SUBROUTINE mp_iallgather_l13
12556 
12557 ! **************************************************************************************************
12558 !> \brief Gathers rank-2 data from all processes and all processes receive the
12559 !> same data
12560 !> \param[in] msgout Rank-2 data to send
12561 !> \param msgin ...
12562 !> \param comm ...
12563 !> \param request ...
12564 !> \note see mp_allgather_l12
12565 ! **************************************************************************************************
12566  SUBROUTINE mp_iallgather_l22(msgout, msgin, comm, request)
12567  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:, :)
12568  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:, :)
12569  CLASS(mp_comm_type), INTENT(IN) :: comm
12570  TYPE(mp_request_type), INTENT(OUT) :: request
12571 
12572  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l22'
12573 
12574  INTEGER :: handle
12575 #if defined(__parallel)
12576  INTEGER :: ierr, rcount, scount
12577 #endif
12578 
12579  CALL mp_timeset(routinen, handle)
12580 
12581 #if defined(__parallel)
12582 #if !defined(__GNUC__) || __GNUC__ >= 9
12583  cpassert(is_contiguous(msgout))
12584  cpassert(is_contiguous(msgin))
12585 #endif
12586 
12587  scount = SIZE(msgout(:, :))
12588  rcount = scount
12589  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12590  msgin, rcount, mpi_integer8, &
12591  comm%handle, request%handle, ierr)
12592  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
12593 #else
12594  mark_used(comm)
12595  msgin(:, :) = msgout(:, :)
12596  request = mp_request_null
12597 #endif
12598  CALL mp_timestop(handle)
12599  END SUBROUTINE mp_iallgather_l22
12600 
12601 ! **************************************************************************************************
12602 !> \brief Gathers rank-2 data from all processes and all processes receive the
12603 !> same data
12604 !> \param[in] msgout Rank-2 data to send
12605 !> \param msgin ...
12606 !> \param comm ...
12607 !> \param request ...
12608 !> \note see mp_allgather_l12
12609 ! **************************************************************************************************
12610  SUBROUTINE mp_iallgather_l24(msgout, msgin, comm, request)
12611  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:, :)
12612  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:, :, :, :)
12613  CLASS(mp_comm_type), INTENT(IN) :: comm
12614  TYPE(mp_request_type), INTENT(OUT) :: request
12615 
12616  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l24'
12617 
12618  INTEGER :: handle
12619 #if defined(__parallel)
12620  INTEGER :: ierr, rcount, scount
12621 #endif
12622 
12623  CALL mp_timeset(routinen, handle)
12624 
12625 #if defined(__parallel)
12626 #if !defined(__GNUC__) || __GNUC__ >= 9
12627  cpassert(is_contiguous(msgout))
12628  cpassert(is_contiguous(msgin))
12629 #endif
12630 
12631  scount = SIZE(msgout(:, :))
12632  rcount = scount
12633  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12634  msgin, rcount, mpi_integer8, &
12635  comm%handle, request%handle, ierr)
12636  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
12637 #else
12638  mark_used(comm)
12639  msgin(:, :, 1, 1) = msgout(:, :)
12640  request = mp_request_null
12641 #endif
12642  CALL mp_timestop(handle)
12643  END SUBROUTINE mp_iallgather_l24
12644 
12645 ! **************************************************************************************************
12646 !> \brief Gathers rank-3 data from all processes and all processes receive the
12647 !> same data
12648 !> \param[in] msgout Rank-3 data to send
12649 !> \param msgin ...
12650 !> \param comm ...
12651 !> \param request ...
12652 !> \note see mp_allgather_l12
12653 ! **************************************************************************************************
12654  SUBROUTINE mp_iallgather_l33(msgout, msgin, comm, request)
12655  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:, :, :)
12656  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:, :, :)
12657  CLASS(mp_comm_type), INTENT(IN) :: comm
12658  TYPE(mp_request_type), INTENT(OUT) :: request
12659 
12660  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_l33'
12661 
12662  INTEGER :: handle
12663 #if defined(__parallel)
12664  INTEGER :: ierr, rcount, scount
12665 #endif
12666 
12667  CALL mp_timeset(routinen, handle)
12668 
12669 #if defined(__parallel)
12670 #if !defined(__GNUC__) || __GNUC__ >= 9
12671  cpassert(is_contiguous(msgout))
12672  cpassert(is_contiguous(msgin))
12673 #endif
12674 
12675  scount = SIZE(msgout(:, :, :))
12676  rcount = scount
12677  CALL mpi_iallgather(msgout, scount, mpi_integer8, &
12678  msgin, rcount, mpi_integer8, &
12679  comm%handle, request%handle, ierr)
12680  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
12681 #else
12682  mark_used(comm)
12683  msgin(:, :, :) = msgout(:, :, :)
12684  request = mp_request_null
12685 #endif
12686  CALL mp_timestop(handle)
12687  END SUBROUTINE mp_iallgather_l33
12688 
12689 ! **************************************************************************************************
12690 !> \brief Gathers vector data from all processes and all processes receive the
12691 !> same data
12692 !> \param[in] msgout Rank-1 data to send
12693 !> \param[out] msgin Received data
12694 !> \param[in] rcount Size of sent data for every process
12695 !> \param[in] rdispl Offset of sent data for every process
12696 !> \param[in] comm Message passing environment identifier
12697 !> \par Data size
12698 !> Processes can send different-sized data
12699 !> \par Ranks
12700 !> The last rank counts the processes
12701 !> \par Offsets
12702 !> Offsets are from 0
12703 !> \par MPI mapping
12704 !> mpi_allgather
12705 ! **************************************************************************************************
12706  SUBROUTINE mp_allgatherv_lv(msgout, msgin, rcount, rdispl, comm)
12707  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
12708  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
12709  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
12710  CLASS(mp_comm_type), INTENT(IN) :: comm
12711 
12712  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_lv'
12713 
12714  INTEGER :: handle
12715 #if defined(__parallel)
12716  INTEGER :: ierr, scount
12717 #endif
12718 
12719  CALL mp_timeset(routinen, handle)
12720 
12721 #if defined(__parallel)
12722  scount = SIZE(msgout)
12723  CALL mpi_allgatherv(msgout, scount, mpi_integer8, msgin, rcount, &
12724  rdispl, mpi_integer8, comm%handle, ierr)
12725  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
12726 #else
12727  mark_used(rcount)
12728  mark_used(rdispl)
12729  mark_used(comm)
12730  msgin = msgout
12731 #endif
12732  CALL mp_timestop(handle)
12733  END SUBROUTINE mp_allgatherv_lv
12734 
12735 ! **************************************************************************************************
12736 !> \brief Gathers vector data from all processes and all processes receive the
12737 !> same data
12738 !> \param[in] msgout Rank-1 data to send
12739 !> \param[out] msgin Received data
12740 !> \param[in] rcount Size of sent data for every process
12741 !> \param[in] rdispl Offset of sent data for every process
12742 !> \param[in] comm Message passing environment identifier
12743 !> \par Data size
12744 !> Processes can send different-sized data
12745 !> \par Ranks
12746 !> The last rank counts the processes
12747 !> \par Offsets
12748 !> Offsets are from 0
12749 !> \par MPI mapping
12750 !> mpi_allgather
12751 ! **************************************************************************************************
12752  SUBROUTINE mp_allgatherv_lm2(msgout, msgin, rcount, rdispl, comm)
12753  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
12754  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
12755  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
12756  CLASS(mp_comm_type), INTENT(IN) :: comm
12757 
12758  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_lv'
12759 
12760  INTEGER :: handle
12761 #if defined(__parallel)
12762  INTEGER :: ierr, scount
12763 #endif
12764 
12765  CALL mp_timeset(routinen, handle)
12766 
12767 #if defined(__parallel)
12768  scount = SIZE(msgout)
12769  CALL mpi_allgatherv(msgout, scount, mpi_integer8, msgin, rcount, &
12770  rdispl, mpi_integer8, comm%handle, ierr)
12771  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
12772 #else
12773  mark_used(rcount)
12774  mark_used(rdispl)
12775  mark_used(comm)
12776  msgin = msgout
12777 #endif
12778  CALL mp_timestop(handle)
12779  END SUBROUTINE mp_allgatherv_lm2
12780 
12781 ! **************************************************************************************************
12782 !> \brief Gathers vector data from all processes and all processes receive the
12783 !> same data
12784 !> \param[in] msgout Rank-1 data to send
12785 !> \param[out] msgin Received data
12786 !> \param[in] rcount Size of sent data for every process
12787 !> \param[in] rdispl Offset of sent data for every process
12788 !> \param[in] comm Message passing environment identifier
12789 !> \par Data size
12790 !> Processes can send different-sized data
12791 !> \par Ranks
12792 !> The last rank counts the processes
12793 !> \par Offsets
12794 !> Offsets are from 0
12795 !> \par MPI mapping
12796 !> mpi_allgather
12797 ! **************************************************************************************************
12798  SUBROUTINE mp_iallgatherv_lv(msgout, msgin, rcount, rdispl, comm, request)
12799  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:)
12800  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:)
12801  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
12802  CLASS(mp_comm_type), INTENT(IN) :: comm
12803  TYPE(mp_request_type), INTENT(OUT) :: request
12804 
12805  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_lv'
12806 
12807  INTEGER :: handle
12808 #if defined(__parallel)
12809  INTEGER :: ierr, scount, rsize
12810 #endif
12811 
12812  CALL mp_timeset(routinen, handle)
12813 
12814 #if defined(__parallel)
12815 #if !defined(__GNUC__) || __GNUC__ >= 9
12816  cpassert(is_contiguous(msgout))
12817  cpassert(is_contiguous(msgin))
12818  cpassert(is_contiguous(rcount))
12819  cpassert(is_contiguous(rdispl))
12820 #endif
12821 
12822  scount = SIZE(msgout)
12823  rsize = SIZE(rcount)
12824  CALL mp_iallgatherv_lv_internal(msgout, scount, msgin, rsize, rcount, &
12825  rdispl, comm, request, ierr)
12826  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
12827 #else
12828  mark_used(rcount)
12829  mark_used(rdispl)
12830  mark_used(comm)
12831  msgin = msgout
12832  request = mp_request_null
12833 #endif
12834  CALL mp_timestop(handle)
12835  END SUBROUTINE mp_iallgatherv_lv
12836 
12837 ! **************************************************************************************************
12838 !> \brief Gathers vector data from all processes and all processes receive the
12839 !> same data
12840 !> \param[in] msgout Rank-1 data to send
12841 !> \param[out] msgin Received data
12842 !> \param[in] rcount Size of sent data for every process
12843 !> \param[in] rdispl Offset of sent data for every process
12844 !> \param[in] comm Message passing environment identifier
12845 !> \par Data size
12846 !> Processes can send different-sized data
12847 !> \par Ranks
12848 !> The last rank counts the processes
12849 !> \par Offsets
12850 !> Offsets are from 0
12851 !> \par MPI mapping
12852 !> mpi_allgather
12853 ! **************************************************************************************************
12854  SUBROUTINE mp_iallgatherv_lv2(msgout, msgin, rcount, rdispl, comm, request)
12855  INTEGER(KIND=int_8), INTENT(IN) :: msgout(:)
12856  INTEGER(KIND=int_8), INTENT(OUT) :: msgin(:)
12857  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
12858  CLASS(mp_comm_type), INTENT(IN) :: comm
12859  TYPE(mp_request_type), INTENT(OUT) :: request
12860 
12861  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_lv2'
12862 
12863  INTEGER :: handle
12864 #if defined(__parallel)
12865  INTEGER :: ierr, scount, rsize
12866 #endif
12867 
12868  CALL mp_timeset(routinen, handle)
12869 
12870 #if defined(__parallel)
12871 #if !defined(__GNUC__) || __GNUC__ >= 9
12872  cpassert(is_contiguous(msgout))
12873  cpassert(is_contiguous(msgin))
12874  cpassert(is_contiguous(rcount))
12875  cpassert(is_contiguous(rdispl))
12876 #endif
12877 
12878  scount = SIZE(msgout)
12879  rsize = SIZE(rcount)
12880  CALL mp_iallgatherv_lv_internal(msgout, scount, msgin, rsize, rcount, &
12881  rdispl, comm, request, ierr)
12882  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
12883 #else
12884  mark_used(rcount)
12885  mark_used(rdispl)
12886  mark_used(comm)
12887  msgin = msgout
12888  request = mp_request_null
12889 #endif
12890  CALL mp_timestop(handle)
12891  END SUBROUTINE mp_iallgatherv_lv2
12892 
12893 ! **************************************************************************************************
12894 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
12895 !> the issue is with the rank of rcount and rdispl
12896 !> \param count ...
12897 !> \param array_of_requests ...
12898 !> \param array_of_statuses ...
12899 !> \param ierr ...
12900 !> \author Alfio Lazzaro
12901 ! **************************************************************************************************
12902 #if defined(__parallel)
12903  SUBROUTINE mp_iallgatherv_lv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
12904  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
12905  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
12906  INTEGER, INTENT(IN) :: rsize
12907  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
12908  CLASS(mp_comm_type), INTENT(IN) :: comm
12909  TYPE(mp_request_type), INTENT(OUT) :: request
12910  INTEGER, INTENT(INOUT) :: ierr
12911 
12912  CALL mpi_iallgatherv(msgout, scount, mpi_integer8, msgin, rcount, &
12913  rdispl, mpi_integer8, comm%handle, request%handle, ierr)
12914 
12915  END SUBROUTINE mp_iallgatherv_lv_internal
12916 #endif
12917 
12918 ! **************************************************************************************************
12919 !> \brief Sums a vector and partitions the result among processes
12920 !> \param[in] msgout Data to sum
12921 !> \param[out] msgin Received portion of summed data
12922 !> \param[in] rcount Partition sizes of the summed data for
12923 !> every process
12924 !> \param[in] comm Message passing environment identifier
12925 ! **************************************************************************************************
12926  SUBROUTINE mp_sum_scatter_lv(msgout, msgin, rcount, comm)
12927  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
12928  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
12929  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
12930  CLASS(mp_comm_type), INTENT(IN) :: comm
12931 
12932  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_lv'
12933 
12934  INTEGER :: handle
12935 #if defined(__parallel)
12936  INTEGER :: ierr
12937 #endif
12938 
12939  CALL mp_timeset(routinen, handle)
12940 
12941 #if defined(__parallel)
12942  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_integer8, mpi_sum, &
12943  comm%handle, ierr)
12944  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
12945 
12946  CALL add_perf(perf_id=3, count=1, &
12947  msg_size=rcount(1)*2*int_8_size)
12948 #else
12949  mark_used(rcount)
12950  mark_used(comm)
12951  msgin = msgout(:, 1)
12952 #endif
12953  CALL mp_timestop(handle)
12954  END SUBROUTINE mp_sum_scatter_lv
12955 
12956 ! **************************************************************************************************
12957 !> \brief Sends and receives vector data
12958 !> \param[in] msgin Data to send
12959 !> \param[in] dest Process to send data to
12960 !> \param[out] msgout Received data
12961 !> \param[in] source Process from which to receive
12962 !> \param[in] comm Message passing environment identifier
12963 !> \param[in] tag Send and recv tag (default: 0)
12964 ! **************************************************************************************************
12965  SUBROUTINE mp_sendrecv_l (msgin, dest, msgout, source, comm, tag)
12966  INTEGER(KIND=int_8), INTENT(IN) :: msgin
12967  INTEGER, INTENT(IN) :: dest
12968  INTEGER(KIND=int_8), INTENT(OUT) :: msgout
12969  INTEGER, INTENT(IN) :: source
12970  CLASS(mp_comm_type), INTENT(IN) :: comm
12971  INTEGER, INTENT(IN), OPTIONAL :: tag
12972 
12973  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_l'
12974 
12975  INTEGER :: handle
12976 #if defined(__parallel)
12977  INTEGER :: ierr, msglen_in, msglen_out, &
12978  recv_tag, send_tag
12979 #endif
12980 
12981  CALL mp_timeset(routinen, handle)
12982 
12983 #if defined(__parallel)
12984  msglen_in = 1
12985  msglen_out = 1
12986  send_tag = 0 ! cannot think of something better here, this might be dangerous
12987  recv_tag = 0 ! cannot think of something better here, this might be dangerous
12988  IF (PRESENT(tag)) THEN
12989  send_tag = tag
12990  recv_tag = tag
12991  END IF
12992  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer8, dest, send_tag, msgout, &
12993  msglen_out, mpi_integer8, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
12994  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
12995  CALL add_perf(perf_id=7, count=1, &
12996  msg_size=(msglen_in + msglen_out)*int_8_size/2)
12997 #else
12998  mark_used(dest)
12999  mark_used(source)
13000  mark_used(comm)
13001  mark_used(tag)
13002  msgout = msgin
13003 #endif
13004  CALL mp_timestop(handle)
13005  END SUBROUTINE mp_sendrecv_l
13006 
13007 ! **************************************************************************************************
13008 !> \brief Sends and receives vector data
13009 !> \param[in] msgin Data to send
13010 !> \param[in] dest Process to send data to
13011 !> \param[out] msgout Received data
13012 !> \param[in] source Process from which to receive
13013 !> \param[in] comm Message passing environment identifier
13014 !> \param[in] tag Send and recv tag (default: 0)
13015 ! **************************************************************************************************
13016  SUBROUTINE mp_sendrecv_lv(msgin, dest, msgout, source, comm, tag)
13017  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgin(:)
13018  INTEGER, INTENT(IN) :: dest
13019  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgout(:)
13020  INTEGER, INTENT(IN) :: source
13021  CLASS(mp_comm_type), INTENT(IN) :: comm
13022  INTEGER, INTENT(IN), OPTIONAL :: tag
13023 
13024  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_lv'
13025 
13026  INTEGER :: handle
13027 #if defined(__parallel)
13028  INTEGER :: ierr, msglen_in, msglen_out, &
13029  recv_tag, send_tag
13030 #endif
13031 
13032  CALL mp_timeset(routinen, handle)
13033 
13034 #if defined(__parallel)
13035  msglen_in = SIZE(msgin)
13036  msglen_out = SIZE(msgout)
13037  send_tag = 0 ! cannot think of something better here, this might be dangerous
13038  recv_tag = 0 ! cannot think of something better here, this might be dangerous
13039  IF (PRESENT(tag)) THEN
13040  send_tag = tag
13041  recv_tag = tag
13042  END IF
13043  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer8, dest, send_tag, msgout, &
13044  msglen_out, mpi_integer8, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
13045  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
13046  CALL add_perf(perf_id=7, count=1, &
13047  msg_size=(msglen_in + msglen_out)*int_8_size/2)
13048 #else
13049  mark_used(dest)
13050  mark_used(source)
13051  mark_used(comm)
13052  mark_used(tag)
13053  msgout = msgin
13054 #endif
13055  CALL mp_timestop(handle)
13056  END SUBROUTINE mp_sendrecv_lv
13057 
13058 ! **************************************************************************************************
13059 !> \brief Sends and receives matrix data
13060 !> \param msgin ...
13061 !> \param dest ...
13062 !> \param msgout ...
13063 !> \param source ...
13064 !> \param comm ...
13065 !> \param tag ...
13066 !> \note see mp_sendrecv_lv
13067 ! **************************************************************************************************
13068  SUBROUTINE mp_sendrecv_lm2(msgin, dest, msgout, source, comm, tag)
13069  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
13070  INTEGER, INTENT(IN) :: dest
13071  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
13072  INTEGER, INTENT(IN) :: source
13073  CLASS(mp_comm_type), INTENT(IN) :: comm
13074  INTEGER, INTENT(IN), OPTIONAL :: tag
13075 
13076  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_lm2'
13077 
13078  INTEGER :: handle
13079 #if defined(__parallel)
13080  INTEGER :: ierr, msglen_in, msglen_out, &
13081  recv_tag, send_tag
13082 #endif
13083 
13084  CALL mp_timeset(routinen, handle)
13085 
13086 #if defined(__parallel)
13087  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
13088  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
13089  send_tag = 0 ! cannot think of something better here, this might be dangerous
13090  recv_tag = 0 ! cannot think of something better here, this might be dangerous
13091  IF (PRESENT(tag)) THEN
13092  send_tag = tag
13093  recv_tag = tag
13094  END IF
13095  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer8, dest, send_tag, msgout, &
13096  msglen_out, mpi_integer8, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
13097  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
13098  CALL add_perf(perf_id=7, count=1, &
13099  msg_size=(msglen_in + msglen_out)*int_8_size/2)
13100 #else
13101  mark_used(dest)
13102  mark_used(source)
13103  mark_used(comm)
13104  mark_used(tag)
13105  msgout = msgin
13106 #endif
13107  CALL mp_timestop(handle)
13108  END SUBROUTINE mp_sendrecv_lm2
13109 
13110 ! **************************************************************************************************
13111 !> \brief Sends and receives rank-3 data
13112 !> \param msgin ...
13113 !> \param dest ...
13114 !> \param msgout ...
13115 !> \param source ...
13116 !> \param comm ...
13117 !> \note see mp_sendrecv_lv
13118 ! **************************************************************************************************
13119  SUBROUTINE mp_sendrecv_lm3(msgin, dest, msgout, source, comm, tag)
13120  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
13121  INTEGER, INTENT(IN) :: dest
13122  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
13123  INTEGER, INTENT(IN) :: source
13124  CLASS(mp_comm_type), INTENT(IN) :: comm
13125  INTEGER, INTENT(IN), OPTIONAL :: tag
13126 
13127  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_lm3'
13128 
13129  INTEGER :: handle
13130 #if defined(__parallel)
13131  INTEGER :: ierr, msglen_in, msglen_out, &
13132  recv_tag, send_tag
13133 #endif
13134 
13135  CALL mp_timeset(routinen, handle)
13136 
13137 #if defined(__parallel)
13138  msglen_in = SIZE(msgin)
13139  msglen_out = SIZE(msgout)
13140  send_tag = 0 ! cannot think of something better here, this might be dangerous
13141  recv_tag = 0 ! cannot think of something better here, this might be dangerous
13142  IF (PRESENT(tag)) THEN
13143  send_tag = tag
13144  recv_tag = tag
13145  END IF
13146  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer8, dest, send_tag, msgout, &
13147  msglen_out, mpi_integer8, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
13148  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
13149  CALL add_perf(perf_id=7, count=1, &
13150  msg_size=(msglen_in + msglen_out)*int_8_size/2)
13151 #else
13152  mark_used(dest)
13153  mark_used(source)
13154  mark_used(comm)
13155  mark_used(tag)
13156  msgout = msgin
13157 #endif
13158  CALL mp_timestop(handle)
13159  END SUBROUTINE mp_sendrecv_lm3
13160 
13161 ! **************************************************************************************************
13162 !> \brief Sends and receives rank-4 data
13163 !> \param msgin ...
13164 !> \param dest ...
13165 !> \param msgout ...
13166 !> \param source ...
13167 !> \param comm ...
13168 !> \note see mp_sendrecv_lv
13169 ! **************************************************************************************************
13170  SUBROUTINE mp_sendrecv_lm4(msgin, dest, msgout, source, comm, tag)
13171  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
13172  INTEGER, INTENT(IN) :: dest
13173  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
13174  INTEGER, INTENT(IN) :: source
13175  CLASS(mp_comm_type), INTENT(IN) :: comm
13176  INTEGER, INTENT(IN), OPTIONAL :: tag
13177 
13178  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_lm4'
13179 
13180  INTEGER :: handle
13181 #if defined(__parallel)
13182  INTEGER :: ierr, msglen_in, msglen_out, &
13183  recv_tag, send_tag
13184 #endif
13185 
13186  CALL mp_timeset(routinen, handle)
13187 
13188 #if defined(__parallel)
13189  msglen_in = SIZE(msgin)
13190  msglen_out = SIZE(msgout)
13191  send_tag = 0 ! cannot think of something better here, this might be dangerous
13192  recv_tag = 0 ! cannot think of something better here, this might be dangerous
13193  IF (PRESENT(tag)) THEN
13194  send_tag = tag
13195  recv_tag = tag
13196  END IF
13197  CALL mpi_sendrecv(msgin, msglen_in, mpi_integer8, dest, send_tag, msgout, &
13198  msglen_out, mpi_integer8, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
13199  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
13200  CALL add_perf(perf_id=7, count=1, &
13201  msg_size=(msglen_in + msglen_out)*int_8_size/2)
13202 #else
13203  mark_used(dest)
13204  mark_used(source)
13205  mark_used(comm)
13206  mark_used(tag)
13207  msgout = msgin
13208 #endif
13209  CALL mp_timestop(handle)
13210  END SUBROUTINE mp_sendrecv_lm4
13211 
13212 ! **************************************************************************************************
13213 !> \brief Non-blocking send and receive of a scalar
13214 !> \param[in] msgin Scalar data to send
13215 !> \param[in] dest Which process to send to
13216 !> \param[out] msgout Receive data into this pointer
13217 !> \param[in] source Process to receive from
13218 !> \param[in] comm Message passing environment identifier
13219 !> \param[out] send_request Request handle for the send
13220 !> \param[out] recv_request Request handle for the receive
13221 !> \param[in] tag (optional) tag to differentiate requests
13222 !> \par Implementation
13223 !> Calls mpi_isend and mpi_irecv.
13224 !> \par History
13225 !> 02.2005 created [Alfio Lazzaro]
13226 ! **************************************************************************************************
13227  SUBROUTINE mp_isendrecv_l (msgin, dest, msgout, source, comm, send_request, &
13228  recv_request, tag)
13229  INTEGER(KIND=int_8), INTENT(IN) :: msgin
13230  INTEGER, INTENT(IN) :: dest
13231  INTEGER(KIND=int_8), INTENT(INOUT) :: msgout
13232  INTEGER, INTENT(IN) :: source
13233  CLASS(mp_comm_type), INTENT(IN) :: comm
13234  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
13235  INTEGER, INTENT(in), OPTIONAL :: tag
13236 
13237  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_l'
13238 
13239  INTEGER :: handle
13240 #if defined(__parallel)
13241  INTEGER :: ierr, my_tag
13242 #endif
13243 
13244  CALL mp_timeset(routinen, handle)
13245 
13246 #if defined(__parallel)
13247  my_tag = 0
13248  IF (PRESENT(tag)) my_tag = tag
13249 
13250  CALL mpi_irecv(msgout, 1, mpi_integer8, source, my_tag, &
13251  comm%handle, recv_request%handle, ierr)
13252  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
13253 
13254  CALL mpi_isend(msgin, 1, mpi_integer8, dest, my_tag, &
13255  comm%handle, send_request%handle, ierr)
13256  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13257 
13258  CALL add_perf(perf_id=8, count=1, msg_size=2*int_8_size)
13259 #else
13260  mark_used(dest)
13261  mark_used(source)
13262  mark_used(comm)
13263  mark_used(tag)
13264  send_request = mp_request_null
13265  recv_request = mp_request_null
13266  msgout = msgin
13267 #endif
13268  CALL mp_timestop(handle)
13269  END SUBROUTINE mp_isendrecv_l
13270 
13271 ! **************************************************************************************************
13272 !> \brief Non-blocking send and receive of a vector
13273 !> \param[in] msgin Vector data to send
13274 !> \param[in] dest Which process to send to
13275 !> \param[out] msgout Receive data into this pointer
13276 !> \param[in] source Process to receive from
13277 !> \param[in] comm Message passing environment identifier
13278 !> \param[out] send_request Request handle for the send
13279 !> \param[out] recv_request Request handle for the receive
13280 !> \param[in] tag (optional) tag to differentiate requests
13281 !> \par Implementation
13282 !> Calls mpi_isend and mpi_irecv.
13283 !> \par History
13284 !> 11.2004 created [Joost VandeVondele]
13285 !> \note
13286 !> arrays can be pointers or assumed shape, but they must be contiguous!
13287 ! **************************************************************************************************
13288  SUBROUTINE mp_isendrecv_lv(msgin, dest, msgout, source, comm, send_request, &
13289  recv_request, tag)
13290  INTEGER(KIND=int_8), DIMENSION(:), INTENT(IN) :: msgin
13291  INTEGER, INTENT(IN) :: dest
13292  INTEGER(KIND=int_8), DIMENSION(:), INTENT(INOUT) :: msgout
13293  INTEGER, INTENT(IN) :: source
13294  CLASS(mp_comm_type), INTENT(IN) :: comm
13295  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
13296  INTEGER, INTENT(in), OPTIONAL :: tag
13297 
13298  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_lv'
13299 
13300  INTEGER :: handle
13301 #if defined(__parallel)
13302  INTEGER :: ierr, msglen, my_tag
13303  INTEGER(KIND=int_8) :: foo
13304 #endif
13305 
13306  CALL mp_timeset(routinen, handle)
13307 
13308 #if defined(__parallel)
13309 #if !defined(__GNUC__) || __GNUC__ >= 9
13310  cpassert(is_contiguous(msgout))
13311  cpassert(is_contiguous(msgin))
13312 #endif
13313 
13314  my_tag = 0
13315  IF (PRESENT(tag)) my_tag = tag
13316 
13317  msglen = SIZE(msgout, 1)
13318  IF (msglen > 0) THEN
13319  CALL mpi_irecv(msgout(1), msglen, mpi_integer8, source, my_tag, &
13320  comm%handle, recv_request%handle, ierr)
13321  ELSE
13322  CALL mpi_irecv(foo, msglen, mpi_integer8, source, my_tag, &
13323  comm%handle, recv_request%handle, ierr)
13324  END IF
13325  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
13326 
13327  msglen = SIZE(msgin, 1)
13328  IF (msglen > 0) THEN
13329  CALL mpi_isend(msgin(1), msglen, mpi_integer8, dest, my_tag, &
13330  comm%handle, send_request%handle, ierr)
13331  ELSE
13332  CALL mpi_isend(foo, msglen, mpi_integer8, dest, my_tag, &
13333  comm%handle, send_request%handle, ierr)
13334  END IF
13335  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13336 
13337  msglen = (msglen + SIZE(msgout, 1) + 1)/2
13338  CALL add_perf(perf_id=8, count=1, msg_size=msglen*int_8_size)
13339 #else
13340  mark_used(dest)
13341  mark_used(source)
13342  mark_used(comm)
13343  mark_used(tag)
13344  send_request = mp_request_null
13345  recv_request = mp_request_null
13346  msgout = msgin
13347 #endif
13348  CALL mp_timestop(handle)
13349  END SUBROUTINE mp_isendrecv_lv
13350 
13351 ! **************************************************************************************************
13352 !> \brief Non-blocking send of vector data
13353 !> \param msgin ...
13354 !> \param dest ...
13355 !> \param comm ...
13356 !> \param request ...
13357 !> \param tag ...
13358 !> \par History
13359 !> 08.2003 created [f&j]
13360 !> \note see mp_isendrecv_lv
13361 !> \note
13362 !> arrays can be pointers or assumed shape, but they must be contiguous!
13363 ! **************************************************************************************************
13364  SUBROUTINE mp_isend_lv(msgin, dest, comm, request, tag)
13365  INTEGER(KIND=int_8), DIMENSION(:), INTENT(IN) :: msgin
13366  INTEGER, INTENT(IN) :: dest
13367  CLASS(mp_comm_type), INTENT(IN) :: comm
13368  TYPE(mp_request_type), INTENT(out) :: request
13369  INTEGER, INTENT(in), OPTIONAL :: tag
13370 
13371  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_lv'
13372 
13373  INTEGER :: handle, ierr
13374 #if defined(__parallel)
13375  INTEGER :: msglen, my_tag
13376  INTEGER(KIND=int_8) :: foo(1)
13377 #endif
13378 
13379  CALL mp_timeset(routinen, handle)
13380 
13381 #if defined(__parallel)
13382 #if !defined(__GNUC__) || __GNUC__ >= 9
13383  cpassert(is_contiguous(msgin))
13384 #endif
13385  my_tag = 0
13386  IF (PRESENT(tag)) my_tag = tag
13387 
13388  msglen = SIZE(msgin)
13389  IF (msglen > 0) THEN
13390  CALL mpi_isend(msgin(1), msglen, mpi_integer8, dest, my_tag, &
13391  comm%handle, request%handle, ierr)
13392  ELSE
13393  CALL mpi_isend(foo, msglen, mpi_integer8, dest, my_tag, &
13394  comm%handle, request%handle, ierr)
13395  END IF
13396  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13397 
13398  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_8_size)
13399 #else
13400  mark_used(msgin)
13401  mark_used(dest)
13402  mark_used(comm)
13403  mark_used(request)
13404  mark_used(tag)
13405  ierr = 1
13406  request = mp_request_null
13407  CALL mp_stop(ierr, "mp_isend called in non parallel case")
13408 #endif
13409  CALL mp_timestop(handle)
13410  END SUBROUTINE mp_isend_lv
13411 
13412 ! **************************************************************************************************
13413 !> \brief Non-blocking send of matrix data
13414 !> \param msgin ...
13415 !> \param dest ...
13416 !> \param comm ...
13417 !> \param request ...
13418 !> \param tag ...
13419 !> \par History
13420 !> 2009-11-25 [UB] Made type-generic for templates
13421 !> \author fawzi
13422 !> \note see mp_isendrecv_lv
13423 !> \note see mp_isend_lv
13424 !> \note
13425 !> arrays can be pointers or assumed shape, but they must be contiguous!
13426 ! **************************************************************************************************
13427  SUBROUTINE mp_isend_lm2(msgin, dest, comm, request, tag)
13428  INTEGER(KIND=int_8), DIMENSION(:, :), INTENT(IN) :: msgin
13429  INTEGER, INTENT(IN) :: dest
13430  CLASS(mp_comm_type), INTENT(IN) :: comm
13431  TYPE(mp_request_type), INTENT(out) :: request
13432  INTEGER, INTENT(in), OPTIONAL :: tag
13433 
13434  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_lm2'
13435 
13436  INTEGER :: handle, ierr
13437 #if defined(__parallel)
13438  INTEGER :: msglen, my_tag
13439  INTEGER(KIND=int_8) :: foo(1)
13440 #endif
13441 
13442  CALL mp_timeset(routinen, handle)
13443 
13444 #if defined(__parallel)
13445 #if !defined(__GNUC__) || __GNUC__ >= 9
13446  cpassert(is_contiguous(msgin))
13447 #endif
13448 
13449  my_tag = 0
13450  IF (PRESENT(tag)) my_tag = tag
13451 
13452  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
13453  IF (msglen > 0) THEN
13454  CALL mpi_isend(msgin(1, 1), msglen, mpi_integer8, dest, my_tag, &
13455  comm%handle, request%handle, ierr)
13456  ELSE
13457  CALL mpi_isend(foo, msglen, mpi_integer8, dest, my_tag, &
13458  comm%handle, request%handle, ierr)
13459  END IF
13460  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13461 
13462  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_8_size)
13463 #else
13464  mark_used(msgin)
13465  mark_used(dest)
13466  mark_used(comm)
13467  mark_used(request)
13468  mark_used(tag)
13469  ierr = 1
13470  request = mp_request_null
13471  CALL mp_stop(ierr, "mp_isend called in non parallel case")
13472 #endif
13473  CALL mp_timestop(handle)
13474  END SUBROUTINE mp_isend_lm2
13475 
13476 ! **************************************************************************************************
13477 !> \brief Non-blocking send of rank-3 data
13478 !> \param msgin ...
13479 !> \param dest ...
13480 !> \param comm ...
13481 !> \param request ...
13482 !> \param tag ...
13483 !> \par History
13484 !> 9.2008 added _rm3 subroutine [Iain Bethune]
13485 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
13486 !> 2009-11-25 [UB] Made type-generic for templates
13487 !> \author fawzi
13488 !> \note see mp_isendrecv_lv
13489 !> \note see mp_isend_lv
13490 !> \note
13491 !> arrays can be pointers or assumed shape, but they must be contiguous!
13492 ! **************************************************************************************************
13493  SUBROUTINE mp_isend_lm3(msgin, dest, comm, request, tag)
13494  INTEGER(KIND=int_8), DIMENSION(:, :, :), INTENT(IN) :: msgin
13495  INTEGER, INTENT(IN) :: dest
13496  CLASS(mp_comm_type), INTENT(IN) :: comm
13497  TYPE(mp_request_type), INTENT(out) :: request
13498  INTEGER, INTENT(in), OPTIONAL :: tag
13499 
13500  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_lm3'
13501 
13502  INTEGER :: handle, ierr
13503 #if defined(__parallel)
13504  INTEGER :: msglen, my_tag
13505  INTEGER(KIND=int_8) :: foo(1)
13506 #endif
13507 
13508  CALL mp_timeset(routinen, handle)
13509 
13510 #if defined(__parallel)
13511 #if !defined(__GNUC__) || __GNUC__ >= 9
13512  cpassert(is_contiguous(msgin))
13513 #endif
13514 
13515  my_tag = 0
13516  IF (PRESENT(tag)) my_tag = tag
13517 
13518  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
13519  IF (msglen > 0) THEN
13520  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_integer8, dest, my_tag, &
13521  comm%handle, request%handle, ierr)
13522  ELSE
13523  CALL mpi_isend(foo, msglen, mpi_integer8, dest, my_tag, &
13524  comm%handle, request%handle, ierr)
13525  END IF
13526  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13527 
13528  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_8_size)
13529 #else
13530  mark_used(msgin)
13531  mark_used(dest)
13532  mark_used(comm)
13533  mark_used(request)
13534  mark_used(tag)
13535  ierr = 1
13536  request = mp_request_null
13537  CALL mp_stop(ierr, "mp_isend called in non parallel case")
13538 #endif
13539  CALL mp_timestop(handle)
13540  END SUBROUTINE mp_isend_lm3
13541 
13542 ! **************************************************************************************************
13543 !> \brief Non-blocking send of rank-4 data
13544 !> \param msgin the input message
13545 !> \param dest the destination processor
13546 !> \param comm the communicator object
13547 !> \param request the communication request id
13548 !> \param tag the message tag
13549 !> \par History
13550 !> 2.2016 added _lm4 subroutine [Nico Holmberg]
13551 !> \author fawzi
13552 !> \note see mp_isend_lv
13553 !> \note
13554 !> arrays can be pointers or assumed shape, but they must be contiguous!
13555 ! **************************************************************************************************
13556  SUBROUTINE mp_isend_lm4(msgin, dest, comm, request, tag)
13557  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
13558  INTEGER, INTENT(IN) :: dest
13559  CLASS(mp_comm_type), INTENT(IN) :: comm
13560  TYPE(mp_request_type), INTENT(out) :: request
13561  INTEGER, INTENT(in), OPTIONAL :: tag
13562 
13563  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_lm4'
13564 
13565  INTEGER :: handle, ierr
13566 #if defined(__parallel)
13567  INTEGER :: msglen, my_tag
13568  INTEGER(KIND=int_8) :: foo(1)
13569 #endif
13570 
13571  CALL mp_timeset(routinen, handle)
13572 
13573 #if defined(__parallel)
13574 #if !defined(__GNUC__) || __GNUC__ >= 9
13575  cpassert(is_contiguous(msgin))
13576 #endif
13577 
13578  my_tag = 0
13579  IF (PRESENT(tag)) my_tag = tag
13580 
13581  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
13582  IF (msglen > 0) THEN
13583  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_integer8, dest, my_tag, &
13584  comm%handle, request%handle, ierr)
13585  ELSE
13586  CALL mpi_isend(foo, msglen, mpi_integer8, dest, my_tag, &
13587  comm%handle, request%handle, ierr)
13588  END IF
13589  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
13590 
13591  CALL add_perf(perf_id=11, count=1, msg_size=msglen*int_8_size)
13592 #else
13593  mark_used(msgin)
13594  mark_used(dest)
13595  mark_used(comm)
13596  mark_used(request)
13597  mark_used(tag)
13598  ierr = 1
13599  request = mp_request_null
13600  CALL mp_stop(ierr, "mp_isend called in non parallel case")
13601 #endif
13602  CALL mp_timestop(handle)
13603  END SUBROUTINE mp_isend_lm4
13604 
13605 ! **************************************************************************************************
13606 !> \brief Non-blocking receive of vector data
13607 !> \param msgout ...
13608 !> \param source ...
13609 !> \param comm ...
13610 !> \param request ...
13611 !> \param tag ...
13612 !> \par History
13613 !> 08.2003 created [f&j]
13614 !> 2009-11-25 [UB] Made type-generic for templates
13615 !> \note see mp_isendrecv_lv
13616 !> \note
13617 !> arrays can be pointers or assumed shape, but they must be contiguous!
13618 ! **************************************************************************************************
13619  SUBROUTINE mp_irecv_lv(msgout, source, comm, request, tag)
13620  INTEGER(KIND=int_8), DIMENSION(:), INTENT(INOUT) :: msgout
13621  INTEGER, INTENT(IN) :: source
13622  CLASS(mp_comm_type), INTENT(IN) :: comm
13623  TYPE(mp_request_type), INTENT(out) :: request
13624  INTEGER, INTENT(in), OPTIONAL :: tag
13625 
13626  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_lv'
13627 
13628  INTEGER :: handle
13629 #if defined(__parallel)
13630  INTEGER :: ierr, msglen, my_tag
13631  INTEGER(KIND=int_8) :: foo(1)
13632 #endif
13633 
13634  CALL mp_timeset(routinen, handle)
13635 
13636 #if defined(__parallel)
13637 #if !defined(__GNUC__) || __GNUC__ >= 9
13638  cpassert(is_contiguous(msgout))
13639 #endif
13640 
13641  my_tag = 0
13642  IF (PRESENT(tag)) my_tag = tag
13643 
13644  msglen = SIZE(msgout)
13645  IF (msglen > 0) THEN
13646  CALL mpi_irecv(msgout(1), msglen, mpi_integer8, source, my_tag, &
13647  comm%handle, request%handle, ierr)
13648  ELSE
13649  CALL mpi_irecv(foo, msglen, mpi_integer8, source, my_tag, &
13650  comm%handle, request%handle, ierr)
13651  END IF
13652  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
13653 
13654  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_8_size)
13655 #else
13656  cpabort("mp_irecv called in non parallel case")
13657  mark_used(msgout)
13658  mark_used(source)
13659  mark_used(comm)
13660  mark_used(tag)
13661  request = mp_request_null
13662 #endif
13663  CALL mp_timestop(handle)
13664  END SUBROUTINE mp_irecv_lv
13665 
13666 ! **************************************************************************************************
13667 !> \brief Non-blocking receive of matrix data
13668 !> \param msgout ...
13669 !> \param source ...
13670 !> \param comm ...
13671 !> \param request ...
13672 !> \param tag ...
13673 !> \par History
13674 !> 2009-11-25 [UB] Made type-generic for templates
13675 !> \author fawzi
13676 !> \note see mp_isendrecv_lv
13677 !> \note see mp_irecv_lv
13678 !> \note
13679 !> arrays can be pointers or assumed shape, but they must be contiguous!
13680 ! **************************************************************************************************
13681  SUBROUTINE mp_irecv_lm2(msgout, source, comm, request, tag)
13682  INTEGER(KIND=int_8), DIMENSION(:, :), INTENT(INOUT) :: msgout
13683  INTEGER, INTENT(IN) :: source
13684  CLASS(mp_comm_type), INTENT(IN) :: comm
13685  TYPE(mp_request_type), INTENT(out) :: request
13686  INTEGER, INTENT(in), OPTIONAL :: tag
13687 
13688  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_lm2'
13689 
13690  INTEGER :: handle
13691 #if defined(__parallel)
13692  INTEGER :: ierr, msglen, my_tag
13693  INTEGER(KIND=int_8) :: foo(1)
13694 #endif
13695 
13696  CALL mp_timeset(routinen, handle)
13697 
13698 #if defined(__parallel)
13699 #if !defined(__GNUC__) || __GNUC__ >= 9
13700  cpassert(is_contiguous(msgout))
13701 #endif
13702 
13703  my_tag = 0
13704  IF (PRESENT(tag)) my_tag = tag
13705 
13706  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
13707  IF (msglen > 0) THEN
13708  CALL mpi_irecv(msgout(1, 1), msglen, mpi_integer8, source, my_tag, &
13709  comm%handle, request%handle, ierr)
13710  ELSE
13711  CALL mpi_irecv(foo, msglen, mpi_integer8, source, my_tag, &
13712  comm%handle, request%handle, ierr)
13713  END IF
13714  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
13715 
13716  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_8_size)
13717 #else
13718  mark_used(msgout)
13719  mark_used(source)
13720  mark_used(comm)
13721  mark_used(tag)
13722  request = mp_request_null
13723  cpabort("mp_irecv called in non parallel case")
13724 #endif
13725  CALL mp_timestop(handle)
13726  END SUBROUTINE mp_irecv_lm2
13727 
13728 ! **************************************************************************************************
13729 !> \brief Non-blocking send of rank-3 data
13730 !> \param msgout ...
13731 !> \param source ...
13732 !> \param comm ...
13733 !> \param request ...
13734 !> \param tag ...
13735 !> \par History
13736 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
13737 !> 2009-11-25 [UB] Made type-generic for templates
13738 !> \author fawzi
13739 !> \note see mp_isendrecv_lv
13740 !> \note see mp_irecv_lv
13741 !> \note
13742 !> arrays can be pointers or assumed shape, but they must be contiguous!
13743 ! **************************************************************************************************
13744  SUBROUTINE mp_irecv_lm3(msgout, source, comm, request, tag)
13745  INTEGER(KIND=int_8), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
13746  INTEGER, INTENT(IN) :: source
13747  CLASS(mp_comm_type), INTENT(IN) :: comm
13748  TYPE(mp_request_type), INTENT(out) :: request
13749  INTEGER, INTENT(in), OPTIONAL :: tag
13750 
13751  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_lm3'
13752 
13753  INTEGER :: handle
13754 #if defined(__parallel)
13755  INTEGER :: ierr, msglen, my_tag
13756  INTEGER(KIND=int_8) :: foo(1)
13757 #endif
13758 
13759  CALL mp_timeset(routinen, handle)
13760 
13761 #if defined(__parallel)
13762 #if !defined(__GNUC__) || __GNUC__ >= 9
13763  cpassert(is_contiguous(msgout))
13764 #endif
13765 
13766  my_tag = 0
13767  IF (PRESENT(tag)) my_tag = tag
13768 
13769  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
13770  IF (msglen > 0) THEN
13771  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_integer8, source, my_tag, &
13772  comm%handle, request%handle, ierr)
13773  ELSE
13774  CALL mpi_irecv(foo, msglen, mpi_integer8, source, my_tag, &
13775  comm%handle, request%handle, ierr)
13776  END IF
13777  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
13778 
13779  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_8_size)
13780 #else
13781  mark_used(msgout)
13782  mark_used(source)
13783  mark_used(comm)
13784  mark_used(tag)
13785  request = mp_request_null
13786  cpabort("mp_irecv called in non parallel case")
13787 #endif
13788  CALL mp_timestop(handle)
13789  END SUBROUTINE mp_irecv_lm3
13790 
13791 ! **************************************************************************************************
13792 !> \brief Non-blocking receive of rank-4 data
13793 !> \param msgout the output message
13794 !> \param source the source processor
13795 !> \param comm the communicator object
13796 !> \param request the communication request id
13797 !> \param tag the message tag
13798 !> \par History
13799 !> 2.2016 added _lm4 subroutine [Nico Holmberg]
13800 !> \author fawzi
13801 !> \note see mp_irecv_lv
13802 !> \note
13803 !> arrays can be pointers or assumed shape, but they must be contiguous!
13804 ! **************************************************************************************************
13805  SUBROUTINE mp_irecv_lm4(msgout, source, comm, request, tag)
13806  INTEGER(KIND=int_8), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
13807  INTEGER, INTENT(IN) :: source
13808  CLASS(mp_comm_type), INTENT(IN) :: comm
13809  TYPE(mp_request_type), INTENT(out) :: request
13810  INTEGER, INTENT(in), OPTIONAL :: tag
13811 
13812  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_lm4'
13813 
13814  INTEGER :: handle
13815 #if defined(__parallel)
13816  INTEGER :: ierr, msglen, my_tag
13817  INTEGER(KIND=int_8) :: foo(1)
13818 #endif
13819 
13820  CALL mp_timeset(routinen, handle)
13821 
13822 #if defined(__parallel)
13823 #if !defined(__GNUC__) || __GNUC__ >= 9
13824  cpassert(is_contiguous(msgout))
13825 #endif
13826 
13827  my_tag = 0
13828  IF (PRESENT(tag)) my_tag = tag
13829 
13830  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
13831  IF (msglen > 0) THEN
13832  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_integer8, source, my_tag, &
13833  comm%handle, request%handle, ierr)
13834  ELSE
13835  CALL mpi_irecv(foo, msglen, mpi_integer8, source, my_tag, &
13836  comm%handle, request%handle, ierr)
13837  END IF
13838  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
13839 
13840  CALL add_perf(perf_id=12, count=1, msg_size=msglen*int_8_size)
13841 #else
13842  mark_used(msgout)
13843  mark_used(source)
13844  mark_used(comm)
13845  mark_used(tag)
13846  request = mp_request_null
13847  cpabort("mp_irecv called in non parallel case")
13848 #endif
13849  CALL mp_timestop(handle)
13850  END SUBROUTINE mp_irecv_lm4
13851 
13852 ! **************************************************************************************************
13853 !> \brief Window initialization function for vector data
13854 !> \param base ...
13855 !> \param comm ...
13856 !> \param win ...
13857 !> \par History
13858 !> 02.2015 created [Alfio Lazzaro]
13859 !> \note
13860 !> arrays can be pointers or assumed shape, but they must be contiguous!
13861 ! **************************************************************************************************
13862  SUBROUTINE mp_win_create_lv(base, comm, win)
13863  INTEGER(KIND=int_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
13864  TYPE(mp_comm_type), INTENT(IN) :: comm
13865  CLASS(mp_win_type), INTENT(INOUT) :: win
13866 
13867  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_lv'
13868 
13869  INTEGER :: handle
13870 #if defined(__parallel)
13871  INTEGER :: ierr
13872  INTEGER(kind=mpi_address_kind) :: len
13873  INTEGER(KIND=int_8) :: foo(1)
13874 #endif
13875 
13876  CALL mp_timeset(routinen, handle)
13877 
13878 #if defined(__parallel)
13879 
13880  len = SIZE(base)*int_8_size
13881  IF (len > 0) THEN
13882  CALL mpi_win_create(base(1), len, int_8_size, mpi_info_null, comm%handle, win%handle, ierr)
13883  ELSE
13884  CALL mpi_win_create(foo, len, int_8_size, mpi_info_null, comm%handle, win%handle, ierr)
13885  END IF
13886  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
13887 
13888  CALL add_perf(perf_id=20, count=1)
13889 #else
13890  mark_used(base)
13891  mark_used(comm)
13892  win%handle = mp_win_null_handle
13893 #endif
13894  CALL mp_timestop(handle)
13895  END SUBROUTINE mp_win_create_lv
13896 
13897 ! **************************************************************************************************
13898 !> \brief Single-sided get function for vector data
13899 !> \param base ...
13900 !> \param comm ...
13901 !> \param win ...
13902 !> \par History
13903 !> 02.2015 created [Alfio Lazzaro]
13904 !> \note
13905 !> arrays can be pointers or assumed shape, but they must be contiguous!
13906 ! **************************************************************************************************
13907  SUBROUTINE mp_rget_lv(base, source, win, win_data, myproc, disp, request, &
13908  origin_datatype, target_datatype)
13909  INTEGER(KIND=int_8), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
13910  INTEGER, INTENT(IN) :: source
13911  CLASS(mp_win_type), INTENT(IN) :: win
13912  INTEGER(KIND=int_8), DIMENSION(:), INTENT(IN) :: win_data
13913  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
13914  TYPE(mp_request_type), INTENT(OUT) :: request
13915  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
13916 
13917  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_lv'
13918 
13919  INTEGER :: handle
13920 #if defined(__parallel)
13921  INTEGER :: ierr, len, &
13922  origin_len, target_len
13923  LOGICAL :: do_local_copy
13924  INTEGER(kind=mpi_address_kind) :: disp_aint
13925  mpi_data_type :: handle_origin_datatype, handle_target_datatype
13926 #endif
13927 
13928  CALL mp_timeset(routinen, handle)
13929 
13930 #if defined(__parallel)
13931  len = SIZE(base)
13932  disp_aint = 0
13933  IF (PRESENT(disp)) THEN
13934  disp_aint = int(disp, kind=mpi_address_kind)
13935  END IF
13936  handle_origin_datatype = mpi_integer8
13937  origin_len = len
13938  IF (PRESENT(origin_datatype)) THEN
13939  handle_origin_datatype = origin_datatype%type_handle
13940  origin_len = 1
13941  END IF
13942  handle_target_datatype = mpi_integer8
13943  target_len = len
13944  IF (PRESENT(target_datatype)) THEN
13945  handle_target_datatype = target_datatype%type_handle
13946  target_len = 1
13947  END IF
13948  IF (len > 0) THEN
13949  do_local_copy = .false.
13950  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
13951  IF (myproc .EQ. source) do_local_copy = .true.
13952  END IF
13953  IF (do_local_copy) THEN
13954  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
13955  base(:) = win_data(disp_aint + 1:disp_aint + len)
13956  !$OMP END PARALLEL WORKSHARE
13957  request = mp_request_null
13958  ierr = 0
13959  ELSE
13960  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
13961  target_len, handle_target_datatype, win%handle, request%handle, ierr)
13962  END IF
13963  ELSE
13964  request = mp_request_null
13965  ierr = 0
13966  END IF
13967  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
13968 
13969  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*int_8_size)
13970 #else
13971  mark_used(source)
13972  mark_used(win)
13973  mark_used(myproc)
13974  mark_used(origin_datatype)
13975  mark_used(target_datatype)
13976 
13977  request = mp_request_null
13978  !
13979  IF (PRESENT(disp)) THEN
13980  base(:) = win_data(disp + 1:disp + SIZE(base))
13981  ELSE
13982  base(:) = win_data(:SIZE(base))
13983  END IF
13984 
13985 #endif
13986  CALL mp_timestop(handle)
13987  END SUBROUTINE mp_rget_lv
13988 
13989 ! **************************************************************************************************
13990 !> \brief ...
13991 !> \param count ...
13992 !> \param lengths ...
13993 !> \param displs ...
13994 !> \return ...
13995 ! ***************************************************************************
13996  FUNCTION mp_type_indexed_make_l (count, lengths, displs) &
13997  result(type_descriptor)
13998  INTEGER, INTENT(IN) :: count
13999  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
14000  TYPE(mp_type_descriptor_type) :: type_descriptor
14001 
14002  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_l'
14003 
14004  INTEGER :: handle
14005 #if defined(__parallel)
14006  INTEGER :: ierr
14007 #endif
14008 
14009  CALL mp_timeset(routinen, handle)
14010 
14011 #if defined(__parallel)
14012  CALL mpi_type_indexed(count, lengths, displs, mpi_integer8, &
14013  type_descriptor%type_handle, ierr)
14014  IF (ierr /= 0) &
14015  cpabort("MPI_Type_Indexed @ "//routinen)
14016  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
14017  IF (ierr /= 0) &
14018  cpabort("MPI_Type_commit @ "//routinen)
14019 #else
14020  type_descriptor%type_handle = 19
14021 #endif
14022  type_descriptor%length = count
14023  NULLIFY (type_descriptor%subtype)
14024  type_descriptor%vector_descriptor(1:2) = 1
14025  type_descriptor%has_indexing = .true.
14026  type_descriptor%index_descriptor%index => lengths
14027  type_descriptor%index_descriptor%chunks => displs
14028 
14029  CALL mp_timestop(handle)
14030 
14031  END FUNCTION mp_type_indexed_make_l
14032 
14033 ! **************************************************************************************************
14034 !> \brief Allocates special parallel memory
14035 !> \param[in] DATA pointer to integer array to allocate
14036 !> \param[in] len number of integers to allocate
14037 !> \param[out] stat (optional) allocation status result
14038 !> \author UB
14039 ! **************************************************************************************************
14040  SUBROUTINE mp_allocate_l (DATA, len, stat)
14041  INTEGER(KIND=int_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
14042  INTEGER, INTENT(IN) :: len
14043  INTEGER, INTENT(OUT), OPTIONAL :: stat
14044 
14045  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_l'
14046 
14047  INTEGER :: handle, ierr
14048 
14049  CALL mp_timeset(routinen, handle)
14050 
14051 #if defined(__parallel)
14052  NULLIFY (data)
14053  CALL mp_alloc_mem(DATA, len, stat=ierr)
14054  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
14055  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
14056  CALL add_perf(perf_id=15, count=1)
14057 #else
14058  ALLOCATE (DATA(len), stat=ierr)
14059  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
14060  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
14061 #endif
14062  IF (PRESENT(stat)) stat = ierr
14063  CALL mp_timestop(handle)
14064  END SUBROUTINE mp_allocate_l
14065 
14066 ! **************************************************************************************************
14067 !> \brief Deallocates special parallel memory
14068 !> \param[in] DATA pointer to special memory to deallocate
14069 !> \param stat ...
14070 !> \author UB
14071 ! **************************************************************************************************
14072  SUBROUTINE mp_deallocate_l (DATA, stat)
14073  INTEGER(KIND=int_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
14074  INTEGER, INTENT(OUT), OPTIONAL :: stat
14075 
14076  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_l'
14077 
14078  INTEGER :: handle
14079 #if defined(__parallel)
14080  INTEGER :: ierr
14081 #endif
14082 
14083  CALL mp_timeset(routinen, handle)
14084 
14085 #if defined(__parallel)
14086  CALL mp_free_mem(DATA, ierr)
14087  IF (PRESENT(stat)) THEN
14088  stat = ierr
14089  ELSE
14090  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
14091  END IF
14092  NULLIFY (data)
14093  CALL add_perf(perf_id=15, count=1)
14094 #else
14095  DEALLOCATE (data)
14096  IF (PRESENT(stat)) stat = 0
14097 #endif
14098  CALL mp_timestop(handle)
14099  END SUBROUTINE mp_deallocate_l
14100 
14101 ! **************************************************************************************************
14102 !> \brief (parallel) Blocking individual file write using explicit offsets
14103 !> (serial) Unformatted stream write
14104 !> \param[in] fh file handle (file storage unit)
14105 !> \param[in] offset file offset (position)
14106 !> \param[in] msg data to be written to the file
14107 !> \param msglen ...
14108 !> \par MPI-I/O mapping mpi_file_write_at
14109 !> \par STREAM-I/O mapping WRITE
14110 !> \param[in](optional) msglen number of the elements of data
14111 ! **************************************************************************************************
14112  SUBROUTINE mp_file_write_at_lv(fh, offset, msg, msglen)
14113  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:)
14114  CLASS(mp_file_type), INTENT(IN) :: fh
14115  INTEGER, INTENT(IN), OPTIONAL :: msglen
14116  INTEGER(kind=file_offset), INTENT(IN) :: offset
14117 
14118  INTEGER :: msg_len
14119 #if defined(__parallel)
14120  INTEGER :: ierr
14121 #endif
14122 
14123  msg_len = SIZE(msg)
14124  IF (PRESENT(msglen)) msg_len = msglen
14125 #if defined(__parallel)
14126  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_integer8, mpi_status_ignore, ierr)
14127  IF (ierr .NE. 0) &
14128  cpabort("mpi_file_write_at_lv @ mp_file_write_at_lv")
14129 #else
14130  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
14131 #endif
14132  END SUBROUTINE mp_file_write_at_lv
14133 
14134 ! **************************************************************************************************
14135 !> \brief ...
14136 !> \param fh ...
14137 !> \param offset ...
14138 !> \param msg ...
14139 ! **************************************************************************************************
14140  SUBROUTINE mp_file_write_at_l (fh, offset, msg)
14141  INTEGER(KIND=int_8), INTENT(IN) :: msg
14142  CLASS(mp_file_type), INTENT(IN) :: fh
14143  INTEGER(kind=file_offset), INTENT(IN) :: offset
14144 
14145 #if defined(__parallel)
14146  INTEGER :: ierr
14147 
14148  ierr = 0
14149  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_integer8, mpi_status_ignore, ierr)
14150  IF (ierr .NE. 0) &
14151  cpabort("mpi_file_write_at_l @ mp_file_write_at_l")
14152 #else
14153  WRITE (unit=fh%handle, pos=offset + 1) msg
14154 #endif
14155  END SUBROUTINE mp_file_write_at_l
14156 
14157 ! **************************************************************************************************
14158 !> \brief (parallel) Blocking collective file write using explicit offsets
14159 !> (serial) Unformatted stream write
14160 !> \param fh ...
14161 !> \param offset ...
14162 !> \param msg ...
14163 !> \param msglen ...
14164 !> \par MPI-I/O mapping mpi_file_write_at_all
14165 !> \par STREAM-I/O mapping WRITE
14166 ! **************************************************************************************************
14167  SUBROUTINE mp_file_write_at_all_lv(fh, offset, msg, msglen)
14168  INTEGER(KIND=int_8), CONTIGUOUS, INTENT(IN) :: msg(:)
14169  CLASS(mp_file_type), INTENT(IN) :: fh
14170  INTEGER, INTENT(IN), OPTIONAL :: msglen
14171  INTEGER(kind=file_offset), INTENT(IN) :: offset
14172 
14173  INTEGER :: msg_len
14174 #if defined(__parallel)
14175  INTEGER :: ierr
14176 #endif
14177 
14178  msg_len = SIZE(msg)
14179  IF (PRESENT(msglen)) msg_len = msglen
14180 #if defined(__parallel)
14181  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_integer8, mpi_status_ignore, ierr)
14182  IF (ierr .NE. 0) &
14183  cpabort("mpi_file_write_at_all_lv @ mp_file_write_at_all_lv")
14184 #else
14185  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
14186 #endif
14187  END SUBROUTINE mp_file_write_at_all_lv
14188 
14189 ! **************************************************************************************************
14190 !> \brief ...
14191 !> \param fh ...
14192 !> \param offset ...
14193 !> \param msg ...
14194 ! **************************************************************************************************
14195  SUBROUTINE mp_file_write_at_all_l (fh, offset, msg)
14196  INTEGER(KIND=int_8), INTENT(IN) :: msg
14197  CLASS(mp_file_type), INTENT(IN) :: fh
14198  INTEGER(kind=file_offset), INTENT(IN) :: offset
14199 
14200 #if defined(__parallel)
14201  INTEGER :: ierr
14202 
14203  ierr = 0
14204  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_integer8, mpi_status_ignore, ierr)
14205  IF (ierr .NE. 0) &
14206  cpabort("mpi_file_write_at_all_l @ mp_file_write_at_all_l")
14207 #else
14208  WRITE (unit=fh%handle, pos=offset + 1) msg
14209 #endif
14210  END SUBROUTINE mp_file_write_at_all_l
14211 
14212 ! **************************************************************************************************
14213 !> \brief (parallel) Blocking individual file read using explicit offsets
14214 !> (serial) Unformatted stream read
14215 !> \param[in] fh file handle (file storage unit)
14216 !> \param[in] offset file offset (position)
14217 !> \param[out] msg data to be read from the file
14218 !> \param msglen ...
14219 !> \par MPI-I/O mapping mpi_file_read_at
14220 !> \par STREAM-I/O mapping READ
14221 !> \param[in](optional) msglen number of elements of data
14222 ! **************************************************************************************************
14223  SUBROUTINE mp_file_read_at_lv(fh, offset, msg, msglen)
14224  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msg(:)
14225  CLASS(mp_file_type), INTENT(IN) :: fh
14226  INTEGER, INTENT(IN), OPTIONAL :: msglen
14227  INTEGER(kind=file_offset), INTENT(IN) :: offset
14228 
14229  INTEGER :: msg_len
14230 #if defined(__parallel)
14231  INTEGER :: ierr
14232 #endif
14233 
14234  msg_len = SIZE(msg)
14235  IF (PRESENT(msglen)) msg_len = msglen
14236 #if defined(__parallel)
14237  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_integer8, mpi_status_ignore, ierr)
14238  IF (ierr .NE. 0) &
14239  cpabort("mpi_file_read_at_lv @ mp_file_read_at_lv")
14240 #else
14241  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
14242 #endif
14243  END SUBROUTINE mp_file_read_at_lv
14244 
14245 ! **************************************************************************************************
14246 !> \brief ...
14247 !> \param fh ...
14248 !> \param offset ...
14249 !> \param msg ...
14250 ! **************************************************************************************************
14251  SUBROUTINE mp_file_read_at_l (fh, offset, msg)
14252  INTEGER(KIND=int_8), INTENT(OUT) :: msg
14253  CLASS(mp_file_type), INTENT(IN) :: fh
14254  INTEGER(kind=file_offset), INTENT(IN) :: offset
14255 
14256 #if defined(__parallel)
14257  INTEGER :: ierr
14258 
14259  ierr = 0
14260  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_integer8, mpi_status_ignore, ierr)
14261  IF (ierr .NE. 0) &
14262  cpabort("mpi_file_read_at_l @ mp_file_read_at_l")
14263 #else
14264  READ (unit=fh%handle, pos=offset + 1) msg
14265 #endif
14266  END SUBROUTINE mp_file_read_at_l
14267 
14268 ! **************************************************************************************************
14269 !> \brief (parallel) Blocking collective file read using explicit offsets
14270 !> (serial) Unformatted stream read
14271 !> \param fh ...
14272 !> \param offset ...
14273 !> \param msg ...
14274 !> \param msglen ...
14275 !> \par MPI-I/O mapping mpi_file_read_at_all
14276 !> \par STREAM-I/O mapping READ
14277 ! **************************************************************************************************
14278  SUBROUTINE mp_file_read_at_all_lv(fh, offset, msg, msglen)
14279  INTEGER(KIND=int_8), INTENT(OUT), CONTIGUOUS :: msg(:)
14280  CLASS(mp_file_type), INTENT(IN) :: fh
14281  INTEGER, INTENT(IN), OPTIONAL :: msglen
14282  INTEGER(kind=file_offset), INTENT(IN) :: offset
14283 
14284  INTEGER :: msg_len
14285 #if defined(__parallel)
14286  INTEGER :: ierr
14287 #endif
14288 
14289  msg_len = SIZE(msg)
14290  IF (PRESENT(msglen)) msg_len = msglen
14291 #if defined(__parallel)
14292  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_integer8, mpi_status_ignore, ierr)
14293  IF (ierr .NE. 0) &
14294  cpabort("mpi_file_read_at_all_lv @ mp_file_read_at_all_lv")
14295 #else
14296  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
14297 #endif
14298  END SUBROUTINE mp_file_read_at_all_lv
14299 
14300 ! **************************************************************************************************
14301 !> \brief ...
14302 !> \param fh ...
14303 !> \param offset ...
14304 !> \param msg ...
14305 ! **************************************************************************************************
14306  SUBROUTINE mp_file_read_at_all_l (fh, offset, msg)
14307  INTEGER(KIND=int_8), INTENT(OUT) :: msg
14308  CLASS(mp_file_type), INTENT(IN) :: fh
14309  INTEGER(kind=file_offset), INTENT(IN) :: offset
14310 
14311 #if defined(__parallel)
14312  INTEGER :: ierr
14313 
14314  ierr = 0
14315  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_integer8, mpi_status_ignore, ierr)
14316  IF (ierr .NE. 0) &
14317  cpabort("mpi_file_read_at_all_l @ mp_file_read_at_all_l")
14318 #else
14319  READ (unit=fh%handle, pos=offset + 1) msg
14320 #endif
14321  END SUBROUTINE mp_file_read_at_all_l
14322 
14323 ! **************************************************************************************************
14324 !> \brief ...
14325 !> \param ptr ...
14326 !> \param vector_descriptor ...
14327 !> \param index_descriptor ...
14328 !> \return ...
14329 ! **************************************************************************************************
14330  FUNCTION mp_type_make_l (ptr, &
14331  vector_descriptor, index_descriptor) &
14332  result(type_descriptor)
14333  INTEGER(KIND=int_8), DIMENSION(:), TARGET, asynchronous :: ptr
14334  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
14335  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
14336  TYPE(mp_type_descriptor_type) :: type_descriptor
14337 
14338  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_l'
14339 
14340 #if defined(__parallel)
14341  INTEGER :: ierr
14342 #endif
14343 
14344  NULLIFY (type_descriptor%subtype)
14345  type_descriptor%length = SIZE(ptr)
14346 #if defined(__parallel)
14347  type_descriptor%type_handle = mpi_integer8
14348  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
14349  IF (ierr /= 0) &
14350  cpabort("MPI_Get_address @ "//routinen)
14351 #else
14352  type_descriptor%type_handle = 19
14353 #endif
14354  type_descriptor%vector_descriptor(1:2) = 1
14355  type_descriptor%has_indexing = .false.
14356  type_descriptor%data_l => ptr
14357  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
14358  cpabort(routinen//": Vectors and indices NYI")
14359  END IF
14360  END FUNCTION mp_type_make_l
14361 
14362 ! **************************************************************************************************
14363 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
14364 !> as the Fortran version returns an integer, which we take to be a C_PTR
14365 !> \param DATA data array to allocate
14366 !> \param[in] len length (in data elements) of data array allocation
14367 !> \param[out] stat (optional) allocation status result
14368 ! **************************************************************************************************
14369  SUBROUTINE mp_alloc_mem_l (DATA, len, stat)
14370  INTEGER(KIND=int_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
14371  INTEGER, INTENT(IN) :: len
14372  INTEGER, INTENT(OUT), OPTIONAL :: stat
14373 
14374 #if defined(__parallel)
14375  INTEGER :: size, ierr, length, &
14376  mp_res
14377  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
14378  TYPE(c_ptr) :: mp_baseptr
14379  mpi_info_type :: mp_info
14380 
14381  length = max(len, 1)
14382  CALL mpi_type_size(mpi_integer8, size, ierr)
14383  mp_size = int(length, kind=mpi_address_kind)*size
14384  IF (mp_size .GT. mp_max_memory_size) THEN
14385  cpabort("MPI cannot allocate more than 2 GiByte")
14386  END IF
14387  mp_info = mpi_info_null
14388  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
14389  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
14390  IF (PRESENT(stat)) stat = mp_res
14391 #else
14392  INTEGER :: length, mystat
14393  length = max(len, 1)
14394  IF (PRESENT(stat)) THEN
14395  ALLOCATE (DATA(length), stat=mystat)
14396  stat = mystat ! show to convention checker that stat is used
14397  ELSE
14398  ALLOCATE (DATA(length))
14399  END IF
14400 #endif
14401  END SUBROUTINE mp_alloc_mem_l
14402 
14403 ! **************************************************************************************************
14404 !> \brief Deallocates am array, ... this is hackish
14405 !> as the Fortran version takes an integer, which we hope to get by reference
14406 !> \param DATA data array to allocate
14407 !> \param[out] stat (optional) allocation status result
14408 ! **************************************************************************************************
14409  SUBROUTINE mp_free_mem_l (DATA, stat)
14410  INTEGER(KIND=int_8), DIMENSION(:), &
14411  POINTER, asynchronous :: data
14412  INTEGER, INTENT(OUT), OPTIONAL :: stat
14413 
14414 #if defined(__parallel)
14415  INTEGER :: mp_res
14416  CALL mpi_free_mem(DATA, mp_res)
14417  IF (PRESENT(stat)) stat = mp_res
14418 #else
14419  DEALLOCATE (data)
14420  IF (PRESENT(stat)) stat = 0
14421 #endif
14422  END SUBROUTINE mp_free_mem_l
14423 ! **************************************************************************************************
14424 !> \brief Shift around the data in msg
14425 !> \param[in,out] msg Rank-2 data to shift
14426 !> \param[in] comm message passing environment identifier
14427 !> \param[in] displ_in displacements (?)
14428 !> \par Example
14429 !> msg will be moved from rank to rank+displ_in (in a circular way)
14430 !> \par Limitations
14431 !> * displ_in will be 1 by default (others not tested)
14432 !> * the message array needs to be the same size on all processes
14433 ! **************************************************************************************************
14434  SUBROUTINE mp_shift_dm(msg, comm, displ_in)
14435 
14436  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
14437  CLASS(mp_comm_type), INTENT(IN) :: comm
14438  INTEGER, INTENT(IN), OPTIONAL :: displ_in
14439 
14440  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_dm'
14441 
14442  INTEGER :: handle, ierror
14443 #if defined(__parallel)
14444  INTEGER :: displ, left, &
14445  msglen, myrank, nprocs, &
14446  right, tag
14447 #endif
14448 
14449  ierror = 0
14450  CALL mp_timeset(routinen, handle)
14451 
14452 #if defined(__parallel)
14453  CALL mpi_comm_rank(comm%handle, myrank, ierror)
14454  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
14455  CALL mpi_comm_size(comm%handle, nprocs, ierror)
14456  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
14457  IF (PRESENT(displ_in)) THEN
14458  displ = displ_in
14459  ELSE
14460  displ = 1
14461  END IF
14462  right = modulo(myrank + displ, nprocs)
14463  left = modulo(myrank - displ, nprocs)
14464  tag = 17
14465  msglen = SIZE(msg)
14466  CALL mpi_sendrecv_replace(msg, msglen, mpi_double_precision, right, tag, left, tag, &
14467  comm%handle, mpi_status_ignore, ierror)
14468  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
14469  CALL add_perf(perf_id=7, count=1, msg_size=msglen*real_8_size)
14470 #else
14471  mark_used(msg)
14472  mark_used(comm)
14473  mark_used(displ_in)
14474 #endif
14475  CALL mp_timestop(handle)
14476 
14477  END SUBROUTINE mp_shift_dm
14478 
14479 ! **************************************************************************************************
14480 !> \brief Shift around the data in msg
14481 !> \param[in,out] msg Data to shift
14482 !> \param[in] comm message passing environment identifier
14483 !> \param[in] displ_in displacements (?)
14484 !> \par Example
14485 !> msg will be moved from rank to rank+displ_in (in a circular way)
14486 !> \par Limitations
14487 !> * displ_in will be 1 by default (others not tested)
14488 !> * the message array needs to be the same size on all processes
14489 ! **************************************************************************************************
14490  SUBROUTINE mp_shift_d (msg, comm, displ_in)
14491 
14492  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
14493  CLASS(mp_comm_type), INTENT(IN) :: comm
14494  INTEGER, INTENT(IN), OPTIONAL :: displ_in
14495 
14496  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_d'
14497 
14498  INTEGER :: handle, ierror
14499 #if defined(__parallel)
14500  INTEGER :: displ, left, &
14501  msglen, myrank, nprocs, &
14502  right, tag
14503 #endif
14504 
14505  ierror = 0
14506  CALL mp_timeset(routinen, handle)
14507 
14508 #if defined(__parallel)
14509  CALL mpi_comm_rank(comm%handle, myrank, ierror)
14510  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
14511  CALL mpi_comm_size(comm%handle, nprocs, ierror)
14512  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
14513  IF (PRESENT(displ_in)) THEN
14514  displ = displ_in
14515  ELSE
14516  displ = 1
14517  END IF
14518  right = modulo(myrank + displ, nprocs)
14519  left = modulo(myrank - displ, nprocs)
14520  tag = 19
14521  msglen = SIZE(msg)
14522  CALL mpi_sendrecv_replace(msg, msglen, mpi_double_precision, right, tag, left, &
14523  tag, comm%handle, mpi_status_ignore, ierror)
14524  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
14525  CALL add_perf(perf_id=7, count=1, msg_size=msglen*real_8_size)
14526 #else
14527  mark_used(msg)
14528  mark_used(comm)
14529  mark_used(displ_in)
14530 #endif
14531  CALL mp_timestop(handle)
14532 
14533  END SUBROUTINE mp_shift_d
14534 
14535 ! **************************************************************************************************
14536 !> \brief All-to-all data exchange, rank-1 data of different sizes
14537 !> \param[in] sb Data to send
14538 !> \param[in] scount Data counts for data sent to other processes
14539 !> \param[in] sdispl Respective data offsets for data sent to process
14540 !> \param[in,out] rb Buffer into which to receive data
14541 !> \param[in] rcount Data counts for data received from other
14542 !> processes
14543 !> \param[in] rdispl Respective data offsets for data received from
14544 !> other processes
14545 !> \param[in] comm Message passing environment identifier
14546 !> \par MPI mapping
14547 !> mpi_alltoallv
14548 !> \par Array sizes
14549 !> The scount, rcount, and the sdispl and rdispl arrays have a
14550 !> size equal to the number of processes.
14551 !> \par Offsets
14552 !> Values in sdispl and rdispl start with 0.
14553 ! **************************************************************************************************
14554  SUBROUTINE mp_alltoall_d11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
14555 
14556  REAL(kind=real_8), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
14557  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
14558  REAL(kind=real_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
14559  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
14560  CLASS(mp_comm_type), INTENT(IN) :: comm
14561 
14562  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d11v'
14563 
14564  INTEGER :: handle
14565 #if defined(__parallel)
14566  INTEGER :: ierr, msglen
14567 #else
14568  INTEGER :: i
14569 #endif
14570 
14571  CALL mp_timeset(routinen, handle)
14572 
14573 #if defined(__parallel)
14574  CALL mpi_alltoallv(sb, scount, sdispl, mpi_double_precision, &
14575  rb, rcount, rdispl, mpi_double_precision, comm%handle, ierr)
14576  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
14577  msglen = sum(scount) + sum(rcount)
14578  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14579 #else
14580  mark_used(comm)
14581  mark_used(scount)
14582  mark_used(sdispl)
14583  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
14584  DO i = 1, rcount(1)
14585  rb(rdispl(1) + i) = sb(sdispl(1) + i)
14586  END DO
14587 #endif
14588  CALL mp_timestop(handle)
14589 
14590  END SUBROUTINE mp_alltoall_d11v
14591 
14592 ! **************************************************************************************************
14593 !> \brief All-to-all data exchange, rank-2 data of different sizes
14594 !> \param sb ...
14595 !> \param scount ...
14596 !> \param sdispl ...
14597 !> \param rb ...
14598 !> \param rcount ...
14599 !> \param rdispl ...
14600 !> \param comm ...
14601 !> \par MPI mapping
14602 !> mpi_alltoallv
14603 !> \note see mp_alltoall_d11v
14604 ! **************************************************************************************************
14605  SUBROUTINE mp_alltoall_d22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
14606 
14607  REAL(kind=real_8), DIMENSION(:, :), &
14608  INTENT(IN), CONTIGUOUS :: sb
14609  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
14610  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, &
14611  INTENT(INOUT) :: rb
14612  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
14613  CLASS(mp_comm_type), INTENT(IN) :: comm
14614 
14615  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d22v'
14616 
14617  INTEGER :: handle
14618 #if defined(__parallel)
14619  INTEGER :: ierr, msglen
14620 #endif
14621 
14622  CALL mp_timeset(routinen, handle)
14623 
14624 #if defined(__parallel)
14625  CALL mpi_alltoallv(sb, scount, sdispl, mpi_double_precision, &
14626  rb, rcount, rdispl, mpi_double_precision, comm%handle, ierr)
14627  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
14628  msglen = sum(scount) + sum(rcount)
14629  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*real_8_size)
14630 #else
14631  mark_used(comm)
14632  mark_used(scount)
14633  mark_used(sdispl)
14634  mark_used(rcount)
14635  mark_used(rdispl)
14636  rb = sb
14637 #endif
14638  CALL mp_timestop(handle)
14639 
14640  END SUBROUTINE mp_alltoall_d22v
14641 
14642 ! **************************************************************************************************
14643 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
14644 !> \param[in] sb array with data to send
14645 !> \param[out] rb array into which data is received
14646 !> \param[in] count number of elements to send/receive (product of the
14647 !> extents of the first two dimensions)
14648 !> \param[in] comm Message passing environment identifier
14649 !> \par Index meaning
14650 !> \par The first two indices specify the data while the last index counts
14651 !> the processes
14652 !> \par Sizes of ranks
14653 !> All processes have the same data size.
14654 !> \par MPI mapping
14655 !> mpi_alltoall
14656 ! **************************************************************************************************
14657  SUBROUTINE mp_alltoall_d (sb, rb, count, comm)
14658 
14659  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
14660  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
14661  INTEGER, INTENT(IN) :: count
14662  CLASS(mp_comm_type), INTENT(IN) :: comm
14663 
14664  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d'
14665 
14666  INTEGER :: handle
14667 #if defined(__parallel)
14668  INTEGER :: ierr, msglen, np
14669 #endif
14670 
14671  CALL mp_timeset(routinen, handle)
14672 
14673 #if defined(__parallel)
14674  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14675  rb, count, mpi_double_precision, comm%handle, ierr)
14676  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14677  CALL mpi_comm_size(comm%handle, np, ierr)
14678  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14679  msglen = 2*count*np
14680  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14681 #else
14682  mark_used(count)
14683  mark_used(comm)
14684  rb = sb
14685 #endif
14686  CALL mp_timestop(handle)
14687 
14688  END SUBROUTINE mp_alltoall_d
14689 
14690 ! **************************************************************************************************
14691 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
14692 !> \param sb ...
14693 !> \param rb ...
14694 !> \param count ...
14695 !> \param commp ...
14696 !> \note see mp_alltoall_d
14697 ! **************************************************************************************************
14698  SUBROUTINE mp_alltoall_d22(sb, rb, count, comm)
14699 
14700  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
14701  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
14702  INTEGER, INTENT(IN) :: count
14703  CLASS(mp_comm_type), INTENT(IN) :: comm
14704 
14705  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d22'
14706 
14707  INTEGER :: handle
14708 #if defined(__parallel)
14709  INTEGER :: ierr, msglen, np
14710 #endif
14711 
14712  CALL mp_timeset(routinen, handle)
14713 
14714 #if defined(__parallel)
14715  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14716  rb, count, mpi_double_precision, comm%handle, ierr)
14717  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14718  CALL mpi_comm_size(comm%handle, np, ierr)
14719  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14720  msglen = 2*SIZE(sb)*np
14721  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14722 #else
14723  mark_used(count)
14724  mark_used(comm)
14725  rb = sb
14726 #endif
14727  CALL mp_timestop(handle)
14728 
14729  END SUBROUTINE mp_alltoall_d22
14730 
14731 ! **************************************************************************************************
14732 !> \brief All-to-all data exchange, rank-3 data with equal sizes
14733 !> \param sb ...
14734 !> \param rb ...
14735 !> \param count ...
14736 !> \param comm ...
14737 !> \note see mp_alltoall_d
14738 ! **************************************************************************************************
14739  SUBROUTINE mp_alltoall_d33(sb, rb, count, comm)
14740 
14741  REAL(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
14742  REAL(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
14743  INTEGER, INTENT(IN) :: count
14744  CLASS(mp_comm_type), INTENT(IN) :: comm
14745 
14746  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d33'
14747 
14748  INTEGER :: handle
14749 #if defined(__parallel)
14750  INTEGER :: ierr, msglen, np
14751 #endif
14752 
14753  CALL mp_timeset(routinen, handle)
14754 
14755 #if defined(__parallel)
14756  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14757  rb, count, mpi_double_precision, comm%handle, ierr)
14758  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14759  CALL mpi_comm_size(comm%handle, np, ierr)
14760  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14761  msglen = 2*count*np
14762  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14763 #else
14764  mark_used(count)
14765  mark_used(comm)
14766  rb = sb
14767 #endif
14768  CALL mp_timestop(handle)
14769 
14770  END SUBROUTINE mp_alltoall_d33
14771 
14772 ! **************************************************************************************************
14773 !> \brief All-to-all data exchange, rank 4 data, equal sizes
14774 !> \param sb ...
14775 !> \param rb ...
14776 !> \param count ...
14777 !> \param comm ...
14778 !> \note see mp_alltoall_d
14779 ! **************************************************************************************************
14780  SUBROUTINE mp_alltoall_d44(sb, rb, count, comm)
14781 
14782  REAL(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
14783  INTENT(IN) :: sb
14784  REAL(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
14785  INTENT(OUT) :: rb
14786  INTEGER, INTENT(IN) :: count
14787  CLASS(mp_comm_type), INTENT(IN) :: comm
14788 
14789  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d44'
14790 
14791  INTEGER :: handle
14792 #if defined(__parallel)
14793  INTEGER :: ierr, msglen, np
14794 #endif
14795 
14796  CALL mp_timeset(routinen, handle)
14797 
14798 #if defined(__parallel)
14799  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14800  rb, count, mpi_double_precision, comm%handle, ierr)
14801  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14802  CALL mpi_comm_size(comm%handle, np, ierr)
14803  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14804  msglen = 2*count*np
14805  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14806 #else
14807  mark_used(count)
14808  mark_used(comm)
14809  rb = sb
14810 #endif
14811  CALL mp_timestop(handle)
14812 
14813  END SUBROUTINE mp_alltoall_d44
14814 
14815 ! **************************************************************************************************
14816 !> \brief All-to-all data exchange, rank 5 data, equal sizes
14817 !> \param sb ...
14818 !> \param rb ...
14819 !> \param count ...
14820 !> \param comm ...
14821 !> \note see mp_alltoall_d
14822 ! **************************************************************************************************
14823  SUBROUTINE mp_alltoall_d55(sb, rb, count, comm)
14824 
14825  REAL(kind=real_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
14826  INTENT(IN) :: sb
14827  REAL(kind=real_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
14828  INTENT(OUT) :: rb
14829  INTEGER, INTENT(IN) :: count
14830  CLASS(mp_comm_type), INTENT(IN) :: comm
14831 
14832  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d55'
14833 
14834  INTEGER :: handle
14835 #if defined(__parallel)
14836  INTEGER :: ierr, msglen, np
14837 #endif
14838 
14839  CALL mp_timeset(routinen, handle)
14840 
14841 #if defined(__parallel)
14842  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14843  rb, count, mpi_double_precision, comm%handle, ierr)
14844  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14845  CALL mpi_comm_size(comm%handle, np, ierr)
14846  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14847  msglen = 2*count*np
14848  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14849 #else
14850  mark_used(count)
14851  mark_used(comm)
14852  rb = sb
14853 #endif
14854  CALL mp_timestop(handle)
14855 
14856  END SUBROUTINE mp_alltoall_d55
14857 
14858 ! **************************************************************************************************
14859 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
14860 !> \param sb ...
14861 !> \param rb ...
14862 !> \param count ...
14863 !> \param comm ...
14864 !> \note see mp_alltoall_d
14865 !> \note User must ensure size consistency.
14866 ! **************************************************************************************************
14867  SUBROUTINE mp_alltoall_d45(sb, rb, count, comm)
14868 
14869  REAL(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
14870  INTENT(IN) :: sb
14871  REAL(kind=real_8), &
14872  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
14873  INTEGER, INTENT(IN) :: count
14874  CLASS(mp_comm_type), INTENT(IN) :: comm
14875 
14876  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d45'
14877 
14878  INTEGER :: handle
14879 #if defined(__parallel)
14880  INTEGER :: ierr, msglen, np
14881 #endif
14882 
14883  CALL mp_timeset(routinen, handle)
14884 
14885 #if defined(__parallel)
14886  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14887  rb, count, mpi_double_precision, comm%handle, ierr)
14888  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14889  CALL mpi_comm_size(comm%handle, np, ierr)
14890  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14891  msglen = 2*count*np
14892  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14893 #else
14894  mark_used(count)
14895  mark_used(comm)
14896  rb = reshape(sb, shape(rb))
14897 #endif
14898  CALL mp_timestop(handle)
14899 
14900  END SUBROUTINE mp_alltoall_d45
14901 
14902 ! **************************************************************************************************
14903 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
14904 !> \param sb ...
14905 !> \param rb ...
14906 !> \param count ...
14907 !> \param comm ...
14908 !> \note see mp_alltoall_d
14909 !> \note User must ensure size consistency.
14910 ! **************************************************************************************************
14911  SUBROUTINE mp_alltoall_d34(sb, rb, count, comm)
14912 
14913  REAL(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, &
14914  INTENT(IN) :: sb
14915  REAL(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
14916  INTENT(OUT) :: rb
14917  INTEGER, INTENT(IN) :: count
14918  CLASS(mp_comm_type), INTENT(IN) :: comm
14919 
14920  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d34'
14921 
14922  INTEGER :: handle
14923 #if defined(__parallel)
14924  INTEGER :: ierr, msglen, np
14925 #endif
14926 
14927  CALL mp_timeset(routinen, handle)
14928 
14929 #if defined(__parallel)
14930  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14931  rb, count, mpi_double_precision, comm%handle, ierr)
14932  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14933  CALL mpi_comm_size(comm%handle, np, ierr)
14934  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14935  msglen = 2*count*np
14936  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14937 #else
14938  mark_used(count)
14939  mark_used(comm)
14940  rb = reshape(sb, shape(rb))
14941 #endif
14942  CALL mp_timestop(handle)
14943 
14944  END SUBROUTINE mp_alltoall_d34
14945 
14946 ! **************************************************************************************************
14947 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
14948 !> \param sb ...
14949 !> \param rb ...
14950 !> \param count ...
14951 !> \param comm ...
14952 !> \note see mp_alltoall_d
14953 !> \note User must ensure size consistency.
14954 ! **************************************************************************************************
14955  SUBROUTINE mp_alltoall_d54(sb, rb, count, comm)
14956 
14957  REAL(kind=real_8), &
14958  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
14959  REAL(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
14960  INTENT(OUT) :: rb
14961  INTEGER, INTENT(IN) :: count
14962  CLASS(mp_comm_type), INTENT(IN) :: comm
14963 
14964  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_d54'
14965 
14966  INTEGER :: handle
14967 #if defined(__parallel)
14968  INTEGER :: ierr, msglen, np
14969 #endif
14970 
14971  CALL mp_timeset(routinen, handle)
14972 
14973 #if defined(__parallel)
14974  CALL mpi_alltoall(sb, count, mpi_double_precision, &
14975  rb, count, mpi_double_precision, comm%handle, ierr)
14976  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
14977  CALL mpi_comm_size(comm%handle, np, ierr)
14978  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
14979  msglen = 2*count*np
14980  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_8_size)
14981 #else
14982  mark_used(count)
14983  mark_used(comm)
14984  rb = reshape(sb, shape(rb))
14985 #endif
14986  CALL mp_timestop(handle)
14987 
14988  END SUBROUTINE mp_alltoall_d54
14989 
14990 ! **************************************************************************************************
14991 !> \brief Send one datum to another process
14992 !> \param[in] msg Scalar to send
14993 !> \param[in] dest Destination process
14994 !> \param[in] tag Transfer identifier
14995 !> \param[in] comm Message passing environment identifier
14996 !> \par MPI mapping
14997 !> mpi_send
14998 ! **************************************************************************************************
14999  SUBROUTINE mp_send_d (msg, dest, tag, comm)
15000  REAL(kind=real_8), INTENT(IN) :: msg
15001  INTEGER, INTENT(IN) :: dest, tag
15002  CLASS(mp_comm_type), INTENT(IN) :: comm
15003 
15004  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_d'
15005 
15006  INTEGER :: handle
15007 #if defined(__parallel)
15008  INTEGER :: ierr, msglen
15009 #endif
15010 
15011  CALL mp_timeset(routinen, handle)
15012 
15013 #if defined(__parallel)
15014  msglen = 1
15015  CALL mpi_send(msg, msglen, mpi_double_precision, dest, tag, comm%handle, ierr)
15016  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
15017  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_8_size)
15018 #else
15019  mark_used(msg)
15020  mark_used(dest)
15021  mark_used(tag)
15022  mark_used(comm)
15023  ! only defined in parallel
15024  cpabort("not in parallel mode")
15025 #endif
15026  CALL mp_timestop(handle)
15027  END SUBROUTINE mp_send_d
15028 
15029 ! **************************************************************************************************
15030 !> \brief Send rank-1 data to another process
15031 !> \param[in] msg Rank-1 data to send
15032 !> \param dest ...
15033 !> \param tag ...
15034 !> \param comm ...
15035 !> \note see mp_send_d
15036 ! **************************************************************************************************
15037  SUBROUTINE mp_send_dv(msg, dest, tag, comm)
15038  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
15039  INTEGER, INTENT(IN) :: dest, tag
15040  CLASS(mp_comm_type), INTENT(IN) :: comm
15041 
15042  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_dv'
15043 
15044  INTEGER :: handle
15045 #if defined(__parallel)
15046  INTEGER :: ierr, msglen
15047 #endif
15048 
15049  CALL mp_timeset(routinen, handle)
15050 
15051 #if defined(__parallel)
15052  msglen = SIZE(msg)
15053  CALL mpi_send(msg, msglen, mpi_double_precision, dest, tag, comm%handle, ierr)
15054  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
15055  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_8_size)
15056 #else
15057  mark_used(msg)
15058  mark_used(dest)
15059  mark_used(tag)
15060  mark_used(comm)
15061  ! only defined in parallel
15062  cpabort("not in parallel mode")
15063 #endif
15064  CALL mp_timestop(handle)
15065  END SUBROUTINE mp_send_dv
15066 
15067 ! **************************************************************************************************
15068 !> \brief Send rank-2 data to another process
15069 !> \param[in] msg Rank-2 data to send
15070 !> \param dest ...
15071 !> \param tag ...
15072 !> \param comm ...
15073 !> \note see mp_send_d
15074 ! **************************************************************************************************
15075  SUBROUTINE mp_send_dm2(msg, dest, tag, comm)
15076  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
15077  INTEGER, INTENT(IN) :: dest, tag
15078  CLASS(mp_comm_type), INTENT(IN) :: comm
15079 
15080  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_dm2'
15081 
15082  INTEGER :: handle
15083 #if defined(__parallel)
15084  INTEGER :: ierr, msglen
15085 #endif
15086 
15087  CALL mp_timeset(routinen, handle)
15088 
15089 #if defined(__parallel)
15090  msglen = SIZE(msg)
15091  CALL mpi_send(msg, msglen, mpi_double_precision, dest, tag, comm%handle, ierr)
15092  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
15093  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_8_size)
15094 #else
15095  mark_used(msg)
15096  mark_used(dest)
15097  mark_used(tag)
15098  mark_used(comm)
15099  ! only defined in parallel
15100  cpabort("not in parallel mode")
15101 #endif
15102  CALL mp_timestop(handle)
15103  END SUBROUTINE mp_send_dm2
15104 
15105 ! **************************************************************************************************
15106 !> \brief Send rank-3 data to another process
15107 !> \param[in] msg Rank-3 data to send
15108 !> \param dest ...
15109 !> \param tag ...
15110 !> \param comm ...
15111 !> \note see mp_send_d
15112 ! **************************************************************************************************
15113  SUBROUTINE mp_send_dm3(msg, dest, tag, comm)
15114  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
15115  INTEGER, INTENT(IN) :: dest, tag
15116  CLASS(mp_comm_type), INTENT(IN) :: comm
15117 
15118  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
15119 
15120  INTEGER :: handle
15121 #if defined(__parallel)
15122  INTEGER :: ierr, msglen
15123 #endif
15124 
15125  CALL mp_timeset(routinen, handle)
15126 
15127 #if defined(__parallel)
15128  msglen = SIZE(msg)
15129  CALL mpi_send(msg, msglen, mpi_double_precision, dest, tag, comm%handle, ierr)
15130  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
15131  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_8_size)
15132 #else
15133  mark_used(msg)
15134  mark_used(dest)
15135  mark_used(tag)
15136  mark_used(comm)
15137  ! only defined in parallel
15138  cpabort("not in parallel mode")
15139 #endif
15140  CALL mp_timestop(handle)
15141  END SUBROUTINE mp_send_dm3
15142 
15143 ! **************************************************************************************************
15144 !> \brief Receive one datum from another process
15145 !> \param[in,out] msg Place received data into this variable
15146 !> \param[in,out] source Process to receive from
15147 !> \param[in,out] tag Transfer identifier
15148 !> \param[in] comm Message passing environment identifier
15149 !> \par MPI mapping
15150 !> mpi_send
15151 ! **************************************************************************************************
15152  SUBROUTINE mp_recv_d (msg, source, tag, comm)
15153  REAL(kind=real_8), INTENT(INOUT) :: msg
15154  INTEGER, INTENT(INOUT) :: source, tag
15155  CLASS(mp_comm_type), INTENT(IN) :: comm
15156 
15157  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_d'
15158 
15159  INTEGER :: handle
15160 #if defined(__parallel)
15161  INTEGER :: ierr, msglen
15162  mpi_status_type :: status
15163 #endif
15164 
15165  CALL mp_timeset(routinen, handle)
15166 
15167 #if defined(__parallel)
15168  msglen = 1
15169  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
15170  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, mpi_status_ignore, ierr)
15171  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15172  ELSE
15173  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, status, ierr)
15174  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15175  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_8_size)
15176  source = status mpi_status_extract(mpi_source)
15177  tag = status mpi_status_extract(mpi_tag)
15178  END IF
15179 #else
15180  mark_used(msg)
15181  mark_used(source)
15182  mark_used(tag)
15183  mark_used(comm)
15184  ! only defined in parallel
15185  cpabort("not in parallel mode")
15186 #endif
15187  CALL mp_timestop(handle)
15188  END SUBROUTINE mp_recv_d
15189 
15190 ! **************************************************************************************************
15191 !> \brief Receive rank-1 data from another process
15192 !> \param[in,out] msg Place received data into this rank-1 array
15193 !> \param source ...
15194 !> \param tag ...
15195 !> \param comm ...
15196 !> \note see mp_recv_d
15197 ! **************************************************************************************************
15198  SUBROUTINE mp_recv_dv(msg, source, tag, comm)
15199  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
15200  INTEGER, INTENT(INOUT) :: source, tag
15201  CLASS(mp_comm_type), INTENT(IN) :: comm
15202 
15203  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_dv'
15204 
15205  INTEGER :: handle
15206 #if defined(__parallel)
15207  INTEGER :: ierr, msglen
15208  mpi_status_type :: status
15209 #endif
15210 
15211  CALL mp_timeset(routinen, handle)
15212 
15213 #if defined(__parallel)
15214  msglen = SIZE(msg)
15215  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
15216  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, mpi_status_ignore, ierr)
15217  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15218  ELSE
15219  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, status, ierr)
15220  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15221  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_8_size)
15222  source = status mpi_status_extract(mpi_source)
15223  tag = status mpi_status_extract(mpi_tag)
15224  END IF
15225 #else
15226  mark_used(msg)
15227  mark_used(source)
15228  mark_used(tag)
15229  mark_used(comm)
15230  ! only defined in parallel
15231  cpabort("not in parallel mode")
15232 #endif
15233  CALL mp_timestop(handle)
15234  END SUBROUTINE mp_recv_dv
15235 
15236 ! **************************************************************************************************
15237 !> \brief Receive rank-2 data from another process
15238 !> \param[in,out] msg Place received data into this rank-2 array
15239 !> \param source ...
15240 !> \param tag ...
15241 !> \param comm ...
15242 !> \note see mp_recv_d
15243 ! **************************************************************************************************
15244  SUBROUTINE mp_recv_dm2(msg, source, tag, comm)
15245  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
15246  INTEGER, INTENT(INOUT) :: source, tag
15247  CLASS(mp_comm_type), INTENT(IN) :: comm
15248 
15249  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_dm2'
15250 
15251  INTEGER :: handle
15252 #if defined(__parallel)
15253  INTEGER :: ierr, msglen
15254  mpi_status_type :: status
15255 #endif
15256 
15257  CALL mp_timeset(routinen, handle)
15258 
15259 #if defined(__parallel)
15260  msglen = SIZE(msg)
15261  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
15262  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, mpi_status_ignore, ierr)
15263  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15264  ELSE
15265  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, status, ierr)
15266  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15267  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_8_size)
15268  source = status mpi_status_extract(mpi_source)
15269  tag = status mpi_status_extract(mpi_tag)
15270  END IF
15271 #else
15272  mark_used(msg)
15273  mark_used(source)
15274  mark_used(tag)
15275  mark_used(comm)
15276  ! only defined in parallel
15277  cpabort("not in parallel mode")
15278 #endif
15279  CALL mp_timestop(handle)
15280  END SUBROUTINE mp_recv_dm2
15281 
15282 ! **************************************************************************************************
15283 !> \brief Receive rank-3 data from another process
15284 !> \param[in,out] msg Place received data into this rank-3 array
15285 !> \param source ...
15286 !> \param tag ...
15287 !> \param comm ...
15288 !> \note see mp_recv_d
15289 ! **************************************************************************************************
15290  SUBROUTINE mp_recv_dm3(msg, source, tag, comm)
15291  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
15292  INTEGER, INTENT(INOUT) :: source, tag
15293  CLASS(mp_comm_type), INTENT(IN) :: comm
15294 
15295  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_dm3'
15296 
15297  INTEGER :: handle
15298 #if defined(__parallel)
15299  INTEGER :: ierr, msglen
15300  mpi_status_type :: status
15301 #endif
15302 
15303  CALL mp_timeset(routinen, handle)
15304 
15305 #if defined(__parallel)
15306  msglen = SIZE(msg)
15307  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
15308  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, mpi_status_ignore, ierr)
15309  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15310  ELSE
15311  CALL mpi_recv(msg, msglen, mpi_double_precision, source, tag, comm%handle, status, ierr)
15312  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
15313  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_8_size)
15314  source = status mpi_status_extract(mpi_source)
15315  tag = status mpi_status_extract(mpi_tag)
15316  END IF
15317 #else
15318  mark_used(msg)
15319  mark_used(source)
15320  mark_used(tag)
15321  mark_used(comm)
15322  ! only defined in parallel
15323  cpabort("not in parallel mode")
15324 #endif
15325  CALL mp_timestop(handle)
15326  END SUBROUTINE mp_recv_dm3
15327 
15328 ! **************************************************************************************************
15329 !> \brief Broadcasts a datum to all processes.
15330 !> \param[in] msg Datum to broadcast
15331 !> \param[in] source Processes which broadcasts
15332 !> \param[in] comm Message passing environment identifier
15333 !> \par MPI mapping
15334 !> mpi_bcast
15335 ! **************************************************************************************************
15336  SUBROUTINE mp_bcast_d (msg, source, comm)
15337  REAL(kind=real_8), INTENT(INOUT) :: msg
15338  INTEGER, INTENT(IN) :: source
15339  CLASS(mp_comm_type), INTENT(IN) :: comm
15340 
15341  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_d'
15342 
15343  INTEGER :: handle
15344 #if defined(__parallel)
15345  INTEGER :: ierr, msglen
15346 #endif
15347 
15348  CALL mp_timeset(routinen, handle)
15349 
15350 #if defined(__parallel)
15351  msglen = 1
15352  CALL mpi_bcast(msg, msglen, mpi_double_precision, source, comm%handle, ierr)
15353  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15354  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15355 #else
15356  mark_used(msg)
15357  mark_used(source)
15358  mark_used(comm)
15359 #endif
15360  CALL mp_timestop(handle)
15361  END SUBROUTINE mp_bcast_d
15362 
15363 ! **************************************************************************************************
15364 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
15365 !> \param[in] msg Datum to broadcast
15366 !> \param[in] comm Message passing environment identifier
15367 !> \par MPI mapping
15368 !> mpi_bcast
15369 ! **************************************************************************************************
15370  SUBROUTINE mp_bcast_d_src(msg, comm)
15371  REAL(kind=real_8), INTENT(INOUT) :: msg
15372  CLASS(mp_comm_type), INTENT(IN) :: comm
15373 
15374  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_d_src'
15375 
15376  INTEGER :: handle
15377 #if defined(__parallel)
15378  INTEGER :: ierr, msglen
15379 #endif
15380 
15381  CALL mp_timeset(routinen, handle)
15382 
15383 #if defined(__parallel)
15384  msglen = 1
15385  CALL mpi_bcast(msg, msglen, mpi_double_precision, comm%source, comm%handle, ierr)
15386  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15387  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15388 #else
15389  mark_used(msg)
15390  mark_used(comm)
15391 #endif
15392  CALL mp_timestop(handle)
15393  END SUBROUTINE mp_bcast_d_src
15394 
15395 ! **************************************************************************************************
15396 !> \brief Broadcasts a datum to all processes.
15397 !> \param[in] msg Datum to broadcast
15398 !> \param[in] source Processes which broadcasts
15399 !> \param[in] comm Message passing environment identifier
15400 !> \par MPI mapping
15401 !> mpi_bcast
15402 ! **************************************************************************************************
15403  SUBROUTINE mp_ibcast_d (msg, source, comm, request)
15404  REAL(kind=real_8), INTENT(INOUT) :: msg
15405  INTEGER, INTENT(IN) :: source
15406  CLASS(mp_comm_type), INTENT(IN) :: comm
15407  TYPE(mp_request_type), INTENT(OUT) :: request
15408 
15409  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_d'
15410 
15411  INTEGER :: handle
15412 #if defined(__parallel)
15413  INTEGER :: ierr, msglen
15414 #endif
15415 
15416  CALL mp_timeset(routinen, handle)
15417 
15418 #if defined(__parallel)
15419  msglen = 1
15420  CALL mpi_ibcast(msg, msglen, mpi_double_precision, source, comm%handle, request%handle, ierr)
15421  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
15422  CALL add_perf(perf_id=22, count=1, msg_size=msglen*real_8_size)
15423 #else
15424  mark_used(msg)
15425  mark_used(source)
15426  mark_used(comm)
15427  request = mp_request_null
15428 #endif
15429  CALL mp_timestop(handle)
15430  END SUBROUTINE mp_ibcast_d
15431 
15432 ! **************************************************************************************************
15433 !> \brief Broadcasts rank-1 data to all processes
15434 !> \param[in] msg Data to broadcast
15435 !> \param source ...
15436 !> \param comm ...
15437 !> \note see mp_bcast_d1
15438 ! **************************************************************************************************
15439  SUBROUTINE mp_bcast_dv(msg, source, comm)
15440  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
15441  INTEGER, INTENT(IN) :: source
15442  CLASS(mp_comm_type), INTENT(IN) :: comm
15443 
15444  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_dv'
15445 
15446  INTEGER :: handle
15447 #if defined(__parallel)
15448  INTEGER :: ierr, msglen
15449 #endif
15450 
15451  CALL mp_timeset(routinen, handle)
15452 
15453 #if defined(__parallel)
15454  msglen = SIZE(msg)
15455  CALL mpi_bcast(msg, msglen, mpi_double_precision, source, comm%handle, ierr)
15456  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15457  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15458 #else
15459  mark_used(msg)
15460  mark_used(source)
15461  mark_used(comm)
15462 #endif
15463  CALL mp_timestop(handle)
15464  END SUBROUTINE mp_bcast_dv
15465 
15466 ! **************************************************************************************************
15467 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
15468 !> \param[in] msg Data to broadcast
15469 !> \param comm ...
15470 !> \note see mp_bcast_d1
15471 ! **************************************************************************************************
15472  SUBROUTINE mp_bcast_dv_src(msg, comm)
15473  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
15474  CLASS(mp_comm_type), INTENT(IN) :: comm
15475 
15476  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_dv_src'
15477 
15478  INTEGER :: handle
15479 #if defined(__parallel)
15480  INTEGER :: ierr, msglen
15481 #endif
15482 
15483  CALL mp_timeset(routinen, handle)
15484 
15485 #if defined(__parallel)
15486  msglen = SIZE(msg)
15487  CALL mpi_bcast(msg, msglen, mpi_double_precision, comm%source, comm%handle, ierr)
15488  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15489  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15490 #else
15491  mark_used(msg)
15492  mark_used(comm)
15493 #endif
15494  CALL mp_timestop(handle)
15495  END SUBROUTINE mp_bcast_dv_src
15496 
15497 ! **************************************************************************************************
15498 !> \brief Broadcasts rank-1 data to all processes
15499 !> \param[in] msg Data to broadcast
15500 !> \param source ...
15501 !> \param comm ...
15502 !> \note see mp_bcast_d1
15503 ! **************************************************************************************************
15504  SUBROUTINE mp_ibcast_dv(msg, source, comm, request)
15505  REAL(kind=real_8), INTENT(INOUT) :: msg(:)
15506  INTEGER, INTENT(IN) :: source
15507  CLASS(mp_comm_type), INTENT(IN) :: comm
15508  TYPE(mp_request_type) :: request
15509 
15510  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_dv'
15511 
15512  INTEGER :: handle
15513 #if defined(__parallel)
15514  INTEGER :: ierr, msglen
15515 #endif
15516 
15517  CALL mp_timeset(routinen, handle)
15518 
15519 #if defined(__parallel)
15520 #if !defined(__GNUC__) || __GNUC__ >= 9
15521  cpassert(is_contiguous(msg))
15522 #endif
15523  msglen = SIZE(msg)
15524  CALL mpi_ibcast(msg, msglen, mpi_double_precision, source, comm%handle, request%handle, ierr)
15525  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
15526  CALL add_perf(perf_id=22, count=1, msg_size=msglen*real_8_size)
15527 #else
15528  mark_used(msg)
15529  mark_used(source)
15530  mark_used(comm)
15531  request = mp_request_null
15532 #endif
15533  CALL mp_timestop(handle)
15534  END SUBROUTINE mp_ibcast_dv
15535 
15536 ! **************************************************************************************************
15537 !> \brief Broadcasts rank-2 data to all processes
15538 !> \param[in] msg Data to broadcast
15539 !> \param source ...
15540 !> \param comm ...
15541 !> \note see mp_bcast_d1
15542 ! **************************************************************************************************
15543  SUBROUTINE mp_bcast_dm(msg, source, comm)
15544  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
15545  INTEGER, INTENT(IN) :: source
15546  CLASS(mp_comm_type), INTENT(IN) :: comm
15547 
15548  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_dm'
15549 
15550  INTEGER :: handle
15551 #if defined(__parallel)
15552  INTEGER :: ierr, msglen
15553 #endif
15554 
15555  CALL mp_timeset(routinen, handle)
15556 
15557 #if defined(__parallel)
15558  msglen = SIZE(msg)
15559  CALL mpi_bcast(msg, msglen, mpi_double_precision, source, comm%handle, ierr)
15560  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15561  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15562 #else
15563  mark_used(msg)
15564  mark_used(source)
15565  mark_used(comm)
15566 #endif
15567  CALL mp_timestop(handle)
15568  END SUBROUTINE mp_bcast_dm
15569 
15570 ! **************************************************************************************************
15571 !> \brief Broadcasts rank-2 data to all processes
15572 !> \param[in] msg Data to broadcast
15573 !> \param source ...
15574 !> \param comm ...
15575 !> \note see mp_bcast_d1
15576 ! **************************************************************************************************
15577  SUBROUTINE mp_bcast_dm_src(msg, comm)
15578  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
15579  CLASS(mp_comm_type), INTENT(IN) :: comm
15580 
15581  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_dm_src'
15582 
15583  INTEGER :: handle
15584 #if defined(__parallel)
15585  INTEGER :: ierr, msglen
15586 #endif
15587 
15588  CALL mp_timeset(routinen, handle)
15589 
15590 #if defined(__parallel)
15591  msglen = SIZE(msg)
15592  CALL mpi_bcast(msg, msglen, mpi_double_precision, comm%source, comm%handle, ierr)
15593  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15594  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15595 #else
15596  mark_used(msg)
15597  mark_used(comm)
15598 #endif
15599  CALL mp_timestop(handle)
15600  END SUBROUTINE mp_bcast_dm_src
15601 
15602 ! **************************************************************************************************
15603 !> \brief Broadcasts rank-3 data to all processes
15604 !> \param[in] msg Data to broadcast
15605 !> \param source ...
15606 !> \param comm ...
15607 !> \note see mp_bcast_d1
15608 ! **************************************************************************************************
15609  SUBROUTINE mp_bcast_d3(msg, source, comm)
15610  REAL(kind=real_8), CONTIGUOUS :: msg(:, :, :)
15611  INTEGER, INTENT(IN) :: source
15612  CLASS(mp_comm_type), INTENT(IN) :: comm
15613 
15614  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_d3'
15615 
15616  INTEGER :: handle
15617 #if defined(__parallel)
15618  INTEGER :: ierr, msglen
15619 #endif
15620 
15621  CALL mp_timeset(routinen, handle)
15622 
15623 #if defined(__parallel)
15624  msglen = SIZE(msg)
15625  CALL mpi_bcast(msg, msglen, mpi_double_precision, source, comm%handle, ierr)
15626  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15627  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15628 #else
15629  mark_used(msg)
15630  mark_used(source)
15631  mark_used(comm)
15632 #endif
15633  CALL mp_timestop(handle)
15634  END SUBROUTINE mp_bcast_d3
15635 
15636 ! **************************************************************************************************
15637 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
15638 !> \param[in] msg Data to broadcast
15639 !> \param source ...
15640 !> \param comm ...
15641 !> \note see mp_bcast_d1
15642 ! **************************************************************************************************
15643  SUBROUTINE mp_bcast_d3_src(msg, comm)
15644  REAL(kind=real_8), CONTIGUOUS :: msg(:, :, :)
15645  CLASS(mp_comm_type), INTENT(IN) :: comm
15646 
15647  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_d3_src'
15648 
15649  INTEGER :: handle
15650 #if defined(__parallel)
15651  INTEGER :: ierr, msglen
15652 #endif
15653 
15654  CALL mp_timeset(routinen, handle)
15655 
15656 #if defined(__parallel)
15657  msglen = SIZE(msg)
15658  CALL mpi_bcast(msg, msglen, mpi_double_precision, comm%source, comm%handle, ierr)
15659  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
15660  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_8_size)
15661 #else
15662  mark_used(msg)
15663  mark_used(comm)
15664 #endif
15665  CALL mp_timestop(handle)
15666  END SUBROUTINE mp_bcast_d3_src
15667 
15668 ! **************************************************************************************************
15669 !> \brief Sums a datum from all processes with result left on all processes.
15670 !> \param[in,out] msg Datum to sum (input) and result (output)
15671 !> \param[in] comm Message passing environment identifier
15672 !> \par MPI mapping
15673 !> mpi_allreduce
15674 ! **************************************************************************************************
15675  SUBROUTINE mp_sum_d (msg, comm)
15676  REAL(kind=real_8), INTENT(INOUT) :: msg
15677  CLASS(mp_comm_type), INTENT(IN) :: comm
15678 
15679  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_d'
15680 
15681  INTEGER :: handle
15682 #if defined(__parallel)
15683  INTEGER :: ierr, msglen
15684 #endif
15685 
15686  CALL mp_timeset(routinen, handle)
15687 
15688 #if defined(__parallel)
15689  msglen = 1
15690  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
15691  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
15692  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15693 #else
15694  mark_used(msg)
15695  mark_used(comm)
15696 #endif
15697  CALL mp_timestop(handle)
15698  END SUBROUTINE mp_sum_d
15699 
15700 ! **************************************************************************************************
15701 !> \brief Element-wise sum of a rank-1 array on all processes.
15702 !> \param[in,out] msg Vector to sum and result
15703 !> \param comm ...
15704 !> \note see mp_sum_d
15705 ! **************************************************************************************************
15706  SUBROUTINE mp_sum_dv(msg, comm)
15707  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
15708  CLASS(mp_comm_type), INTENT(IN) :: comm
15709 
15710  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_dv'
15711 
15712  INTEGER :: handle
15713 #if defined(__parallel)
15714  INTEGER :: ierr, msglen
15715 #endif
15716 
15717  CALL mp_timeset(routinen, handle)
15718 
15719 #if defined(__parallel)
15720  msglen = SIZE(msg)
15721  IF (msglen > 0) THEN
15722  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
15723  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
15724  END IF
15725  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15726 #else
15727  mark_used(msg)
15728  mark_used(comm)
15729 #endif
15730  CALL mp_timestop(handle)
15731  END SUBROUTINE mp_sum_dv
15732 
15733 ! **************************************************************************************************
15734 !> \brief Element-wise sum of a rank-1 array on all processes.
15735 !> \param[in,out] msg Vector to sum and result
15736 !> \param comm ...
15737 !> \note see mp_sum_d
15738 ! **************************************************************************************************
15739  SUBROUTINE mp_isum_dv(msg, comm, request)
15740  REAL(kind=real_8), INTENT(INOUT) :: msg(:)
15741  CLASS(mp_comm_type), INTENT(IN) :: comm
15742  TYPE(mp_request_type), INTENT(OUT) :: request
15743 
15744  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_dv'
15745 
15746  INTEGER :: handle
15747 #if defined(__parallel)
15748  INTEGER :: ierr, msglen
15749 #endif
15750 
15751  CALL mp_timeset(routinen, handle)
15752 
15753 #if defined(__parallel)
15754 #if !defined(__GNUC__) || __GNUC__ >= 9
15755  cpassert(is_contiguous(msg))
15756 #endif
15757  msglen = SIZE(msg)
15758  IF (msglen > 0) THEN
15759  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_sum, comm%handle, request%handle, ierr)
15760  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
15761  ELSE
15762  request = mp_request_null
15763  END IF
15764  CALL add_perf(perf_id=23, count=1, msg_size=msglen*real_8_size)
15765 #else
15766  mark_used(msg)
15767  mark_used(comm)
15768  request = mp_request_null
15769 #endif
15770  CALL mp_timestop(handle)
15771  END SUBROUTINE mp_isum_dv
15772 
15773 ! **************************************************************************************************
15774 !> \brief Element-wise sum of a rank-2 array on all processes.
15775 !> \param[in] msg Matrix to sum and result
15776 !> \param comm ...
15777 !> \note see mp_sum_d
15778 ! **************************************************************************************************
15779  SUBROUTINE mp_sum_dm(msg, comm)
15780  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
15781  CLASS(mp_comm_type), INTENT(IN) :: comm
15782 
15783  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_dm'
15784 
15785  INTEGER :: handle
15786 #if defined(__parallel)
15787  INTEGER, PARAMETER :: max_msg = 2**25
15788  INTEGER :: ierr, m1, msglen, step, msglensum
15789 #endif
15790 
15791  CALL mp_timeset(routinen, handle)
15792 
15793 #if defined(__parallel)
15794  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
15795  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
15796  msglensum = 0
15797  DO m1 = lbound(msg, 2), ubound(msg, 2), step
15798  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
15799  msglensum = msglensum + msglen
15800  IF (msglen > 0) THEN
15801  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
15802  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
15803  END IF
15804  END DO
15805  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*real_8_size)
15806 #else
15807  mark_used(msg)
15808  mark_used(comm)
15809 #endif
15810  CALL mp_timestop(handle)
15811  END SUBROUTINE mp_sum_dm
15812 
15813 ! **************************************************************************************************
15814 !> \brief Element-wise sum of a rank-3 array on all processes.
15815 !> \param[in] msg Array to sum and result
15816 !> \param comm ...
15817 !> \note see mp_sum_d
15818 ! **************************************************************************************************
15819  SUBROUTINE mp_sum_dm3(msg, comm)
15820  REAL(kind=real_8), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
15821  CLASS(mp_comm_type), INTENT(IN) :: comm
15822 
15823  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_dm3'
15824 
15825  INTEGER :: handle
15826 #if defined(__parallel)
15827  INTEGER :: ierr, msglen
15828 #endif
15829 
15830  CALL mp_timeset(routinen, handle)
15831 
15832 #if defined(__parallel)
15833  msglen = SIZE(msg)
15834  IF (msglen > 0) THEN
15835  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
15836  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
15837  END IF
15838  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15839 #else
15840  mark_used(msg)
15841  mark_used(comm)
15842 #endif
15843  CALL mp_timestop(handle)
15844  END SUBROUTINE mp_sum_dm3
15845 
15846 ! **************************************************************************************************
15847 !> \brief Element-wise sum of a rank-4 array on all processes.
15848 !> \param[in] msg Array to sum and result
15849 !> \param comm ...
15850 !> \note see mp_sum_d
15851 ! **************************************************************************************************
15852  SUBROUTINE mp_sum_dm4(msg, comm)
15853  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
15854  CLASS(mp_comm_type), INTENT(IN) :: comm
15855 
15856  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_dm4'
15857 
15858  INTEGER :: handle
15859 #if defined(__parallel)
15860  INTEGER :: ierr, msglen
15861 #endif
15862 
15863  CALL mp_timeset(routinen, handle)
15864 
15865 #if defined(__parallel)
15866  msglen = SIZE(msg)
15867  IF (msglen > 0) THEN
15868  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
15869  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
15870  END IF
15871  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15872 #else
15873  mark_used(msg)
15874  mark_used(comm)
15875 #endif
15876  CALL mp_timestop(handle)
15877  END SUBROUTINE mp_sum_dm4
15878 
15879 ! **************************************************************************************************
15880 !> \brief Element-wise sum of data from all processes with result left only on
15881 !> one.
15882 !> \param[in,out] msg Vector to sum (input) and (only on process root)
15883 !> result (output)
15884 !> \param root ...
15885 !> \param[in] comm Message passing environment identifier
15886 !> \par MPI mapping
15887 !> mpi_reduce
15888 ! **************************************************************************************************
15889  SUBROUTINE mp_sum_root_dv(msg, root, comm)
15890  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
15891  INTEGER, INTENT(IN) :: root
15892  CLASS(mp_comm_type), INTENT(IN) :: comm
15893 
15894  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_dv'
15895 
15896  INTEGER :: handle
15897 #if defined(__parallel)
15898  INTEGER :: ierr, m1, msglen, taskid
15899  REAL(kind=real_8), ALLOCATABLE :: res(:)
15900 #endif
15901 
15902  CALL mp_timeset(routinen, handle)
15903 
15904 #if defined(__parallel)
15905  msglen = SIZE(msg)
15906  CALL mpi_comm_rank(comm%handle, taskid, ierr)
15907  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
15908  IF (msglen > 0) THEN
15909  m1 = SIZE(msg, 1)
15910  ALLOCATE (res(m1))
15911  CALL mpi_reduce(msg, res, msglen, mpi_double_precision, mpi_sum, &
15912  root, comm%handle, ierr)
15913  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
15914  IF (taskid == root) THEN
15915  msg = res
15916  END IF
15917  DEALLOCATE (res)
15918  END IF
15919  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15920 #else
15921  mark_used(msg)
15922  mark_used(root)
15923  mark_used(comm)
15924 #endif
15925  CALL mp_timestop(handle)
15926  END SUBROUTINE mp_sum_root_dv
15927 
15928 ! **************************************************************************************************
15929 !> \brief Element-wise sum of data from all processes with result left only on
15930 !> one.
15931 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
15932 !> result (output)
15933 !> \param root ...
15934 !> \param comm ...
15935 !> \note see mp_sum_root_dv
15936 ! **************************************************************************************************
15937  SUBROUTINE mp_sum_root_dm(msg, root, comm)
15938  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
15939  INTEGER, INTENT(IN) :: root
15940  CLASS(mp_comm_type), INTENT(IN) :: comm
15941 
15942  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
15943 
15944  INTEGER :: handle
15945 #if defined(__parallel)
15946  INTEGER :: ierr, m1, m2, msglen, taskid
15947  REAL(kind=real_8), ALLOCATABLE :: res(:, :)
15948 #endif
15949 
15950  CALL mp_timeset(routinen, handle)
15951 
15952 #if defined(__parallel)
15953  msglen = SIZE(msg)
15954  CALL mpi_comm_rank(comm%handle, taskid, ierr)
15955  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
15956  IF (msglen > 0) THEN
15957  m1 = SIZE(msg, 1)
15958  m2 = SIZE(msg, 2)
15959  ALLOCATE (res(m1, m2))
15960  CALL mpi_reduce(msg, res, msglen, mpi_double_precision, mpi_sum, root, comm%handle, ierr)
15961  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
15962  IF (taskid == root) THEN
15963  msg = res
15964  END IF
15965  DEALLOCATE (res)
15966  END IF
15967  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
15968 #else
15969  mark_used(root)
15970  mark_used(msg)
15971  mark_used(comm)
15972 #endif
15973  CALL mp_timestop(handle)
15974  END SUBROUTINE mp_sum_root_dm
15975 
15976 ! **************************************************************************************************
15977 !> \brief Partial sum of data from all processes with result on each process.
15978 !> \param[in] msg Matrix to sum (input)
15979 !> \param[out] res Matrix containing result (output)
15980 !> \param[in] comm Message passing environment identifier
15981 ! **************************************************************************************************
15982  SUBROUTINE mp_sum_partial_dm(msg, res, comm)
15983  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
15984  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: res(:, :)
15985  CLASS(mp_comm_type), INTENT(IN) :: comm
15986 
15987  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_dm'
15988 
15989  INTEGER :: handle
15990 #if defined(__parallel)
15991  INTEGER :: ierr, msglen, taskid
15992 #endif
15993 
15994  CALL mp_timeset(routinen, handle)
15995 
15996 #if defined(__parallel)
15997  msglen = SIZE(msg)
15998  CALL mpi_comm_rank(comm%handle, taskid, ierr)
15999  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
16000  IF (msglen > 0) THEN
16001  CALL mpi_scan(msg, res, msglen, mpi_double_precision, mpi_sum, comm%handle, ierr)
16002  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
16003  END IF
16004  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16005  ! perf_id is same as for other summation routines
16006 #else
16007  res = msg
16008  mark_used(comm)
16009 #endif
16010  CALL mp_timestop(handle)
16011  END SUBROUTINE mp_sum_partial_dm
16012 
16013 ! **************************************************************************************************
16014 !> \brief Finds the maximum of a datum with the result left on all processes.
16015 !> \param[in,out] msg Find maximum among these data (input) and
16016 !> maximum (output)
16017 !> \param[in] comm Message passing environment identifier
16018 !> \par MPI mapping
16019 !> mpi_allreduce
16020 ! **************************************************************************************************
16021  SUBROUTINE mp_max_d (msg, comm)
16022  REAL(kind=real_8), INTENT(INOUT) :: msg
16023  CLASS(mp_comm_type), INTENT(IN) :: comm
16024 
16025  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_d'
16026 
16027  INTEGER :: handle
16028 #if defined(__parallel)
16029  INTEGER :: ierr, msglen
16030 #endif
16031 
16032  CALL mp_timeset(routinen, handle)
16033 
16034 #if defined(__parallel)
16035  msglen = 1
16036  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_max, comm%handle, ierr)
16037  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16038  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16039 #else
16040  mark_used(msg)
16041  mark_used(comm)
16042 #endif
16043  CALL mp_timestop(handle)
16044  END SUBROUTINE mp_max_d
16045 
16046 ! **************************************************************************************************
16047 !> \brief Finds the maximum of a datum with the result left on all processes.
16048 !> \param[in,out] msg Find maximum among these data (input) and
16049 !> maximum (output)
16050 !> \param[in] comm Message passing environment identifier
16051 !> \par MPI mapping
16052 !> mpi_allreduce
16053 ! **************************************************************************************************
16054  SUBROUTINE mp_max_root_d (msg, root, comm)
16055  REAL(kind=real_8), INTENT(INOUT) :: msg
16056  INTEGER, INTENT(IN) :: root
16057  CLASS(mp_comm_type), INTENT(IN) :: comm
16058 
16059  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_d'
16060 
16061  INTEGER :: handle
16062 #if defined(__parallel)
16063  INTEGER :: ierr, msglen
16064  REAL(kind=real_8) :: res
16065 #endif
16066 
16067  CALL mp_timeset(routinen, handle)
16068 
16069 #if defined(__parallel)
16070  msglen = 1
16071  CALL mpi_reduce(msg, res, msglen, mpi_double_precision, mpi_max, root, comm%handle, ierr)
16072  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
16073  IF (root == comm%mepos) msg = res
16074  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16075 #else
16076  mark_used(msg)
16077  mark_used(comm)
16078  mark_used(root)
16079 #endif
16080  CALL mp_timestop(handle)
16081  END SUBROUTINE mp_max_root_d
16082 
16083 ! **************************************************************************************************
16084 !> \brief Finds the element-wise maximum of a vector with the result left on
16085 !> all processes.
16086 !> \param[in,out] msg Find maximum among these data (input) and
16087 !> maximum (output)
16088 !> \param comm ...
16089 !> \note see mp_max_d
16090 ! **************************************************************************************************
16091  SUBROUTINE mp_max_dv(msg, comm)
16092  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
16093  CLASS(mp_comm_type), INTENT(IN) :: comm
16094 
16095  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_dv'
16096 
16097  INTEGER :: handle
16098 #if defined(__parallel)
16099  INTEGER :: ierr, msglen
16100 #endif
16101 
16102  CALL mp_timeset(routinen, handle)
16103 
16104 #if defined(__parallel)
16105  msglen = SIZE(msg)
16106  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_max, comm%handle, ierr)
16107  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16108  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16109 #else
16110  mark_used(msg)
16111  mark_used(comm)
16112 #endif
16113  CALL mp_timestop(handle)
16114  END SUBROUTINE mp_max_dv
16115 
16116 ! **************************************************************************************************
16117 !> \brief Finds the element-wise maximum of a vector with the result left on
16118 !> all processes.
16119 !> \param[in,out] msg Find maximum among these data (input) and
16120 !> maximum (output)
16121 !> \param comm ...
16122 !> \note see mp_max_d
16123 ! **************************************************************************************************
16124  SUBROUTINE mp_max_root_dm(msg, root, comm)
16125  REAL(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
16126  INTEGER :: root
16127  CLASS(mp_comm_type), INTENT(IN) :: comm
16128 
16129  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_dm'
16130 
16131  INTEGER :: handle
16132 #if defined(__parallel)
16133  INTEGER :: ierr, msglen
16134  REAL(kind=real_8) :: res(SIZE(msg, 1), SIZE(msg, 2))
16135 #endif
16136 
16137  CALL mp_timeset(routinen, handle)
16138 
16139 #if defined(__parallel)
16140  msglen = SIZE(msg)
16141  CALL mpi_reduce(msg, res, msglen, mpi_double_precision, mpi_max, root, comm%handle, ierr)
16142  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16143  IF (root == comm%mepos) msg = res
16144  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16145 #else
16146  mark_used(msg)
16147  mark_used(comm)
16148  mark_used(root)
16149 #endif
16150  CALL mp_timestop(handle)
16151  END SUBROUTINE mp_max_root_dm
16152 
16153 ! **************************************************************************************************
16154 !> \brief Finds the minimum of a datum with the result left on all processes.
16155 !> \param[in,out] msg Find minimum among these data (input) and
16156 !> maximum (output)
16157 !> \param[in] comm Message passing environment identifier
16158 !> \par MPI mapping
16159 !> mpi_allreduce
16160 ! **************************************************************************************************
16161  SUBROUTINE mp_min_d (msg, comm)
16162  REAL(kind=real_8), INTENT(INOUT) :: msg
16163  CLASS(mp_comm_type), INTENT(IN) :: comm
16164 
16165  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_d'
16166 
16167  INTEGER :: handle
16168 #if defined(__parallel)
16169  INTEGER :: ierr, msglen
16170 #endif
16171 
16172  CALL mp_timeset(routinen, handle)
16173 
16174 #if defined(__parallel)
16175  msglen = 1
16176  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_min, comm%handle, ierr)
16177  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16178  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16179 #else
16180  mark_used(msg)
16181  mark_used(comm)
16182 #endif
16183  CALL mp_timestop(handle)
16184  END SUBROUTINE mp_min_d
16185 
16186 ! **************************************************************************************************
16187 !> \brief Finds the element-wise minimum of vector with the result left on
16188 !> all processes.
16189 !> \param[in,out] msg Find minimum among these data (input) and
16190 !> maximum (output)
16191 !> \param comm ...
16192 !> \par MPI mapping
16193 !> mpi_allreduce
16194 !> \note see mp_min_d
16195 ! **************************************************************************************************
16196  SUBROUTINE mp_min_dv(msg, comm)
16197  REAL(kind=real_8), INTENT(INOUT), CONTIGUOUS :: msg(:)
16198  CLASS(mp_comm_type), INTENT(IN) :: comm
16199 
16200  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_dv'
16201 
16202  INTEGER :: handle
16203 #if defined(__parallel)
16204  INTEGER :: ierr, msglen
16205 #endif
16206 
16207  CALL mp_timeset(routinen, handle)
16208 
16209 #if defined(__parallel)
16210  msglen = SIZE(msg)
16211  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_min, comm%handle, ierr)
16212  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16213  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16214 #else
16215  mark_used(msg)
16216  mark_used(comm)
16217 #endif
16218  CALL mp_timestop(handle)
16219  END SUBROUTINE mp_min_dv
16220 
16221 ! **************************************************************************************************
16222 !> \brief Multiplies a set of numbers scattered across a number of processes,
16223 !> then replicates the result.
16224 !> \param[in,out] msg a number to multiply (input) and result (output)
16225 !> \param[in] comm message passing environment identifier
16226 !> \par MPI mapping
16227 !> mpi_allreduce
16228 ! **************************************************************************************************
16229  SUBROUTINE mp_prod_d (msg, comm)
16230  REAL(kind=real_8), INTENT(INOUT) :: msg
16231  CLASS(mp_comm_type), INTENT(IN) :: comm
16232 
16233  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_d'
16234 
16235  INTEGER :: handle
16236 #if defined(__parallel)
16237  INTEGER :: ierr, msglen
16238 #endif
16239 
16240  CALL mp_timeset(routinen, handle)
16241 
16242 #if defined(__parallel)
16243  msglen = 1
16244  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_precision, mpi_prod, comm%handle, ierr)
16245  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
16246  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_8_size)
16247 #else
16248  mark_used(msg)
16249  mark_used(comm)
16250 #endif
16251  CALL mp_timestop(handle)
16252  END SUBROUTINE mp_prod_d
16253 
16254 ! **************************************************************************************************
16255 !> \brief Scatters data from one processes to all others
16256 !> \param[in] msg_scatter Data to scatter (for root process)
16257 !> \param[out] msg Received data
16258 !> \param[in] root Process which scatters data
16259 !> \param[in] comm Message passing environment identifier
16260 !> \par MPI mapping
16261 !> mpi_scatter
16262 ! **************************************************************************************************
16263  SUBROUTINE mp_scatter_dv(msg_scatter, msg, root, comm)
16264  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
16265  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg(:)
16266  INTEGER, INTENT(IN) :: root
16267  CLASS(mp_comm_type), INTENT(IN) :: comm
16268 
16269  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_dv'
16270 
16271  INTEGER :: handle
16272 #if defined(__parallel)
16273  INTEGER :: ierr, msglen
16274 #endif
16275 
16276  CALL mp_timeset(routinen, handle)
16277 
16278 #if defined(__parallel)
16279  msglen = SIZE(msg)
16280  CALL mpi_scatter(msg_scatter, msglen, mpi_double_precision, msg, &
16281  msglen, mpi_double_precision, root, comm%handle, ierr)
16282  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
16283  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16284 #else
16285  mark_used(root)
16286  mark_used(comm)
16287  msg = msg_scatter
16288 #endif
16289  CALL mp_timestop(handle)
16290  END SUBROUTINE mp_scatter_dv
16291 
16292 ! **************************************************************************************************
16293 !> \brief Scatters data from one processes to all others
16294 !> \param[in] msg_scatter Data to scatter (for root process)
16295 !> \param[in] root Process which scatters data
16296 !> \param[in] comm Message passing environment identifier
16297 !> \par MPI mapping
16298 !> mpi_scatter
16299 ! **************************************************************************************************
16300  SUBROUTINE mp_iscatter_d (msg_scatter, msg, root, comm, request)
16301  REAL(kind=real_8), INTENT(IN) :: msg_scatter(:)
16302  REAL(kind=real_8), INTENT(INOUT) :: msg
16303  INTEGER, INTENT(IN) :: root
16304  CLASS(mp_comm_type), INTENT(IN) :: comm
16305  TYPE(mp_request_type), INTENT(OUT) :: request
16306 
16307  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_d'
16308 
16309  INTEGER :: handle
16310 #if defined(__parallel)
16311  INTEGER :: ierr, msglen
16312 #endif
16313 
16314  CALL mp_timeset(routinen, handle)
16315 
16316 #if defined(__parallel)
16317 #if !defined(__GNUC__) || __GNUC__ >= 9
16318  cpassert(is_contiguous(msg_scatter))
16319 #endif
16320  msglen = 1
16321  CALL mpi_iscatter(msg_scatter, msglen, mpi_double_precision, msg, &
16322  msglen, mpi_double_precision, root, comm%handle, request%handle, ierr)
16323  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
16324  CALL add_perf(perf_id=24, count=1, msg_size=1*real_8_size)
16325 #else
16326  mark_used(root)
16327  mark_used(comm)
16328  msg = msg_scatter(1)
16329  request = mp_request_null
16330 #endif
16331  CALL mp_timestop(handle)
16332  END SUBROUTINE mp_iscatter_d
16333 
16334 ! **************************************************************************************************
16335 !> \brief Scatters data from one processes to all others
16336 !> \param[in] msg_scatter Data to scatter (for root process)
16337 !> \param[in] root Process which scatters data
16338 !> \param[in] comm Message passing environment identifier
16339 !> \par MPI mapping
16340 !> mpi_scatter
16341 ! **************************************************************************************************
16342  SUBROUTINE mp_iscatter_dv2(msg_scatter, msg, root, comm, request)
16343  REAL(kind=real_8), INTENT(IN) :: msg_scatter(:, :)
16344  REAL(kind=real_8), INTENT(INOUT) :: msg(:)
16345  INTEGER, INTENT(IN) :: root
16346  CLASS(mp_comm_type), INTENT(IN) :: comm
16347  TYPE(mp_request_type), INTENT(OUT) :: request
16348 
16349  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_dv2'
16350 
16351  INTEGER :: handle
16352 #if defined(__parallel)
16353  INTEGER :: ierr, msglen
16354 #endif
16355 
16356  CALL mp_timeset(routinen, handle)
16357 
16358 #if defined(__parallel)
16359 #if !defined(__GNUC__) || __GNUC__ >= 9
16360  cpassert(is_contiguous(msg_scatter))
16361 #endif
16362  msglen = SIZE(msg)
16363  CALL mpi_iscatter(msg_scatter, msglen, mpi_double_precision, msg, &
16364  msglen, mpi_double_precision, root, comm%handle, request%handle, ierr)
16365  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
16366  CALL add_perf(perf_id=24, count=1, msg_size=1*real_8_size)
16367 #else
16368  mark_used(root)
16369  mark_used(comm)
16370  msg(:) = msg_scatter(:, 1)
16371  request = mp_request_null
16372 #endif
16373  CALL mp_timestop(handle)
16374  END SUBROUTINE mp_iscatter_dv2
16375 
16376 ! **************************************************************************************************
16377 !> \brief Scatters data from one processes to all others
16378 !> \param[in] msg_scatter Data to scatter (for root process)
16379 !> \param[in] root Process which scatters data
16380 !> \param[in] comm Message passing environment identifier
16381 !> \par MPI mapping
16382 !> mpi_scatter
16383 ! **************************************************************************************************
16384  SUBROUTINE mp_iscatterv_dv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
16385  REAL(kind=real_8), INTENT(IN) :: msg_scatter(:)
16386  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
16387  REAL(kind=real_8), INTENT(INOUT) :: msg(:)
16388  INTEGER, INTENT(IN) :: recvcount, root
16389  CLASS(mp_comm_type), INTENT(IN) :: comm
16390  TYPE(mp_request_type), INTENT(OUT) :: request
16391 
16392  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_dv'
16393 
16394  INTEGER :: handle
16395 #if defined(__parallel)
16396  INTEGER :: ierr
16397 #endif
16398 
16399  CALL mp_timeset(routinen, handle)
16400 
16401 #if defined(__parallel)
16402 #if !defined(__GNUC__) || __GNUC__ >= 9
16403  cpassert(is_contiguous(msg_scatter))
16404  cpassert(is_contiguous(msg))
16405  cpassert(is_contiguous(sendcounts))
16406  cpassert(is_contiguous(displs))
16407 #endif
16408  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_double_precision, msg, &
16409  recvcount, mpi_double_precision, root, comm%handle, request%handle, ierr)
16410  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
16411  CALL add_perf(perf_id=24, count=1, msg_size=1*real_8_size)
16412 #else
16413  mark_used(sendcounts)
16414  mark_used(displs)
16415  mark_used(recvcount)
16416  mark_used(root)
16417  mark_used(comm)
16418  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
16419  request = mp_request_null
16420 #endif
16421  CALL mp_timestop(handle)
16422  END SUBROUTINE mp_iscatterv_dv
16423 
16424 ! **************************************************************************************************
16425 !> \brief Gathers a datum from all processes to one
16426 !> \param[in] msg Datum to send to root
16427 !> \param[out] msg_gather Received data (on root)
16428 !> \param[in] root Process which gathers the data
16429 !> \param[in] comm Message passing environment identifier
16430 !> \par MPI mapping
16431 !> mpi_gather
16432 ! **************************************************************************************************
16433  SUBROUTINE mp_gather_d (msg, msg_gather, root, comm)
16434  REAL(kind=real_8), INTENT(IN) :: msg
16435  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
16436  INTEGER, INTENT(IN) :: root
16437  CLASS(mp_comm_type), INTENT(IN) :: comm
16438 
16439  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_d'
16440 
16441  INTEGER :: handle
16442 #if defined(__parallel)
16443  INTEGER :: ierr, msglen
16444 #endif
16445 
16446  CALL mp_timeset(routinen, handle)
16447 
16448 #if defined(__parallel)
16449  msglen = 1
16450  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16451  msglen, mpi_double_precision, root, comm%handle, ierr)
16452  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16453  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16454 #else
16455  mark_used(root)
16456  mark_used(comm)
16457  msg_gather(1) = msg
16458 #endif
16459  CALL mp_timestop(handle)
16460  END SUBROUTINE mp_gather_d
16461 
16462 ! **************************************************************************************************
16463 !> \brief Gathers a datum from all processes to one, uses the source process of comm
16464 !> \param[in] msg Datum to send to root
16465 !> \param[out] msg_gather Received data (on root)
16466 !> \param[in] comm Message passing environment identifier
16467 !> \par MPI mapping
16468 !> mpi_gather
16469 ! **************************************************************************************************
16470  SUBROUTINE mp_gather_d_src(msg, msg_gather, comm)
16471  REAL(kind=real_8), INTENT(IN) :: msg
16472  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
16473  CLASS(mp_comm_type), INTENT(IN) :: comm
16474 
16475  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_d_src'
16476 
16477  INTEGER :: handle
16478 #if defined(__parallel)
16479  INTEGER :: ierr, msglen
16480 #endif
16481 
16482  CALL mp_timeset(routinen, handle)
16483 
16484 #if defined(__parallel)
16485  msglen = 1
16486  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16487  msglen, mpi_double_precision, comm%source, comm%handle, ierr)
16488  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16489  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16490 #else
16491  mark_used(comm)
16492  msg_gather(1) = msg
16493 #endif
16494  CALL mp_timestop(handle)
16495  END SUBROUTINE mp_gather_d_src
16496 
16497 ! **************************************************************************************************
16498 !> \brief Gathers data from all processes to one
16499 !> \param[in] msg Datum to send to root
16500 !> \param msg_gather ...
16501 !> \param root ...
16502 !> \param comm ...
16503 !> \par Data length
16504 !> All data (msg) is equal-sized
16505 !> \par MPI mapping
16506 !> mpi_gather
16507 !> \note see mp_gather_d
16508 ! **************************************************************************************************
16509  SUBROUTINE mp_gather_dv(msg, msg_gather, root, comm)
16510  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
16511  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
16512  INTEGER, INTENT(IN) :: root
16513  CLASS(mp_comm_type), INTENT(IN) :: comm
16514 
16515  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_dv'
16516 
16517  INTEGER :: handle
16518 #if defined(__parallel)
16519  INTEGER :: ierr, msglen
16520 #endif
16521 
16522  CALL mp_timeset(routinen, handle)
16523 
16524 #if defined(__parallel)
16525  msglen = SIZE(msg)
16526  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16527  msglen, mpi_double_precision, root, comm%handle, ierr)
16528  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16529  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16530 #else
16531  mark_used(root)
16532  mark_used(comm)
16533  msg_gather = msg
16534 #endif
16535  CALL mp_timestop(handle)
16536  END SUBROUTINE mp_gather_dv
16537 
16538 ! **************************************************************************************************
16539 !> \brief Gathers data from all processes to one. Gathers from comm%source
16540 !> \param[in] msg Datum to send to root
16541 !> \param msg_gather ...
16542 !> \param comm ...
16543 !> \par Data length
16544 !> All data (msg) is equal-sized
16545 !> \par MPI mapping
16546 !> mpi_gather
16547 !> \note see mp_gather_d
16548 ! **************************************************************************************************
16549  SUBROUTINE mp_gather_dv_src(msg, msg_gather, comm)
16550  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
16551  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
16552  CLASS(mp_comm_type), INTENT(IN) :: comm
16553 
16554  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_dv_src'
16555 
16556  INTEGER :: handle
16557 #if defined(__parallel)
16558  INTEGER :: ierr, msglen
16559 #endif
16560 
16561  CALL mp_timeset(routinen, handle)
16562 
16563 #if defined(__parallel)
16564  msglen = SIZE(msg)
16565  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16566  msglen, mpi_double_precision, comm%source, comm%handle, ierr)
16567  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16568  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16569 #else
16570  mark_used(comm)
16571  msg_gather = msg
16572 #endif
16573  CALL mp_timestop(handle)
16574  END SUBROUTINE mp_gather_dv_src
16575 
16576 ! **************************************************************************************************
16577 !> \brief Gathers data from all processes to one
16578 !> \param[in] msg Datum to send to root
16579 !> \param msg_gather ...
16580 !> \param root ...
16581 !> \param comm ...
16582 !> \par Data length
16583 !> All data (msg) is equal-sized
16584 !> \par MPI mapping
16585 !> mpi_gather
16586 !> \note see mp_gather_d
16587 ! **************************************************************************************************
16588  SUBROUTINE mp_gather_dm(msg, msg_gather, root, comm)
16589  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
16590  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
16591  INTEGER, INTENT(IN) :: root
16592  CLASS(mp_comm_type), INTENT(IN) :: comm
16593 
16594  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_dm'
16595 
16596  INTEGER :: handle
16597 #if defined(__parallel)
16598  INTEGER :: ierr, msglen
16599 #endif
16600 
16601  CALL mp_timeset(routinen, handle)
16602 
16603 #if defined(__parallel)
16604  msglen = SIZE(msg)
16605  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16606  msglen, mpi_double_precision, root, comm%handle, ierr)
16607  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16608  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16609 #else
16610  mark_used(root)
16611  mark_used(comm)
16612  msg_gather = msg
16613 #endif
16614  CALL mp_timestop(handle)
16615  END SUBROUTINE mp_gather_dm
16616 
16617 ! **************************************************************************************************
16618 !> \brief Gathers data from all processes to one. Gathers from comm%source
16619 !> \param[in] msg Datum to send to root
16620 !> \param msg_gather ...
16621 !> \param comm ...
16622 !> \par Data length
16623 !> All data (msg) is equal-sized
16624 !> \par MPI mapping
16625 !> mpi_gather
16626 !> \note see mp_gather_d
16627 ! **************************************************************************************************
16628  SUBROUTINE mp_gather_dm_src(msg, msg_gather, comm)
16629  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
16630  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
16631  CLASS(mp_comm_type), INTENT(IN) :: comm
16632 
16633  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_dm_src'
16634 
16635  INTEGER :: handle
16636 #if defined(__parallel)
16637  INTEGER :: ierr, msglen
16638 #endif
16639 
16640  CALL mp_timeset(routinen, handle)
16641 
16642 #if defined(__parallel)
16643  msglen = SIZE(msg)
16644  CALL mpi_gather(msg, msglen, mpi_double_precision, msg_gather, &
16645  msglen, mpi_double_precision, comm%source, comm%handle, ierr)
16646  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
16647  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_8_size)
16648 #else
16649  mark_used(comm)
16650  msg_gather = msg
16651 #endif
16652  CALL mp_timestop(handle)
16653  END SUBROUTINE mp_gather_dm_src
16654 
16655 ! **************************************************************************************************
16656 !> \brief Gathers data from all processes to one.
16657 !> \param[in] sendbuf Data to send to root
16658 !> \param[out] recvbuf Received data (on root)
16659 !> \param[in] recvcounts Sizes of data received from processes
16660 !> \param[in] displs Offsets of data received from processes
16661 !> \param[in] root Process which gathers the data
16662 !> \param[in] comm Message passing environment identifier
16663 !> \par Data length
16664 !> Data can have different lengths
16665 !> \par Offsets
16666 !> Offsets start at 0
16667 !> \par MPI mapping
16668 !> mpi_gather
16669 ! **************************************************************************************************
16670  SUBROUTINE mp_gatherv_dv(sendbuf, recvbuf, recvcounts, displs, root, comm)
16671 
16672  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
16673  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
16674  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
16675  INTEGER, INTENT(IN) :: root
16676  CLASS(mp_comm_type), INTENT(IN) :: comm
16677 
16678  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_dv'
16679 
16680  INTEGER :: handle
16681 #if defined(__parallel)
16682  INTEGER :: ierr, sendcount
16683 #endif
16684 
16685  CALL mp_timeset(routinen, handle)
16686 
16687 #if defined(__parallel)
16688  sendcount = SIZE(sendbuf)
16689  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_precision, &
16690  recvbuf, recvcounts, displs, mpi_double_precision, &
16691  root, comm%handle, ierr)
16692  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
16693  CALL add_perf(perf_id=4, &
16694  count=1, &
16695  msg_size=sendcount*real_8_size)
16696 #else
16697  mark_used(recvcounts)
16698  mark_used(root)
16699  mark_used(comm)
16700  recvbuf(1 + displs(1):) = sendbuf
16701 #endif
16702  CALL mp_timestop(handle)
16703  END SUBROUTINE mp_gatherv_dv
16704 
16705 ! **************************************************************************************************
16706 !> \brief Gathers data from all processes to one. Gathers from comm%source
16707 !> \param[in] sendbuf Data to send to root
16708 !> \param[out] recvbuf Received data (on root)
16709 !> \param[in] recvcounts Sizes of data received from processes
16710 !> \param[in] displs Offsets of data received from processes
16711 !> \param[in] comm Message passing environment identifier
16712 !> \par Data length
16713 !> Data can have different lengths
16714 !> \par Offsets
16715 !> Offsets start at 0
16716 !> \par MPI mapping
16717 !> mpi_gather
16718 ! **************************************************************************************************
16719  SUBROUTINE mp_gatherv_dv_src(sendbuf, recvbuf, recvcounts, displs, comm)
16720 
16721  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
16722  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
16723  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
16724  CLASS(mp_comm_type), INTENT(IN) :: comm
16725 
16726  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_dv_src'
16727 
16728  INTEGER :: handle
16729 #if defined(__parallel)
16730  INTEGER :: ierr, sendcount
16731 #endif
16732 
16733  CALL mp_timeset(routinen, handle)
16734 
16735 #if defined(__parallel)
16736  sendcount = SIZE(sendbuf)
16737  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_precision, &
16738  recvbuf, recvcounts, displs, mpi_double_precision, &
16739  comm%source, comm%handle, ierr)
16740  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
16741  CALL add_perf(perf_id=4, &
16742  count=1, &
16743  msg_size=sendcount*real_8_size)
16744 #else
16745  mark_used(recvcounts)
16746  mark_used(comm)
16747  recvbuf(1 + displs(1):) = sendbuf
16748 #endif
16749  CALL mp_timestop(handle)
16750  END SUBROUTINE mp_gatherv_dv_src
16751 
16752 ! **************************************************************************************************
16753 !> \brief Gathers data from all processes to one.
16754 !> \param[in] sendbuf Data to send to root
16755 !> \param[out] recvbuf Received data (on root)
16756 !> \param[in] recvcounts Sizes of data received from processes
16757 !> \param[in] displs Offsets of data received from processes
16758 !> \param[in] root Process which gathers the data
16759 !> \param[in] comm Message passing environment identifier
16760 !> \par Data length
16761 !> Data can have different lengths
16762 !> \par Offsets
16763 !> Offsets start at 0
16764 !> \par MPI mapping
16765 !> mpi_gather
16766 ! **************************************************************************************************
16767  SUBROUTINE mp_gatherv_dm2(sendbuf, recvbuf, recvcounts, displs, root, comm)
16768 
16769  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
16770  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
16771  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
16772  INTEGER, INTENT(IN) :: root
16773  CLASS(mp_comm_type), INTENT(IN) :: comm
16774 
16775  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_dm2'
16776 
16777  INTEGER :: handle
16778 #if defined(__parallel)
16779  INTEGER :: ierr, sendcount
16780 #endif
16781 
16782  CALL mp_timeset(routinen, handle)
16783 
16784 #if defined(__parallel)
16785  sendcount = SIZE(sendbuf)
16786  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_precision, &
16787  recvbuf, recvcounts, displs, mpi_double_precision, &
16788  root, comm%handle, ierr)
16789  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
16790  CALL add_perf(perf_id=4, &
16791  count=1, &
16792  msg_size=sendcount*real_8_size)
16793 #else
16794  mark_used(recvcounts)
16795  mark_used(root)
16796  mark_used(comm)
16797  recvbuf(:, 1 + displs(1):) = sendbuf
16798 #endif
16799  CALL mp_timestop(handle)
16800  END SUBROUTINE mp_gatherv_dm2
16801 
16802 ! **************************************************************************************************
16803 !> \brief Gathers data from all processes to one.
16804 !> \param[in] sendbuf Data to send to root
16805 !> \param[out] recvbuf Received data (on root)
16806 !> \param[in] recvcounts Sizes of data received from processes
16807 !> \param[in] displs Offsets of data received from processes
16808 !> \param[in] comm Message passing environment identifier
16809 !> \par Data length
16810 !> Data can have different lengths
16811 !> \par Offsets
16812 !> Offsets start at 0
16813 !> \par MPI mapping
16814 !> mpi_gather
16815 ! **************************************************************************************************
16816  SUBROUTINE mp_gatherv_dm2_src(sendbuf, recvbuf, recvcounts, displs, comm)
16817 
16818  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
16819  REAL(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
16820  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
16821  CLASS(mp_comm_type), INTENT(IN) :: comm
16822 
16823  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_dm2_src'
16824 
16825  INTEGER :: handle
16826 #if defined(__parallel)
16827  INTEGER :: ierr, sendcount
16828 #endif
16829 
16830  CALL mp_timeset(routinen, handle)
16831 
16832 #if defined(__parallel)
16833  sendcount = SIZE(sendbuf)
16834  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_precision, &
16835  recvbuf, recvcounts, displs, mpi_double_precision, &
16836  comm%source, comm%handle, ierr)
16837  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
16838  CALL add_perf(perf_id=4, &
16839  count=1, &
16840  msg_size=sendcount*real_8_size)
16841 #else
16842  mark_used(recvcounts)
16843  mark_used(comm)
16844  recvbuf(:, 1 + displs(1):) = sendbuf
16845 #endif
16846  CALL mp_timestop(handle)
16847  END SUBROUTINE mp_gatherv_dm2_src
16848 
16849 ! **************************************************************************************************
16850 !> \brief Gathers data from all processes to one.
16851 !> \param[in] sendbuf Data to send to root
16852 !> \param[out] recvbuf Received data (on root)
16853 !> \param[in] recvcounts Sizes of data received from processes
16854 !> \param[in] displs Offsets of data received from processes
16855 !> \param[in] root Process which gathers the data
16856 !> \param[in] comm Message passing environment identifier
16857 !> \par Data length
16858 !> Data can have different lengths
16859 !> \par Offsets
16860 !> Offsets start at 0
16861 !> \par MPI mapping
16862 !> mpi_gather
16863 ! **************************************************************************************************
16864  SUBROUTINE mp_igatherv_dv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
16865  REAL(kind=real_8), DIMENSION(:), INTENT(IN) :: sendbuf
16866  REAL(kind=real_8), DIMENSION(:), INTENT(OUT) :: recvbuf
16867  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
16868  INTEGER, INTENT(IN) :: sendcount, root
16869  CLASS(mp_comm_type), INTENT(IN) :: comm
16870  TYPE(mp_request_type), INTENT(OUT) :: request
16871 
16872  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_dv'
16873 
16874  INTEGER :: handle
16875 #if defined(__parallel)
16876  INTEGER :: ierr
16877 #endif
16878 
16879  CALL mp_timeset(routinen, handle)
16880 
16881 #if defined(__parallel)
16882 #if !defined(__GNUC__) || __GNUC__ >= 9
16883  cpassert(is_contiguous(sendbuf))
16884  cpassert(is_contiguous(recvbuf))
16885  cpassert(is_contiguous(recvcounts))
16886  cpassert(is_contiguous(displs))
16887 #endif
16888  CALL mpi_igatherv(sendbuf, sendcount, mpi_double_precision, &
16889  recvbuf, recvcounts, displs, mpi_double_precision, &
16890  root, comm%handle, request%handle, ierr)
16891  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
16892  CALL add_perf(perf_id=24, &
16893  count=1, &
16894  msg_size=sendcount*real_8_size)
16895 #else
16896  mark_used(sendcount)
16897  mark_used(recvcounts)
16898  mark_used(root)
16899  mark_used(comm)
16900  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
16901  request = mp_request_null
16902 #endif
16903  CALL mp_timestop(handle)
16904  END SUBROUTINE mp_igatherv_dv
16905 
16906 ! **************************************************************************************************
16907 !> \brief Gathers a datum from all processes and all processes receive the
16908 !> same data
16909 !> \param[in] msgout Datum to send
16910 !> \param[out] msgin Received data
16911 !> \param[in] comm Message passing environment identifier
16912 !> \par Data size
16913 !> All processes send equal-sized data
16914 !> \par MPI mapping
16915 !> mpi_allgather
16916 ! **************************************************************************************************
16917  SUBROUTINE mp_allgather_d (msgout, msgin, comm)
16918  REAL(kind=real_8), INTENT(IN) :: msgout
16919  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:)
16920  CLASS(mp_comm_type), INTENT(IN) :: comm
16921 
16922  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d'
16923 
16924  INTEGER :: handle
16925 #if defined(__parallel)
16926  INTEGER :: ierr, rcount, scount
16927 #endif
16928 
16929  CALL mp_timeset(routinen, handle)
16930 
16931 #if defined(__parallel)
16932  scount = 1
16933  rcount = 1
16934  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
16935  msgin, rcount, mpi_double_precision, &
16936  comm%handle, ierr)
16937  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
16938 #else
16939  mark_used(comm)
16940  msgin = msgout
16941 #endif
16942  CALL mp_timestop(handle)
16943  END SUBROUTINE mp_allgather_d
16944 
16945 ! **************************************************************************************************
16946 !> \brief Gathers a datum from all processes and all processes receive the
16947 !> same data
16948 !> \param[in] msgout Datum to send
16949 !> \param[out] msgin Received data
16950 !> \param[in] comm Message passing environment identifier
16951 !> \par Data size
16952 !> All processes send equal-sized data
16953 !> \par MPI mapping
16954 !> mpi_allgather
16955 ! **************************************************************************************************
16956  SUBROUTINE mp_allgather_d2(msgout, msgin, comm)
16957  REAL(kind=real_8), INTENT(IN) :: msgout
16958  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
16959  CLASS(mp_comm_type), INTENT(IN) :: comm
16960 
16961  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d2'
16962 
16963  INTEGER :: handle
16964 #if defined(__parallel)
16965  INTEGER :: ierr, rcount, scount
16966 #endif
16967 
16968  CALL mp_timeset(routinen, handle)
16969 
16970 #if defined(__parallel)
16971  scount = 1
16972  rcount = 1
16973  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
16974  msgin, rcount, mpi_double_precision, &
16975  comm%handle, ierr)
16976  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
16977 #else
16978  mark_used(comm)
16979  msgin = msgout
16980 #endif
16981  CALL mp_timestop(handle)
16982  END SUBROUTINE mp_allgather_d2
16983 
16984 ! **************************************************************************************************
16985 !> \brief Gathers a datum from all processes and all processes receive the
16986 !> same data
16987 !> \param[in] msgout Datum to send
16988 !> \param[out] msgin Received data
16989 !> \param[in] comm Message passing environment identifier
16990 !> \par Data size
16991 !> All processes send equal-sized data
16992 !> \par MPI mapping
16993 !> mpi_allgather
16994 ! **************************************************************************************************
16995  SUBROUTINE mp_iallgather_d (msgout, msgin, comm, request)
16996  REAL(kind=real_8), INTENT(IN) :: msgout
16997  REAL(kind=real_8), INTENT(OUT) :: msgin(:)
16998  CLASS(mp_comm_type), INTENT(IN) :: comm
16999  TYPE(mp_request_type), INTENT(OUT) :: request
17000 
17001  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d'
17002 
17003  INTEGER :: handle
17004 #if defined(__parallel)
17005  INTEGER :: ierr, rcount, scount
17006 #endif
17007 
17008  CALL mp_timeset(routinen, handle)
17009 
17010 #if defined(__parallel)
17011 #if !defined(__GNUC__) || __GNUC__ >= 9
17012  cpassert(is_contiguous(msgin))
17013 #endif
17014  scount = 1
17015  rcount = 1
17016  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17017  msgin, rcount, mpi_double_precision, &
17018  comm%handle, request%handle, ierr)
17019  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
17020 #else
17021  mark_used(comm)
17022  msgin = msgout
17023  request = mp_request_null
17024 #endif
17025  CALL mp_timestop(handle)
17026  END SUBROUTINE mp_iallgather_d
17027 
17028 ! **************************************************************************************************
17029 !> \brief Gathers vector data from all processes and all processes receive the
17030 !> same data
17031 !> \param[in] msgout Rank-1 data to send
17032 !> \param[out] msgin Received data
17033 !> \param[in] comm Message passing environment identifier
17034 !> \par Data size
17035 !> All processes send equal-sized data
17036 !> \par Ranks
17037 !> The last rank counts the processes
17038 !> \par MPI mapping
17039 !> mpi_allgather
17040 ! **************************************************************************************************
17041  SUBROUTINE mp_allgather_d12(msgout, msgin, comm)
17042  REAL(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:)
17043  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
17044  CLASS(mp_comm_type), INTENT(IN) :: comm
17045 
17046  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d12'
17047 
17048  INTEGER :: handle
17049 #if defined(__parallel)
17050  INTEGER :: ierr, rcount, scount
17051 #endif
17052 
17053  CALL mp_timeset(routinen, handle)
17054 
17055 #if defined(__parallel)
17056  scount = SIZE(msgout(:))
17057  rcount = scount
17058  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
17059  msgin, rcount, mpi_double_precision, &
17060  comm%handle, ierr)
17061  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
17062 #else
17063  mark_used(comm)
17064  msgin(:, 1) = msgout(:)
17065 #endif
17066  CALL mp_timestop(handle)
17067  END SUBROUTINE mp_allgather_d12
17068 
17069 ! **************************************************************************************************
17070 !> \brief Gathers matrix data from all processes and all processes receive the
17071 !> same data
17072 !> \param[in] msgout Rank-2 data to send
17073 !> \param msgin ...
17074 !> \param comm ...
17075 !> \note see mp_allgather_d12
17076 ! **************************************************************************************************
17077  SUBROUTINE mp_allgather_d23(msgout, msgin, comm)
17078  REAL(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
17079  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
17080  CLASS(mp_comm_type), INTENT(IN) :: comm
17081 
17082  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d23'
17083 
17084  INTEGER :: handle
17085 #if defined(__parallel)
17086  INTEGER :: ierr, rcount, scount
17087 #endif
17088 
17089  CALL mp_timeset(routinen, handle)
17090 
17091 #if defined(__parallel)
17092  scount = SIZE(msgout(:, :))
17093  rcount = scount
17094  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
17095  msgin, rcount, mpi_double_precision, &
17096  comm%handle, ierr)
17097  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
17098 #else
17099  mark_used(comm)
17100  msgin(:, :, 1) = msgout(:, :)
17101 #endif
17102  CALL mp_timestop(handle)
17103  END SUBROUTINE mp_allgather_d23
17104 
17105 ! **************************************************************************************************
17106 !> \brief Gathers rank-3 data from all processes and all processes receive the
17107 !> same data
17108 !> \param[in] msgout Rank-3 data to send
17109 !> \param msgin ...
17110 !> \param comm ...
17111 !> \note see mp_allgather_d12
17112 ! **************************************************************************************************
17113  SUBROUTINE mp_allgather_d34(msgout, msgin, comm)
17114  REAL(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
17115  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
17116  CLASS(mp_comm_type), INTENT(IN) :: comm
17117 
17118  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d34'
17119 
17120  INTEGER :: handle
17121 #if defined(__parallel)
17122  INTEGER :: ierr, rcount, scount
17123 #endif
17124 
17125  CALL mp_timeset(routinen, handle)
17126 
17127 #if defined(__parallel)
17128  scount = SIZE(msgout(:, :, :))
17129  rcount = scount
17130  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
17131  msgin, rcount, mpi_double_precision, &
17132  comm%handle, ierr)
17133  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
17134 #else
17135  mark_used(comm)
17136  msgin(:, :, :, 1) = msgout(:, :, :)
17137 #endif
17138  CALL mp_timestop(handle)
17139  END SUBROUTINE mp_allgather_d34
17140 
17141 ! **************************************************************************************************
17142 !> \brief Gathers rank-2 data from all processes and all processes receive the
17143 !> same data
17144 !> \param[in] msgout Rank-2 data to send
17145 !> \param msgin ...
17146 !> \param comm ...
17147 !> \note see mp_allgather_d12
17148 ! **************************************************************************************************
17149  SUBROUTINE mp_allgather_d22(msgout, msgin, comm)
17150  REAL(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
17151  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
17152  CLASS(mp_comm_type), INTENT(IN) :: comm
17153 
17154  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_d22'
17155 
17156  INTEGER :: handle
17157 #if defined(__parallel)
17158  INTEGER :: ierr, rcount, scount
17159 #endif
17160 
17161  CALL mp_timeset(routinen, handle)
17162 
17163 #if defined(__parallel)
17164  scount = SIZE(msgout(:, :))
17165  rcount = scount
17166  CALL mpi_allgather(msgout, scount, mpi_double_precision, &
17167  msgin, rcount, mpi_double_precision, &
17168  comm%handle, ierr)
17169  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
17170 #else
17171  mark_used(comm)
17172  msgin(:, :) = msgout(:, :)
17173 #endif
17174  CALL mp_timestop(handle)
17175  END SUBROUTINE mp_allgather_d22
17176 
17177 ! **************************************************************************************************
17178 !> \brief Gathers rank-1 data from all processes and all processes receive the
17179 !> same data
17180 !> \param[in] msgout Rank-1 data to send
17181 !> \param msgin ...
17182 !> \param comm ...
17183 !> \param request ...
17184 !> \note see mp_allgather_d11
17185 ! **************************************************************************************************
17186  SUBROUTINE mp_iallgather_d11(msgout, msgin, comm, request)
17187  REAL(kind=real_8), INTENT(IN) :: msgout(:)
17188  REAL(kind=real_8), INTENT(OUT) :: msgin(:)
17189  CLASS(mp_comm_type), INTENT(IN) :: comm
17190  TYPE(mp_request_type), INTENT(OUT) :: request
17191 
17192  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d11'
17193 
17194  INTEGER :: handle
17195 #if defined(__parallel)
17196  INTEGER :: ierr, rcount, scount
17197 #endif
17198 
17199  CALL mp_timeset(routinen, handle)
17200 
17201 #if defined(__parallel)
17202 #if !defined(__GNUC__) || __GNUC__ >= 9
17203  cpassert(is_contiguous(msgout))
17204  cpassert(is_contiguous(msgin))
17205 #endif
17206  scount = SIZE(msgout(:))
17207  rcount = scount
17208  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17209  msgin, rcount, mpi_double_precision, &
17210  comm%handle, request%handle, ierr)
17211  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
17212 #else
17213  mark_used(comm)
17214  msgin = msgout
17215  request = mp_request_null
17216 #endif
17217  CALL mp_timestop(handle)
17218  END SUBROUTINE mp_iallgather_d11
17219 
17220 ! **************************************************************************************************
17221 !> \brief Gathers rank-2 data from all processes and all processes receive the
17222 !> same data
17223 !> \param[in] msgout Rank-2 data to send
17224 !> \param msgin ...
17225 !> \param comm ...
17226 !> \param request ...
17227 !> \note see mp_allgather_d12
17228 ! **************************************************************************************************
17229  SUBROUTINE mp_iallgather_d13(msgout, msgin, comm, request)
17230  REAL(kind=real_8), INTENT(IN) :: msgout(:)
17231  REAL(kind=real_8), INTENT(OUT) :: msgin(:, :, :)
17232  CLASS(mp_comm_type), INTENT(IN) :: comm
17233  TYPE(mp_request_type), INTENT(OUT) :: request
17234 
17235  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d13'
17236 
17237  INTEGER :: handle
17238 #if defined(__parallel)
17239  INTEGER :: ierr, rcount, scount
17240 #endif
17241 
17242  CALL mp_timeset(routinen, handle)
17243 
17244 #if defined(__parallel)
17245 #if !defined(__GNUC__) || __GNUC__ >= 9
17246  cpassert(is_contiguous(msgout))
17247  cpassert(is_contiguous(msgin))
17248 #endif
17249 
17250  scount = SIZE(msgout(:))
17251  rcount = scount
17252  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17253  msgin, rcount, mpi_double_precision, &
17254  comm%handle, request%handle, ierr)
17255  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
17256 #else
17257  mark_used(comm)
17258  msgin(:, 1, 1) = msgout(:)
17259  request = mp_request_null
17260 #endif
17261  CALL mp_timestop(handle)
17262  END SUBROUTINE mp_iallgather_d13
17263 
17264 ! **************************************************************************************************
17265 !> \brief Gathers rank-2 data from all processes and all processes receive the
17266 !> same data
17267 !> \param[in] msgout Rank-2 data to send
17268 !> \param msgin ...
17269 !> \param comm ...
17270 !> \param request ...
17271 !> \note see mp_allgather_d12
17272 ! **************************************************************************************************
17273  SUBROUTINE mp_iallgather_d22(msgout, msgin, comm, request)
17274  REAL(kind=real_8), INTENT(IN) :: msgout(:, :)
17275  REAL(kind=real_8), INTENT(OUT) :: msgin(:, :)
17276  CLASS(mp_comm_type), INTENT(IN) :: comm
17277  TYPE(mp_request_type), INTENT(OUT) :: request
17278 
17279  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d22'
17280 
17281  INTEGER :: handle
17282 #if defined(__parallel)
17283  INTEGER :: ierr, rcount, scount
17284 #endif
17285 
17286  CALL mp_timeset(routinen, handle)
17287 
17288 #if defined(__parallel)
17289 #if !defined(__GNUC__) || __GNUC__ >= 9
17290  cpassert(is_contiguous(msgout))
17291  cpassert(is_contiguous(msgin))
17292 #endif
17293 
17294  scount = SIZE(msgout(:, :))
17295  rcount = scount
17296  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17297  msgin, rcount, mpi_double_precision, &
17298  comm%handle, request%handle, ierr)
17299  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
17300 #else
17301  mark_used(comm)
17302  msgin(:, :) = msgout(:, :)
17303  request = mp_request_null
17304 #endif
17305  CALL mp_timestop(handle)
17306  END SUBROUTINE mp_iallgather_d22
17307 
17308 ! **************************************************************************************************
17309 !> \brief Gathers rank-2 data from all processes and all processes receive the
17310 !> same data
17311 !> \param[in] msgout Rank-2 data to send
17312 !> \param msgin ...
17313 !> \param comm ...
17314 !> \param request ...
17315 !> \note see mp_allgather_d12
17316 ! **************************************************************************************************
17317  SUBROUTINE mp_iallgather_d24(msgout, msgin, comm, request)
17318  REAL(kind=real_8), INTENT(IN) :: msgout(:, :)
17319  REAL(kind=real_8), INTENT(OUT) :: msgin(:, :, :, :)
17320  CLASS(mp_comm_type), INTENT(IN) :: comm
17321  TYPE(mp_request_type), INTENT(OUT) :: request
17322 
17323  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d24'
17324 
17325  INTEGER :: handle
17326 #if defined(__parallel)
17327  INTEGER :: ierr, rcount, scount
17328 #endif
17329 
17330  CALL mp_timeset(routinen, handle)
17331 
17332 #if defined(__parallel)
17333 #if !defined(__GNUC__) || __GNUC__ >= 9
17334  cpassert(is_contiguous(msgout))
17335  cpassert(is_contiguous(msgin))
17336 #endif
17337 
17338  scount = SIZE(msgout(:, :))
17339  rcount = scount
17340  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17341  msgin, rcount, mpi_double_precision, &
17342  comm%handle, request%handle, ierr)
17343  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
17344 #else
17345  mark_used(comm)
17346  msgin(:, :, 1, 1) = msgout(:, :)
17347  request = mp_request_null
17348 #endif
17349  CALL mp_timestop(handle)
17350  END SUBROUTINE mp_iallgather_d24
17351 
17352 ! **************************************************************************************************
17353 !> \brief Gathers rank-3 data from all processes and all processes receive the
17354 !> same data
17355 !> \param[in] msgout Rank-3 data to send
17356 !> \param msgin ...
17357 !> \param comm ...
17358 !> \param request ...
17359 !> \note see mp_allgather_d12
17360 ! **************************************************************************************************
17361  SUBROUTINE mp_iallgather_d33(msgout, msgin, comm, request)
17362  REAL(kind=real_8), INTENT(IN) :: msgout(:, :, :)
17363  REAL(kind=real_8), INTENT(OUT) :: msgin(:, :, :)
17364  CLASS(mp_comm_type), INTENT(IN) :: comm
17365  TYPE(mp_request_type), INTENT(OUT) :: request
17366 
17367  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_d33'
17368 
17369  INTEGER :: handle
17370 #if defined(__parallel)
17371  INTEGER :: ierr, rcount, scount
17372 #endif
17373 
17374  CALL mp_timeset(routinen, handle)
17375 
17376 #if defined(__parallel)
17377 #if !defined(__GNUC__) || __GNUC__ >= 9
17378  cpassert(is_contiguous(msgout))
17379  cpassert(is_contiguous(msgin))
17380 #endif
17381 
17382  scount = SIZE(msgout(:, :, :))
17383  rcount = scount
17384  CALL mpi_iallgather(msgout, scount, mpi_double_precision, &
17385  msgin, rcount, mpi_double_precision, &
17386  comm%handle, request%handle, ierr)
17387  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
17388 #else
17389  mark_used(comm)
17390  msgin(:, :, :) = msgout(:, :, :)
17391  request = mp_request_null
17392 #endif
17393  CALL mp_timestop(handle)
17394  END SUBROUTINE mp_iallgather_d33
17395 
17396 ! **************************************************************************************************
17397 !> \brief Gathers vector data from all processes and all processes receive the
17398 !> same data
17399 !> \param[in] msgout Rank-1 data to send
17400 !> \param[out] msgin Received data
17401 !> \param[in] rcount Size of sent data for every process
17402 !> \param[in] rdispl Offset of sent data for every process
17403 !> \param[in] comm Message passing environment identifier
17404 !> \par Data size
17405 !> Processes can send different-sized data
17406 !> \par Ranks
17407 !> The last rank counts the processes
17408 !> \par Offsets
17409 !> Offsets are from 0
17410 !> \par MPI mapping
17411 !> mpi_allgather
17412 ! **************************************************************************************************
17413  SUBROUTINE mp_allgatherv_dv(msgout, msgin, rcount, rdispl, comm)
17414  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
17415  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
17416  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
17417  CLASS(mp_comm_type), INTENT(IN) :: comm
17418 
17419  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_dv'
17420 
17421  INTEGER :: handle
17422 #if defined(__parallel)
17423  INTEGER :: ierr, scount
17424 #endif
17425 
17426  CALL mp_timeset(routinen, handle)
17427 
17428 #if defined(__parallel)
17429  scount = SIZE(msgout)
17430  CALL mpi_allgatherv(msgout, scount, mpi_double_precision, msgin, rcount, &
17431  rdispl, mpi_double_precision, comm%handle, ierr)
17432  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
17433 #else
17434  mark_used(rcount)
17435  mark_used(rdispl)
17436  mark_used(comm)
17437  msgin = msgout
17438 #endif
17439  CALL mp_timestop(handle)
17440  END SUBROUTINE mp_allgatherv_dv
17441 
17442 ! **************************************************************************************************
17443 !> \brief Gathers vector data from all processes and all processes receive the
17444 !> same data
17445 !> \param[in] msgout Rank-1 data to send
17446 !> \param[out] msgin Received data
17447 !> \param[in] rcount Size of sent data for every process
17448 !> \param[in] rdispl Offset of sent data for every process
17449 !> \param[in] comm Message passing environment identifier
17450 !> \par Data size
17451 !> Processes can send different-sized data
17452 !> \par Ranks
17453 !> The last rank counts the processes
17454 !> \par Offsets
17455 !> Offsets are from 0
17456 !> \par MPI mapping
17457 !> mpi_allgather
17458 ! **************************************************************************************************
17459  SUBROUTINE mp_allgatherv_dm2(msgout, msgin, rcount, rdispl, comm)
17460  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
17461  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
17462  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
17463  CLASS(mp_comm_type), INTENT(IN) :: comm
17464 
17465  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_dv'
17466 
17467  INTEGER :: handle
17468 #if defined(__parallel)
17469  INTEGER :: ierr, scount
17470 #endif
17471 
17472  CALL mp_timeset(routinen, handle)
17473 
17474 #if defined(__parallel)
17475  scount = SIZE(msgout)
17476  CALL mpi_allgatherv(msgout, scount, mpi_double_precision, msgin, rcount, &
17477  rdispl, mpi_double_precision, comm%handle, ierr)
17478  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
17479 #else
17480  mark_used(rcount)
17481  mark_used(rdispl)
17482  mark_used(comm)
17483  msgin = msgout
17484 #endif
17485  CALL mp_timestop(handle)
17486  END SUBROUTINE mp_allgatherv_dm2
17487 
17488 ! **************************************************************************************************
17489 !> \brief Gathers vector data from all processes and all processes receive the
17490 !> same data
17491 !> \param[in] msgout Rank-1 data to send
17492 !> \param[out] msgin Received data
17493 !> \param[in] rcount Size of sent data for every process
17494 !> \param[in] rdispl Offset of sent data for every process
17495 !> \param[in] comm Message passing environment identifier
17496 !> \par Data size
17497 !> Processes can send different-sized data
17498 !> \par Ranks
17499 !> The last rank counts the processes
17500 !> \par Offsets
17501 !> Offsets are from 0
17502 !> \par MPI mapping
17503 !> mpi_allgather
17504 ! **************************************************************************************************
17505  SUBROUTINE mp_iallgatherv_dv(msgout, msgin, rcount, rdispl, comm, request)
17506  REAL(kind=real_8), INTENT(IN) :: msgout(:)
17507  REAL(kind=real_8), INTENT(OUT) :: msgin(:)
17508  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
17509  CLASS(mp_comm_type), INTENT(IN) :: comm
17510  TYPE(mp_request_type), INTENT(OUT) :: request
17511 
17512  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_dv'
17513 
17514  INTEGER :: handle
17515 #if defined(__parallel)
17516  INTEGER :: ierr, scount, rsize
17517 #endif
17518 
17519  CALL mp_timeset(routinen, handle)
17520 
17521 #if defined(__parallel)
17522 #if !defined(__GNUC__) || __GNUC__ >= 9
17523  cpassert(is_contiguous(msgout))
17524  cpassert(is_contiguous(msgin))
17525  cpassert(is_contiguous(rcount))
17526  cpassert(is_contiguous(rdispl))
17527 #endif
17528 
17529  scount = SIZE(msgout)
17530  rsize = SIZE(rcount)
17531  CALL mp_iallgatherv_dv_internal(msgout, scount, msgin, rsize, rcount, &
17532  rdispl, comm, request, ierr)
17533  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
17534 #else
17535  mark_used(rcount)
17536  mark_used(rdispl)
17537  mark_used(comm)
17538  msgin = msgout
17539  request = mp_request_null
17540 #endif
17541  CALL mp_timestop(handle)
17542  END SUBROUTINE mp_iallgatherv_dv
17543 
17544 ! **************************************************************************************************
17545 !> \brief Gathers vector data from all processes and all processes receive the
17546 !> same data
17547 !> \param[in] msgout Rank-1 data to send
17548 !> \param[out] msgin Received data
17549 !> \param[in] rcount Size of sent data for every process
17550 !> \param[in] rdispl Offset of sent data for every process
17551 !> \param[in] comm Message passing environment identifier
17552 !> \par Data size
17553 !> Processes can send different-sized data
17554 !> \par Ranks
17555 !> The last rank counts the processes
17556 !> \par Offsets
17557 !> Offsets are from 0
17558 !> \par MPI mapping
17559 !> mpi_allgather
17560 ! **************************************************************************************************
17561  SUBROUTINE mp_iallgatherv_dv2(msgout, msgin, rcount, rdispl, comm, request)
17562  REAL(kind=real_8), INTENT(IN) :: msgout(:)
17563  REAL(kind=real_8), INTENT(OUT) :: msgin(:)
17564  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
17565  CLASS(mp_comm_type), INTENT(IN) :: comm
17566  TYPE(mp_request_type), INTENT(OUT) :: request
17567 
17568  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_dv2'
17569 
17570  INTEGER :: handle
17571 #if defined(__parallel)
17572  INTEGER :: ierr, scount, rsize
17573 #endif
17574 
17575  CALL mp_timeset(routinen, handle)
17576 
17577 #if defined(__parallel)
17578 #if !defined(__GNUC__) || __GNUC__ >= 9
17579  cpassert(is_contiguous(msgout))
17580  cpassert(is_contiguous(msgin))
17581  cpassert(is_contiguous(rcount))
17582  cpassert(is_contiguous(rdispl))
17583 #endif
17584 
17585  scount = SIZE(msgout)
17586  rsize = SIZE(rcount)
17587  CALL mp_iallgatherv_dv_internal(msgout, scount, msgin, rsize, rcount, &
17588  rdispl, comm, request, ierr)
17589  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
17590 #else
17591  mark_used(rcount)
17592  mark_used(rdispl)
17593  mark_used(comm)
17594  msgin = msgout
17595  request = mp_request_null
17596 #endif
17597  CALL mp_timestop(handle)
17598  END SUBROUTINE mp_iallgatherv_dv2
17599 
17600 ! **************************************************************************************************
17601 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
17602 !> the issue is with the rank of rcount and rdispl
17603 !> \param count ...
17604 !> \param array_of_requests ...
17605 !> \param array_of_statuses ...
17606 !> \param ierr ...
17607 !> \author Alfio Lazzaro
17608 ! **************************************************************************************************
17609 #if defined(__parallel)
17610  SUBROUTINE mp_iallgatherv_dv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
17611  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
17612  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
17613  INTEGER, INTENT(IN) :: rsize
17614  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
17615  CLASS(mp_comm_type), INTENT(IN) :: comm
17616  TYPE(mp_request_type), INTENT(OUT) :: request
17617  INTEGER, INTENT(INOUT) :: ierr
17618 
17619  CALL mpi_iallgatherv(msgout, scount, mpi_double_precision, msgin, rcount, &
17620  rdispl, mpi_double_precision, comm%handle, request%handle, ierr)
17621 
17622  END SUBROUTINE mp_iallgatherv_dv_internal
17623 #endif
17624 
17625 ! **************************************************************************************************
17626 !> \brief Sums a vector and partitions the result among processes
17627 !> \param[in] msgout Data to sum
17628 !> \param[out] msgin Received portion of summed data
17629 !> \param[in] rcount Partition sizes of the summed data for
17630 !> every process
17631 !> \param[in] comm Message passing environment identifier
17632 ! **************************************************************************************************
17633  SUBROUTINE mp_sum_scatter_dv(msgout, msgin, rcount, comm)
17634  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
17635  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
17636  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
17637  CLASS(mp_comm_type), INTENT(IN) :: comm
17638 
17639  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_dv'
17640 
17641  INTEGER :: handle
17642 #if defined(__parallel)
17643  INTEGER :: ierr
17644 #endif
17645 
17646  CALL mp_timeset(routinen, handle)
17647 
17648 #if defined(__parallel)
17649  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_double_precision, mpi_sum, &
17650  comm%handle, ierr)
17651  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
17652 
17653  CALL add_perf(perf_id=3, count=1, &
17654  msg_size=rcount(1)*2*real_8_size)
17655 #else
17656  mark_used(rcount)
17657  mark_used(comm)
17658  msgin = msgout(:, 1)
17659 #endif
17660  CALL mp_timestop(handle)
17661  END SUBROUTINE mp_sum_scatter_dv
17662 
17663 ! **************************************************************************************************
17664 !> \brief Sends and receives vector data
17665 !> \param[in] msgin Data to send
17666 !> \param[in] dest Process to send data to
17667 !> \param[out] msgout Received data
17668 !> \param[in] source Process from which to receive
17669 !> \param[in] comm Message passing environment identifier
17670 !> \param[in] tag Send and recv tag (default: 0)
17671 ! **************************************************************************************************
17672  SUBROUTINE mp_sendrecv_d (msgin, dest, msgout, source, comm, tag)
17673  REAL(kind=real_8), INTENT(IN) :: msgin
17674  INTEGER, INTENT(IN) :: dest
17675  REAL(kind=real_8), INTENT(OUT) :: msgout
17676  INTEGER, INTENT(IN) :: source
17677  CLASS(mp_comm_type), INTENT(IN) :: comm
17678  INTEGER, INTENT(IN), OPTIONAL :: tag
17679 
17680  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_d'
17681 
17682  INTEGER :: handle
17683 #if defined(__parallel)
17684  INTEGER :: ierr, msglen_in, msglen_out, &
17685  recv_tag, send_tag
17686 #endif
17687 
17688  CALL mp_timeset(routinen, handle)
17689 
17690 #if defined(__parallel)
17691  msglen_in = 1
17692  msglen_out = 1
17693  send_tag = 0 ! cannot think of something better here, this might be dangerous
17694  recv_tag = 0 ! cannot think of something better here, this might be dangerous
17695  IF (PRESENT(tag)) THEN
17696  send_tag = tag
17697  recv_tag = tag
17698  END IF
17699  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_precision, dest, send_tag, msgout, &
17700  msglen_out, mpi_double_precision, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
17701  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
17702  CALL add_perf(perf_id=7, count=1, &
17703  msg_size=(msglen_in + msglen_out)*real_8_size/2)
17704 #else
17705  mark_used(dest)
17706  mark_used(source)
17707  mark_used(comm)
17708  mark_used(tag)
17709  msgout = msgin
17710 #endif
17711  CALL mp_timestop(handle)
17712  END SUBROUTINE mp_sendrecv_d
17713 
17714 ! **************************************************************************************************
17715 !> \brief Sends and receives vector data
17716 !> \param[in] msgin Data to send
17717 !> \param[in] dest Process to send data to
17718 !> \param[out] msgout Received data
17719 !> \param[in] source Process from which to receive
17720 !> \param[in] comm Message passing environment identifier
17721 !> \param[in] tag Send and recv tag (default: 0)
17722 ! **************************************************************************************************
17723  SUBROUTINE mp_sendrecv_dv(msgin, dest, msgout, source, comm, tag)
17724  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:)
17725  INTEGER, INTENT(IN) :: dest
17726  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:)
17727  INTEGER, INTENT(IN) :: source
17728  CLASS(mp_comm_type), INTENT(IN) :: comm
17729  INTEGER, INTENT(IN), OPTIONAL :: tag
17730 
17731  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_dv'
17732 
17733  INTEGER :: handle
17734 #if defined(__parallel)
17735  INTEGER :: ierr, msglen_in, msglen_out, &
17736  recv_tag, send_tag
17737 #endif
17738 
17739  CALL mp_timeset(routinen, handle)
17740 
17741 #if defined(__parallel)
17742  msglen_in = SIZE(msgin)
17743  msglen_out = SIZE(msgout)
17744  send_tag = 0 ! cannot think of something better here, this might be dangerous
17745  recv_tag = 0 ! cannot think of something better here, this might be dangerous
17746  IF (PRESENT(tag)) THEN
17747  send_tag = tag
17748  recv_tag = tag
17749  END IF
17750  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_precision, dest, send_tag, msgout, &
17751  msglen_out, mpi_double_precision, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
17752  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
17753  CALL add_perf(perf_id=7, count=1, &
17754  msg_size=(msglen_in + msglen_out)*real_8_size/2)
17755 #else
17756  mark_used(dest)
17757  mark_used(source)
17758  mark_used(comm)
17759  mark_used(tag)
17760  msgout = msgin
17761 #endif
17762  CALL mp_timestop(handle)
17763  END SUBROUTINE mp_sendrecv_dv
17764 
17765 ! **************************************************************************************************
17766 !> \brief Sends and receives matrix data
17767 !> \param msgin ...
17768 !> \param dest ...
17769 !> \param msgout ...
17770 !> \param source ...
17771 !> \param comm ...
17772 !> \param tag ...
17773 !> \note see mp_sendrecv_dv
17774 ! **************************************************************************************************
17775  SUBROUTINE mp_sendrecv_dm2(msgin, dest, msgout, source, comm, tag)
17776  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
17777  INTEGER, INTENT(IN) :: dest
17778  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
17779  INTEGER, INTENT(IN) :: source
17780  CLASS(mp_comm_type), INTENT(IN) :: comm
17781  INTEGER, INTENT(IN), OPTIONAL :: tag
17782 
17783  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_dm2'
17784 
17785  INTEGER :: handle
17786 #if defined(__parallel)
17787  INTEGER :: ierr, msglen_in, msglen_out, &
17788  recv_tag, send_tag
17789 #endif
17790 
17791  CALL mp_timeset(routinen, handle)
17792 
17793 #if defined(__parallel)
17794  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
17795  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
17796  send_tag = 0 ! cannot think of something better here, this might be dangerous
17797  recv_tag = 0 ! cannot think of something better here, this might be dangerous
17798  IF (PRESENT(tag)) THEN
17799  send_tag = tag
17800  recv_tag = tag
17801  END IF
17802  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_precision, dest, send_tag, msgout, &
17803  msglen_out, mpi_double_precision, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
17804  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
17805  CALL add_perf(perf_id=7, count=1, &
17806  msg_size=(msglen_in + msglen_out)*real_8_size/2)
17807 #else
17808  mark_used(dest)
17809  mark_used(source)
17810  mark_used(comm)
17811  mark_used(tag)
17812  msgout = msgin
17813 #endif
17814  CALL mp_timestop(handle)
17815  END SUBROUTINE mp_sendrecv_dm2
17816 
17817 ! **************************************************************************************************
17818 !> \brief Sends and receives rank-3 data
17819 !> \param msgin ...
17820 !> \param dest ...
17821 !> \param msgout ...
17822 !> \param source ...
17823 !> \param comm ...
17824 !> \note see mp_sendrecv_dv
17825 ! **************************************************************************************************
17826  SUBROUTINE mp_sendrecv_dm3(msgin, dest, msgout, source, comm, tag)
17827  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
17828  INTEGER, INTENT(IN) :: dest
17829  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
17830  INTEGER, INTENT(IN) :: source
17831  CLASS(mp_comm_type), INTENT(IN) :: comm
17832  INTEGER, INTENT(IN), OPTIONAL :: tag
17833 
17834  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_dm3'
17835 
17836  INTEGER :: handle
17837 #if defined(__parallel)
17838  INTEGER :: ierr, msglen_in, msglen_out, &
17839  recv_tag, send_tag
17840 #endif
17841 
17842  CALL mp_timeset(routinen, handle)
17843 
17844 #if defined(__parallel)
17845  msglen_in = SIZE(msgin)
17846  msglen_out = SIZE(msgout)
17847  send_tag = 0 ! cannot think of something better here, this might be dangerous
17848  recv_tag = 0 ! cannot think of something better here, this might be dangerous
17849  IF (PRESENT(tag)) THEN
17850  send_tag = tag
17851  recv_tag = tag
17852  END IF
17853  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_precision, dest, send_tag, msgout, &
17854  msglen_out, mpi_double_precision, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
17855  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
17856  CALL add_perf(perf_id=7, count=1, &
17857  msg_size=(msglen_in + msglen_out)*real_8_size/2)
17858 #else
17859  mark_used(dest)
17860  mark_used(source)
17861  mark_used(comm)
17862  mark_used(tag)
17863  msgout = msgin
17864 #endif
17865  CALL mp_timestop(handle)
17866  END SUBROUTINE mp_sendrecv_dm3
17867 
17868 ! **************************************************************************************************
17869 !> \brief Sends and receives rank-4 data
17870 !> \param msgin ...
17871 !> \param dest ...
17872 !> \param msgout ...
17873 !> \param source ...
17874 !> \param comm ...
17875 !> \note see mp_sendrecv_dv
17876 ! **************************************************************************************************
17877  SUBROUTINE mp_sendrecv_dm4(msgin, dest, msgout, source, comm, tag)
17878  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
17879  INTEGER, INTENT(IN) :: dest
17880  REAL(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
17881  INTEGER, INTENT(IN) :: source
17882  CLASS(mp_comm_type), INTENT(IN) :: comm
17883  INTEGER, INTENT(IN), OPTIONAL :: tag
17884 
17885  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_dm4'
17886 
17887  INTEGER :: handle
17888 #if defined(__parallel)
17889  INTEGER :: ierr, msglen_in, msglen_out, &
17890  recv_tag, send_tag
17891 #endif
17892 
17893  CALL mp_timeset(routinen, handle)
17894 
17895 #if defined(__parallel)
17896  msglen_in = SIZE(msgin)
17897  msglen_out = SIZE(msgout)
17898  send_tag = 0 ! cannot think of something better here, this might be dangerous
17899  recv_tag = 0 ! cannot think of something better here, this might be dangerous
17900  IF (PRESENT(tag)) THEN
17901  send_tag = tag
17902  recv_tag = tag
17903  END IF
17904  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_precision, dest, send_tag, msgout, &
17905  msglen_out, mpi_double_precision, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
17906  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
17907  CALL add_perf(perf_id=7, count=1, &
17908  msg_size=(msglen_in + msglen_out)*real_8_size/2)
17909 #else
17910  mark_used(dest)
17911  mark_used(source)
17912  mark_used(comm)
17913  mark_used(tag)
17914  msgout = msgin
17915 #endif
17916  CALL mp_timestop(handle)
17917  END SUBROUTINE mp_sendrecv_dm4
17918 
17919 ! **************************************************************************************************
17920 !> \brief Non-blocking send and receive of a scalar
17921 !> \param[in] msgin Scalar data to send
17922 !> \param[in] dest Which process to send to
17923 !> \param[out] msgout Receive data into this pointer
17924 !> \param[in] source Process to receive from
17925 !> \param[in] comm Message passing environment identifier
17926 !> \param[out] send_request Request handle for the send
17927 !> \param[out] recv_request Request handle for the receive
17928 !> \param[in] tag (optional) tag to differentiate requests
17929 !> \par Implementation
17930 !> Calls mpi_isend and mpi_irecv.
17931 !> \par History
17932 !> 02.2005 created [Alfio Lazzaro]
17933 ! **************************************************************************************************
17934  SUBROUTINE mp_isendrecv_d (msgin, dest, msgout, source, comm, send_request, &
17935  recv_request, tag)
17936  REAL(kind=real_8), INTENT(IN) :: msgin
17937  INTEGER, INTENT(IN) :: dest
17938  REAL(kind=real_8), INTENT(INOUT) :: msgout
17939  INTEGER, INTENT(IN) :: source
17940  CLASS(mp_comm_type), INTENT(IN) :: comm
17941  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
17942  INTEGER, INTENT(in), OPTIONAL :: tag
17943 
17944  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_d'
17945 
17946  INTEGER :: handle
17947 #if defined(__parallel)
17948  INTEGER :: ierr, my_tag
17949 #endif
17950 
17951  CALL mp_timeset(routinen, handle)
17952 
17953 #if defined(__parallel)
17954  my_tag = 0
17955  IF (PRESENT(tag)) my_tag = tag
17956 
17957  CALL mpi_irecv(msgout, 1, mpi_double_precision, source, my_tag, &
17958  comm%handle, recv_request%handle, ierr)
17959  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
17960 
17961  CALL mpi_isend(msgin, 1, mpi_double_precision, dest, my_tag, &
17962  comm%handle, send_request%handle, ierr)
17963  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
17964 
17965  CALL add_perf(perf_id=8, count=1, msg_size=2*real_8_size)
17966 #else
17967  mark_used(dest)
17968  mark_used(source)
17969  mark_used(comm)
17970  mark_used(tag)
17971  send_request = mp_request_null
17972  recv_request = mp_request_null
17973  msgout = msgin
17974 #endif
17975  CALL mp_timestop(handle)
17976  END SUBROUTINE mp_isendrecv_d
17977 
17978 ! **************************************************************************************************
17979 !> \brief Non-blocking send and receive of a vector
17980 !> \param[in] msgin Vector data to send
17981 !> \param[in] dest Which process to send to
17982 !> \param[out] msgout Receive data into this pointer
17983 !> \param[in] source Process to receive from
17984 !> \param[in] comm Message passing environment identifier
17985 !> \param[out] send_request Request handle for the send
17986 !> \param[out] recv_request Request handle for the receive
17987 !> \param[in] tag (optional) tag to differentiate requests
17988 !> \par Implementation
17989 !> Calls mpi_isend and mpi_irecv.
17990 !> \par History
17991 !> 11.2004 created [Joost VandeVondele]
17992 !> \note
17993 !> arrays can be pointers or assumed shape, but they must be contiguous!
17994 ! **************************************************************************************************
17995  SUBROUTINE mp_isendrecv_dv(msgin, dest, msgout, source, comm, send_request, &
17996  recv_request, tag)
17997  REAL(kind=real_8), DIMENSION(:), INTENT(IN) :: msgin
17998  INTEGER, INTENT(IN) :: dest
17999  REAL(kind=real_8), DIMENSION(:), INTENT(INOUT) :: msgout
18000  INTEGER, INTENT(IN) :: source
18001  CLASS(mp_comm_type), INTENT(IN) :: comm
18002  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
18003  INTEGER, INTENT(in), OPTIONAL :: tag
18004 
18005  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_dv'
18006 
18007  INTEGER :: handle
18008 #if defined(__parallel)
18009  INTEGER :: ierr, msglen, my_tag
18010  REAL(kind=real_8) :: foo
18011 #endif
18012 
18013  CALL mp_timeset(routinen, handle)
18014 
18015 #if defined(__parallel)
18016 #if !defined(__GNUC__) || __GNUC__ >= 9
18017  cpassert(is_contiguous(msgout))
18018  cpassert(is_contiguous(msgin))
18019 #endif
18020 
18021  my_tag = 0
18022  IF (PRESENT(tag)) my_tag = tag
18023 
18024  msglen = SIZE(msgout, 1)
18025  IF (msglen > 0) THEN
18026  CALL mpi_irecv(msgout(1), msglen, mpi_double_precision, source, my_tag, &
18027  comm%handle, recv_request%handle, ierr)
18028  ELSE
18029  CALL mpi_irecv(foo, msglen, mpi_double_precision, source, my_tag, &
18030  comm%handle, recv_request%handle, ierr)
18031  END IF
18032  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
18033 
18034  msglen = SIZE(msgin, 1)
18035  IF (msglen > 0) THEN
18036  CALL mpi_isend(msgin(1), msglen, mpi_double_precision, dest, my_tag, &
18037  comm%handle, send_request%handle, ierr)
18038  ELSE
18039  CALL mpi_isend(foo, msglen, mpi_double_precision, dest, my_tag, &
18040  comm%handle, send_request%handle, ierr)
18041  END IF
18042  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
18043 
18044  msglen = (msglen + SIZE(msgout, 1) + 1)/2
18045  CALL add_perf(perf_id=8, count=1, msg_size=msglen*real_8_size)
18046 #else
18047  mark_used(dest)
18048  mark_used(source)
18049  mark_used(comm)
18050  mark_used(tag)
18051  send_request = mp_request_null
18052  recv_request = mp_request_null
18053  msgout = msgin
18054 #endif
18055  CALL mp_timestop(handle)
18056  END SUBROUTINE mp_isendrecv_dv
18057 
18058 ! **************************************************************************************************
18059 !> \brief Non-blocking send of vector data
18060 !> \param msgin ...
18061 !> \param dest ...
18062 !> \param comm ...
18063 !> \param request ...
18064 !> \param tag ...
18065 !> \par History
18066 !> 08.2003 created [f&j]
18067 !> \note see mp_isendrecv_dv
18068 !> \note
18069 !> arrays can be pointers or assumed shape, but they must be contiguous!
18070 ! **************************************************************************************************
18071  SUBROUTINE mp_isend_dv(msgin, dest, comm, request, tag)
18072  REAL(kind=real_8), DIMENSION(:), INTENT(IN) :: msgin
18073  INTEGER, INTENT(IN) :: dest
18074  CLASS(mp_comm_type), INTENT(IN) :: comm
18075  TYPE(mp_request_type), INTENT(out) :: request
18076  INTEGER, INTENT(in), OPTIONAL :: tag
18077 
18078  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_dv'
18079 
18080  INTEGER :: handle, ierr
18081 #if defined(__parallel)
18082  INTEGER :: msglen, my_tag
18083  REAL(kind=real_8) :: foo(1)
18084 #endif
18085 
18086  CALL mp_timeset(routinen, handle)
18087 
18088 #if defined(__parallel)
18089 #if !defined(__GNUC__) || __GNUC__ >= 9
18090  cpassert(is_contiguous(msgin))
18091 #endif
18092  my_tag = 0
18093  IF (PRESENT(tag)) my_tag = tag
18094 
18095  msglen = SIZE(msgin)
18096  IF (msglen > 0) THEN
18097  CALL mpi_isend(msgin(1), msglen, mpi_double_precision, dest, my_tag, &
18098  comm%handle, request%handle, ierr)
18099  ELSE
18100  CALL mpi_isend(foo, msglen, mpi_double_precision, dest, my_tag, &
18101  comm%handle, request%handle, ierr)
18102  END IF
18103  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
18104 
18105  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_8_size)
18106 #else
18107  mark_used(msgin)
18108  mark_used(dest)
18109  mark_used(comm)
18110  mark_used(request)
18111  mark_used(tag)
18112  ierr = 1
18113  request = mp_request_null
18114  CALL mp_stop(ierr, "mp_isend called in non parallel case")
18115 #endif
18116  CALL mp_timestop(handle)
18117  END SUBROUTINE mp_isend_dv
18118 
18119 ! **************************************************************************************************
18120 !> \brief Non-blocking send of matrix data
18121 !> \param msgin ...
18122 !> \param dest ...
18123 !> \param comm ...
18124 !> \param request ...
18125 !> \param tag ...
18126 !> \par History
18127 !> 2009-11-25 [UB] Made type-generic for templates
18128 !> \author fawzi
18129 !> \note see mp_isendrecv_dv
18130 !> \note see mp_isend_dv
18131 !> \note
18132 !> arrays can be pointers or assumed shape, but they must be contiguous!
18133 ! **************************************************************************************************
18134  SUBROUTINE mp_isend_dm2(msgin, dest, comm, request, tag)
18135  REAL(kind=real_8), DIMENSION(:, :), INTENT(IN) :: msgin
18136  INTEGER, INTENT(IN) :: dest
18137  CLASS(mp_comm_type), INTENT(IN) :: comm
18138  TYPE(mp_request_type), INTENT(out) :: request
18139  INTEGER, INTENT(in), OPTIONAL :: tag
18140 
18141  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_dm2'
18142 
18143  INTEGER :: handle, ierr
18144 #if defined(__parallel)
18145  INTEGER :: msglen, my_tag
18146  REAL(kind=real_8) :: foo(1)
18147 #endif
18148 
18149  CALL mp_timeset(routinen, handle)
18150 
18151 #if defined(__parallel)
18152 #if !defined(__GNUC__) || __GNUC__ >= 9
18153  cpassert(is_contiguous(msgin))
18154 #endif
18155 
18156  my_tag = 0
18157  IF (PRESENT(tag)) my_tag = tag
18158 
18159  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
18160  IF (msglen > 0) THEN
18161  CALL mpi_isend(msgin(1, 1), msglen, mpi_double_precision, dest, my_tag, &
18162  comm%handle, request%handle, ierr)
18163  ELSE
18164  CALL mpi_isend(foo, msglen, mpi_double_precision, dest, my_tag, &
18165  comm%handle, request%handle, ierr)
18166  END IF
18167  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
18168 
18169  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_8_size)
18170 #else
18171  mark_used(msgin)
18172  mark_used(dest)
18173  mark_used(comm)
18174  mark_used(request)
18175  mark_used(tag)
18176  ierr = 1
18177  request = mp_request_null
18178  CALL mp_stop(ierr, "mp_isend called in non parallel case")
18179 #endif
18180  CALL mp_timestop(handle)
18181  END SUBROUTINE mp_isend_dm2
18182 
18183 ! **************************************************************************************************
18184 !> \brief Non-blocking send of rank-3 data
18185 !> \param msgin ...
18186 !> \param dest ...
18187 !> \param comm ...
18188 !> \param request ...
18189 !> \param tag ...
18190 !> \par History
18191 !> 9.2008 added _rm3 subroutine [Iain Bethune]
18192 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
18193 !> 2009-11-25 [UB] Made type-generic for templates
18194 !> \author fawzi
18195 !> \note see mp_isendrecv_dv
18196 !> \note see mp_isend_dv
18197 !> \note
18198 !> arrays can be pointers or assumed shape, but they must be contiguous!
18199 ! **************************************************************************************************
18200  SUBROUTINE mp_isend_dm3(msgin, dest, comm, request, tag)
18201  REAL(kind=real_8), DIMENSION(:, :, :), INTENT(IN) :: msgin
18202  INTEGER, INTENT(IN) :: dest
18203  CLASS(mp_comm_type), INTENT(IN) :: comm
18204  TYPE(mp_request_type), INTENT(out) :: request
18205  INTEGER, INTENT(in), OPTIONAL :: tag
18206 
18207  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_dm3'
18208 
18209  INTEGER :: handle, ierr
18210 #if defined(__parallel)
18211  INTEGER :: msglen, my_tag
18212  REAL(kind=real_8) :: foo(1)
18213 #endif
18214 
18215  CALL mp_timeset(routinen, handle)
18216 
18217 #if defined(__parallel)
18218 #if !defined(__GNUC__) || __GNUC__ >= 9
18219  cpassert(is_contiguous(msgin))
18220 #endif
18221 
18222  my_tag = 0
18223  IF (PRESENT(tag)) my_tag = tag
18224 
18225  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
18226  IF (msglen > 0) THEN
18227  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_double_precision, dest, my_tag, &
18228  comm%handle, request%handle, ierr)
18229  ELSE
18230  CALL mpi_isend(foo, msglen, mpi_double_precision, dest, my_tag, &
18231  comm%handle, request%handle, ierr)
18232  END IF
18233  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
18234 
18235  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_8_size)
18236 #else
18237  mark_used(msgin)
18238  mark_used(dest)
18239  mark_used(comm)
18240  mark_used(request)
18241  mark_used(tag)
18242  ierr = 1
18243  request = mp_request_null
18244  CALL mp_stop(ierr, "mp_isend called in non parallel case")
18245 #endif
18246  CALL mp_timestop(handle)
18247  END SUBROUTINE mp_isend_dm3
18248 
18249 ! **************************************************************************************************
18250 !> \brief Non-blocking send of rank-4 data
18251 !> \param msgin the input message
18252 !> \param dest the destination processor
18253 !> \param comm the communicator object
18254 !> \param request the communication request id
18255 !> \param tag the message tag
18256 !> \par History
18257 !> 2.2016 added _dm4 subroutine [Nico Holmberg]
18258 !> \author fawzi
18259 !> \note see mp_isend_dv
18260 !> \note
18261 !> arrays can be pointers or assumed shape, but they must be contiguous!
18262 ! **************************************************************************************************
18263  SUBROUTINE mp_isend_dm4(msgin, dest, comm, request, tag)
18264  REAL(kind=real_8), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
18265  INTEGER, INTENT(IN) :: dest
18266  CLASS(mp_comm_type), INTENT(IN) :: comm
18267  TYPE(mp_request_type), INTENT(out) :: request
18268  INTEGER, INTENT(in), OPTIONAL :: tag
18269 
18270  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_dm4'
18271 
18272  INTEGER :: handle, ierr
18273 #if defined(__parallel)
18274  INTEGER :: msglen, my_tag
18275  REAL(kind=real_8) :: foo(1)
18276 #endif
18277 
18278  CALL mp_timeset(routinen, handle)
18279 
18280 #if defined(__parallel)
18281 #if !defined(__GNUC__) || __GNUC__ >= 9
18282  cpassert(is_contiguous(msgin))
18283 #endif
18284 
18285  my_tag = 0
18286  IF (PRESENT(tag)) my_tag = tag
18287 
18288  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
18289  IF (msglen > 0) THEN
18290  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_double_precision, dest, my_tag, &
18291  comm%handle, request%handle, ierr)
18292  ELSE
18293  CALL mpi_isend(foo, msglen, mpi_double_precision, dest, my_tag, &
18294  comm%handle, request%handle, ierr)
18295  END IF
18296  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
18297 
18298  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_8_size)
18299 #else
18300  mark_used(msgin)
18301  mark_used(dest)
18302  mark_used(comm)
18303  mark_used(request)
18304  mark_used(tag)
18305  ierr = 1
18306  request = mp_request_null
18307  CALL mp_stop(ierr, "mp_isend called in non parallel case")
18308 #endif
18309  CALL mp_timestop(handle)
18310  END SUBROUTINE mp_isend_dm4
18311 
18312 ! **************************************************************************************************
18313 !> \brief Non-blocking receive of vector data
18314 !> \param msgout ...
18315 !> \param source ...
18316 !> \param comm ...
18317 !> \param request ...
18318 !> \param tag ...
18319 !> \par History
18320 !> 08.2003 created [f&j]
18321 !> 2009-11-25 [UB] Made type-generic for templates
18322 !> \note see mp_isendrecv_dv
18323 !> \note
18324 !> arrays can be pointers or assumed shape, but they must be contiguous!
18325 ! **************************************************************************************************
18326  SUBROUTINE mp_irecv_dv(msgout, source, comm, request, tag)
18327  REAL(kind=real_8), DIMENSION(:), INTENT(INOUT) :: msgout
18328  INTEGER, INTENT(IN) :: source
18329  CLASS(mp_comm_type), INTENT(IN) :: comm
18330  TYPE(mp_request_type), INTENT(out) :: request
18331  INTEGER, INTENT(in), OPTIONAL :: tag
18332 
18333  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_dv'
18334 
18335  INTEGER :: handle
18336 #if defined(__parallel)
18337  INTEGER :: ierr, msglen, my_tag
18338  REAL(kind=real_8) :: foo(1)
18339 #endif
18340 
18341  CALL mp_timeset(routinen, handle)
18342 
18343 #if defined(__parallel)
18344 #if !defined(__GNUC__) || __GNUC__ >= 9
18345  cpassert(is_contiguous(msgout))
18346 #endif
18347 
18348  my_tag = 0
18349  IF (PRESENT(tag)) my_tag = tag
18350 
18351  msglen = SIZE(msgout)
18352  IF (msglen > 0) THEN
18353  CALL mpi_irecv(msgout(1), msglen, mpi_double_precision, source, my_tag, &
18354  comm%handle, request%handle, ierr)
18355  ELSE
18356  CALL mpi_irecv(foo, msglen, mpi_double_precision, source, my_tag, &
18357  comm%handle, request%handle, ierr)
18358  END IF
18359  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
18360 
18361  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_8_size)
18362 #else
18363  cpabort("mp_irecv called in non parallel case")
18364  mark_used(msgout)
18365  mark_used(source)
18366  mark_used(comm)
18367  mark_used(tag)
18368  request = mp_request_null
18369 #endif
18370  CALL mp_timestop(handle)
18371  END SUBROUTINE mp_irecv_dv
18372 
18373 ! **************************************************************************************************
18374 !> \brief Non-blocking receive of matrix data
18375 !> \param msgout ...
18376 !> \param source ...
18377 !> \param comm ...
18378 !> \param request ...
18379 !> \param tag ...
18380 !> \par History
18381 !> 2009-11-25 [UB] Made type-generic for templates
18382 !> \author fawzi
18383 !> \note see mp_isendrecv_dv
18384 !> \note see mp_irecv_dv
18385 !> \note
18386 !> arrays can be pointers or assumed shape, but they must be contiguous!
18387 ! **************************************************************************************************
18388  SUBROUTINE mp_irecv_dm2(msgout, source, comm, request, tag)
18389  REAL(kind=real_8), DIMENSION(:, :), INTENT(INOUT) :: msgout
18390  INTEGER, INTENT(IN) :: source
18391  CLASS(mp_comm_type), INTENT(IN) :: comm
18392  TYPE(mp_request_type), INTENT(out) :: request
18393  INTEGER, INTENT(in), OPTIONAL :: tag
18394 
18395  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_dm2'
18396 
18397  INTEGER :: handle
18398 #if defined(__parallel)
18399  INTEGER :: ierr, msglen, my_tag
18400  REAL(kind=real_8) :: foo(1)
18401 #endif
18402 
18403  CALL mp_timeset(routinen, handle)
18404 
18405 #if defined(__parallel)
18406 #if !defined(__GNUC__) || __GNUC__ >= 9
18407  cpassert(is_contiguous(msgout))
18408 #endif
18409 
18410  my_tag = 0
18411  IF (PRESENT(tag)) my_tag = tag
18412 
18413  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
18414  IF (msglen > 0) THEN
18415  CALL mpi_irecv(msgout(1, 1), msglen, mpi_double_precision, source, my_tag, &
18416  comm%handle, request%handle, ierr)
18417  ELSE
18418  CALL mpi_irecv(foo, msglen, mpi_double_precision, source, my_tag, &
18419  comm%handle, request%handle, ierr)
18420  END IF
18421  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
18422 
18423  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_8_size)
18424 #else
18425  mark_used(msgout)
18426  mark_used(source)
18427  mark_used(comm)
18428  mark_used(tag)
18429  request = mp_request_null
18430  cpabort("mp_irecv called in non parallel case")
18431 #endif
18432  CALL mp_timestop(handle)
18433  END SUBROUTINE mp_irecv_dm2
18434 
18435 ! **************************************************************************************************
18436 !> \brief Non-blocking send of rank-3 data
18437 !> \param msgout ...
18438 !> \param source ...
18439 !> \param comm ...
18440 !> \param request ...
18441 !> \param tag ...
18442 !> \par History
18443 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
18444 !> 2009-11-25 [UB] Made type-generic for templates
18445 !> \author fawzi
18446 !> \note see mp_isendrecv_dv
18447 !> \note see mp_irecv_dv
18448 !> \note
18449 !> arrays can be pointers or assumed shape, but they must be contiguous!
18450 ! **************************************************************************************************
18451  SUBROUTINE mp_irecv_dm3(msgout, source, comm, request, tag)
18452  REAL(kind=real_8), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
18453  INTEGER, INTENT(IN) :: source
18454  CLASS(mp_comm_type), INTENT(IN) :: comm
18455  TYPE(mp_request_type), INTENT(out) :: request
18456  INTEGER, INTENT(in), OPTIONAL :: tag
18457 
18458  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_dm3'
18459 
18460  INTEGER :: handle
18461 #if defined(__parallel)
18462  INTEGER :: ierr, msglen, my_tag
18463  REAL(kind=real_8) :: foo(1)
18464 #endif
18465 
18466  CALL mp_timeset(routinen, handle)
18467 
18468 #if defined(__parallel)
18469 #if !defined(__GNUC__) || __GNUC__ >= 9
18470  cpassert(is_contiguous(msgout))
18471 #endif
18472 
18473  my_tag = 0
18474  IF (PRESENT(tag)) my_tag = tag
18475 
18476  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
18477  IF (msglen > 0) THEN
18478  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_double_precision, source, my_tag, &
18479  comm%handle, request%handle, ierr)
18480  ELSE
18481  CALL mpi_irecv(foo, msglen, mpi_double_precision, source, my_tag, &
18482  comm%handle, request%handle, ierr)
18483  END IF
18484  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
18485 
18486  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_8_size)
18487 #else
18488  mark_used(msgout)
18489  mark_used(source)
18490  mark_used(comm)
18491  mark_used(tag)
18492  request = mp_request_null
18493  cpabort("mp_irecv called in non parallel case")
18494 #endif
18495  CALL mp_timestop(handle)
18496  END SUBROUTINE mp_irecv_dm3
18497 
18498 ! **************************************************************************************************
18499 !> \brief Non-blocking receive of rank-4 data
18500 !> \param msgout the output message
18501 !> \param source the source processor
18502 !> \param comm the communicator object
18503 !> \param request the communication request id
18504 !> \param tag the message tag
18505 !> \par History
18506 !> 2.2016 added _dm4 subroutine [Nico Holmberg]
18507 !> \author fawzi
18508 !> \note see mp_irecv_dv
18509 !> \note
18510 !> arrays can be pointers or assumed shape, but they must be contiguous!
18511 ! **************************************************************************************************
18512  SUBROUTINE mp_irecv_dm4(msgout, source, comm, request, tag)
18513  REAL(kind=real_8), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
18514  INTEGER, INTENT(IN) :: source
18515  CLASS(mp_comm_type), INTENT(IN) :: comm
18516  TYPE(mp_request_type), INTENT(out) :: request
18517  INTEGER, INTENT(in), OPTIONAL :: tag
18518 
18519  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_dm4'
18520 
18521  INTEGER :: handle
18522 #if defined(__parallel)
18523  INTEGER :: ierr, msglen, my_tag
18524  REAL(kind=real_8) :: foo(1)
18525 #endif
18526 
18527  CALL mp_timeset(routinen, handle)
18528 
18529 #if defined(__parallel)
18530 #if !defined(__GNUC__) || __GNUC__ >= 9
18531  cpassert(is_contiguous(msgout))
18532 #endif
18533 
18534  my_tag = 0
18535  IF (PRESENT(tag)) my_tag = tag
18536 
18537  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
18538  IF (msglen > 0) THEN
18539  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_double_precision, source, my_tag, &
18540  comm%handle, request%handle, ierr)
18541  ELSE
18542  CALL mpi_irecv(foo, msglen, mpi_double_precision, source, my_tag, &
18543  comm%handle, request%handle, ierr)
18544  END IF
18545  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
18546 
18547  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_8_size)
18548 #else
18549  mark_used(msgout)
18550  mark_used(source)
18551  mark_used(comm)
18552  mark_used(tag)
18553  request = mp_request_null
18554  cpabort("mp_irecv called in non parallel case")
18555 #endif
18556  CALL mp_timestop(handle)
18557  END SUBROUTINE mp_irecv_dm4
18558 
18559 ! **************************************************************************************************
18560 !> \brief Window initialization function for vector data
18561 !> \param base ...
18562 !> \param comm ...
18563 !> \param win ...
18564 !> \par History
18565 !> 02.2015 created [Alfio Lazzaro]
18566 !> \note
18567 !> arrays can be pointers or assumed shape, but they must be contiguous!
18568 ! **************************************************************************************************
18569  SUBROUTINE mp_win_create_dv(base, comm, win)
18570  REAL(kind=real_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
18571  TYPE(mp_comm_type), INTENT(IN) :: comm
18572  CLASS(mp_win_type), INTENT(INOUT) :: win
18573 
18574  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_dv'
18575 
18576  INTEGER :: handle
18577 #if defined(__parallel)
18578  INTEGER :: ierr
18579  INTEGER(kind=mpi_address_kind) :: len
18580  REAL(kind=real_8) :: foo(1)
18581 #endif
18582 
18583  CALL mp_timeset(routinen, handle)
18584 
18585 #if defined(__parallel)
18586 
18587  len = SIZE(base)*real_8_size
18588  IF (len > 0) THEN
18589  CALL mpi_win_create(base(1), len, real_8_size, mpi_info_null, comm%handle, win%handle, ierr)
18590  ELSE
18591  CALL mpi_win_create(foo, len, real_8_size, mpi_info_null, comm%handle, win%handle, ierr)
18592  END IF
18593  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
18594 
18595  CALL add_perf(perf_id=20, count=1)
18596 #else
18597  mark_used(base)
18598  mark_used(comm)
18599  win%handle = mp_win_null_handle
18600 #endif
18601  CALL mp_timestop(handle)
18602  END SUBROUTINE mp_win_create_dv
18603 
18604 ! **************************************************************************************************
18605 !> \brief Single-sided get function for vector data
18606 !> \param base ...
18607 !> \param comm ...
18608 !> \param win ...
18609 !> \par History
18610 !> 02.2015 created [Alfio Lazzaro]
18611 !> \note
18612 !> arrays can be pointers or assumed shape, but they must be contiguous!
18613 ! **************************************************************************************************
18614  SUBROUTINE mp_rget_dv(base, source, win, win_data, myproc, disp, request, &
18615  origin_datatype, target_datatype)
18616  REAL(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
18617  INTEGER, INTENT(IN) :: source
18618  CLASS(mp_win_type), INTENT(IN) :: win
18619  REAL(kind=real_8), DIMENSION(:), INTENT(IN) :: win_data
18620  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
18621  TYPE(mp_request_type), INTENT(OUT) :: request
18622  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
18623 
18624  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_dv'
18625 
18626  INTEGER :: handle
18627 #if defined(__parallel)
18628  INTEGER :: ierr, len, &
18629  origin_len, target_len
18630  LOGICAL :: do_local_copy
18631  INTEGER(kind=mpi_address_kind) :: disp_aint
18632  mpi_data_type :: handle_origin_datatype, handle_target_datatype
18633 #endif
18634 
18635  CALL mp_timeset(routinen, handle)
18636 
18637 #if defined(__parallel)
18638  len = SIZE(base)
18639  disp_aint = 0
18640  IF (PRESENT(disp)) THEN
18641  disp_aint = int(disp, kind=mpi_address_kind)
18642  END IF
18643  handle_origin_datatype = mpi_double_precision
18644  origin_len = len
18645  IF (PRESENT(origin_datatype)) THEN
18646  handle_origin_datatype = origin_datatype%type_handle
18647  origin_len = 1
18648  END IF
18649  handle_target_datatype = mpi_double_precision
18650  target_len = len
18651  IF (PRESENT(target_datatype)) THEN
18652  handle_target_datatype = target_datatype%type_handle
18653  target_len = 1
18654  END IF
18655  IF (len > 0) THEN
18656  do_local_copy = .false.
18657  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
18658  IF (myproc .EQ. source) do_local_copy = .true.
18659  END IF
18660  IF (do_local_copy) THEN
18661  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
18662  base(:) = win_data(disp_aint + 1:disp_aint + len)
18663  !$OMP END PARALLEL WORKSHARE
18664  request = mp_request_null
18665  ierr = 0
18666  ELSE
18667  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
18668  target_len, handle_target_datatype, win%handle, request%handle, ierr)
18669  END IF
18670  ELSE
18671  request = mp_request_null
18672  ierr = 0
18673  END IF
18674  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
18675 
18676  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*real_8_size)
18677 #else
18678  mark_used(source)
18679  mark_used(win)
18680  mark_used(myproc)
18681  mark_used(origin_datatype)
18682  mark_used(target_datatype)
18683 
18684  request = mp_request_null
18685  !
18686  IF (PRESENT(disp)) THEN
18687  base(:) = win_data(disp + 1:disp + SIZE(base))
18688  ELSE
18689  base(:) = win_data(:SIZE(base))
18690  END IF
18691 
18692 #endif
18693  CALL mp_timestop(handle)
18694  END SUBROUTINE mp_rget_dv
18695 
18696 ! **************************************************************************************************
18697 !> \brief ...
18698 !> \param count ...
18699 !> \param lengths ...
18700 !> \param displs ...
18701 !> \return ...
18702 ! ***************************************************************************
18703  FUNCTION mp_type_indexed_make_d (count, lengths, displs) &
18704  result(type_descriptor)
18705  INTEGER, INTENT(IN) :: count
18706  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
18707  TYPE(mp_type_descriptor_type) :: type_descriptor
18708 
18709  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_d'
18710 
18711  INTEGER :: handle
18712 #if defined(__parallel)
18713  INTEGER :: ierr
18714 #endif
18715 
18716  CALL mp_timeset(routinen, handle)
18717 
18718 #if defined(__parallel)
18719  CALL mpi_type_indexed(count, lengths, displs, mpi_double_precision, &
18720  type_descriptor%type_handle, ierr)
18721  IF (ierr /= 0) &
18722  cpabort("MPI_Type_Indexed @ "//routinen)
18723  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
18724  IF (ierr /= 0) &
18725  cpabort("MPI_Type_commit @ "//routinen)
18726 #else
18727  type_descriptor%type_handle = 3
18728 #endif
18729  type_descriptor%length = count
18730  NULLIFY (type_descriptor%subtype)
18731  type_descriptor%vector_descriptor(1:2) = 1
18732  type_descriptor%has_indexing = .true.
18733  type_descriptor%index_descriptor%index => lengths
18734  type_descriptor%index_descriptor%chunks => displs
18735 
18736  CALL mp_timestop(handle)
18737 
18738  END FUNCTION mp_type_indexed_make_d
18739 
18740 ! **************************************************************************************************
18741 !> \brief Allocates special parallel memory
18742 !> \param[in] DATA pointer to integer array to allocate
18743 !> \param[in] len number of integers to allocate
18744 !> \param[out] stat (optional) allocation status result
18745 !> \author UB
18746 ! **************************************************************************************************
18747  SUBROUTINE mp_allocate_d (DATA, len, stat)
18748  REAL(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
18749  INTEGER, INTENT(IN) :: len
18750  INTEGER, INTENT(OUT), OPTIONAL :: stat
18751 
18752  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_d'
18753 
18754  INTEGER :: handle, ierr
18755 
18756  CALL mp_timeset(routinen, handle)
18757 
18758 #if defined(__parallel)
18759  NULLIFY (data)
18760  CALL mp_alloc_mem(DATA, len, stat=ierr)
18761  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
18762  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
18763  CALL add_perf(perf_id=15, count=1)
18764 #else
18765  ALLOCATE (DATA(len), stat=ierr)
18766  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
18767  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
18768 #endif
18769  IF (PRESENT(stat)) stat = ierr
18770  CALL mp_timestop(handle)
18771  END SUBROUTINE mp_allocate_d
18772 
18773 ! **************************************************************************************************
18774 !> \brief Deallocates special parallel memory
18775 !> \param[in] DATA pointer to special memory to deallocate
18776 !> \param stat ...
18777 !> \author UB
18778 ! **************************************************************************************************
18779  SUBROUTINE mp_deallocate_d (DATA, stat)
18780  REAL(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
18781  INTEGER, INTENT(OUT), OPTIONAL :: stat
18782 
18783  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_d'
18784 
18785  INTEGER :: handle
18786 #if defined(__parallel)
18787  INTEGER :: ierr
18788 #endif
18789 
18790  CALL mp_timeset(routinen, handle)
18791 
18792 #if defined(__parallel)
18793  CALL mp_free_mem(DATA, ierr)
18794  IF (PRESENT(stat)) THEN
18795  stat = ierr
18796  ELSE
18797  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
18798  END IF
18799  NULLIFY (data)
18800  CALL add_perf(perf_id=15, count=1)
18801 #else
18802  DEALLOCATE (data)
18803  IF (PRESENT(stat)) stat = 0
18804 #endif
18805  CALL mp_timestop(handle)
18806  END SUBROUTINE mp_deallocate_d
18807 
18808 ! **************************************************************************************************
18809 !> \brief (parallel) Blocking individual file write using explicit offsets
18810 !> (serial) Unformatted stream write
18811 !> \param[in] fh file handle (file storage unit)
18812 !> \param[in] offset file offset (position)
18813 !> \param[in] msg data to be written to the file
18814 !> \param msglen ...
18815 !> \par MPI-I/O mapping mpi_file_write_at
18816 !> \par STREAM-I/O mapping WRITE
18817 !> \param[in](optional) msglen number of the elements of data
18818 ! **************************************************************************************************
18819  SUBROUTINE mp_file_write_at_dv(fh, offset, msg, msglen)
18820  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
18821  CLASS(mp_file_type), INTENT(IN) :: fh
18822  INTEGER, INTENT(IN), OPTIONAL :: msglen
18823  INTEGER(kind=file_offset), INTENT(IN) :: offset
18824 
18825  INTEGER :: msg_len
18826 #if defined(__parallel)
18827  INTEGER :: ierr
18828 #endif
18829 
18830  msg_len = SIZE(msg)
18831  IF (PRESENT(msglen)) msg_len = msglen
18832 #if defined(__parallel)
18833  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_double_precision, mpi_status_ignore, ierr)
18834  IF (ierr .NE. 0) &
18835  cpabort("mpi_file_write_at_dv @ mp_file_write_at_dv")
18836 #else
18837  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
18838 #endif
18839  END SUBROUTINE mp_file_write_at_dv
18840 
18841 ! **************************************************************************************************
18842 !> \brief ...
18843 !> \param fh ...
18844 !> \param offset ...
18845 !> \param msg ...
18846 ! **************************************************************************************************
18847  SUBROUTINE mp_file_write_at_d (fh, offset, msg)
18848  REAL(kind=real_8), INTENT(IN) :: msg
18849  CLASS(mp_file_type), INTENT(IN) :: fh
18850  INTEGER(kind=file_offset), INTENT(IN) :: offset
18851 
18852 #if defined(__parallel)
18853  INTEGER :: ierr
18854 
18855  ierr = 0
18856  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_double_precision, mpi_status_ignore, ierr)
18857  IF (ierr .NE. 0) &
18858  cpabort("mpi_file_write_at_d @ mp_file_write_at_d")
18859 #else
18860  WRITE (unit=fh%handle, pos=offset + 1) msg
18861 #endif
18862  END SUBROUTINE mp_file_write_at_d
18863 
18864 ! **************************************************************************************************
18865 !> \brief (parallel) Blocking collective file write using explicit offsets
18866 !> (serial) Unformatted stream write
18867 !> \param fh ...
18868 !> \param offset ...
18869 !> \param msg ...
18870 !> \param msglen ...
18871 !> \par MPI-I/O mapping mpi_file_write_at_all
18872 !> \par STREAM-I/O mapping WRITE
18873 ! **************************************************************************************************
18874  SUBROUTINE mp_file_write_at_all_dv(fh, offset, msg, msglen)
18875  REAL(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
18876  CLASS(mp_file_type), INTENT(IN) :: fh
18877  INTEGER, INTENT(IN), OPTIONAL :: msglen
18878  INTEGER(kind=file_offset), INTENT(IN) :: offset
18879 
18880  INTEGER :: msg_len
18881 #if defined(__parallel)
18882  INTEGER :: ierr
18883 #endif
18884 
18885  msg_len = SIZE(msg)
18886  IF (PRESENT(msglen)) msg_len = msglen
18887 #if defined(__parallel)
18888  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_double_precision, mpi_status_ignore, ierr)
18889  IF (ierr .NE. 0) &
18890  cpabort("mpi_file_write_at_all_dv @ mp_file_write_at_all_dv")
18891 #else
18892  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
18893 #endif
18894  END SUBROUTINE mp_file_write_at_all_dv
18895 
18896 ! **************************************************************************************************
18897 !> \brief ...
18898 !> \param fh ...
18899 !> \param offset ...
18900 !> \param msg ...
18901 ! **************************************************************************************************
18902  SUBROUTINE mp_file_write_at_all_d (fh, offset, msg)
18903  REAL(kind=real_8), INTENT(IN) :: msg
18904  CLASS(mp_file_type), INTENT(IN) :: fh
18905  INTEGER(kind=file_offset), INTENT(IN) :: offset
18906 
18907 #if defined(__parallel)
18908  INTEGER :: ierr
18909 
18910  ierr = 0
18911  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_double_precision, mpi_status_ignore, ierr)
18912  IF (ierr .NE. 0) &
18913  cpabort("mpi_file_write_at_all_d @ mp_file_write_at_all_d")
18914 #else
18915  WRITE (unit=fh%handle, pos=offset + 1) msg
18916 #endif
18917  END SUBROUTINE mp_file_write_at_all_d
18918 
18919 ! **************************************************************************************************
18920 !> \brief (parallel) Blocking individual file read using explicit offsets
18921 !> (serial) Unformatted stream read
18922 !> \param[in] fh file handle (file storage unit)
18923 !> \param[in] offset file offset (position)
18924 !> \param[out] msg data to be read from the file
18925 !> \param msglen ...
18926 !> \par MPI-I/O mapping mpi_file_read_at
18927 !> \par STREAM-I/O mapping READ
18928 !> \param[in](optional) msglen number of elements of data
18929 ! **************************************************************************************************
18930  SUBROUTINE mp_file_read_at_dv(fh, offset, msg, msglen)
18931  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msg(:)
18932  CLASS(mp_file_type), INTENT(IN) :: fh
18933  INTEGER, INTENT(IN), OPTIONAL :: msglen
18934  INTEGER(kind=file_offset), INTENT(IN) :: offset
18935 
18936  INTEGER :: msg_len
18937 #if defined(__parallel)
18938  INTEGER :: ierr
18939 #endif
18940 
18941  msg_len = SIZE(msg)
18942  IF (PRESENT(msglen)) msg_len = msglen
18943 #if defined(__parallel)
18944  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_double_precision, mpi_status_ignore, ierr)
18945  IF (ierr .NE. 0) &
18946  cpabort("mpi_file_read_at_dv @ mp_file_read_at_dv")
18947 #else
18948  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
18949 #endif
18950  END SUBROUTINE mp_file_read_at_dv
18951 
18952 ! **************************************************************************************************
18953 !> \brief ...
18954 !> \param fh ...
18955 !> \param offset ...
18956 !> \param msg ...
18957 ! **************************************************************************************************
18958  SUBROUTINE mp_file_read_at_d (fh, offset, msg)
18959  REAL(kind=real_8), INTENT(OUT) :: msg
18960  CLASS(mp_file_type), INTENT(IN) :: fh
18961  INTEGER(kind=file_offset), INTENT(IN) :: offset
18962 
18963 #if defined(__parallel)
18964  INTEGER :: ierr
18965 
18966  ierr = 0
18967  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_double_precision, mpi_status_ignore, ierr)
18968  IF (ierr .NE. 0) &
18969  cpabort("mpi_file_read_at_d @ mp_file_read_at_d")
18970 #else
18971  READ (unit=fh%handle, pos=offset + 1) msg
18972 #endif
18973  END SUBROUTINE mp_file_read_at_d
18974 
18975 ! **************************************************************************************************
18976 !> \brief (parallel) Blocking collective file read using explicit offsets
18977 !> (serial) Unformatted stream read
18978 !> \param fh ...
18979 !> \param offset ...
18980 !> \param msg ...
18981 !> \param msglen ...
18982 !> \par MPI-I/O mapping mpi_file_read_at_all
18983 !> \par STREAM-I/O mapping READ
18984 ! **************************************************************************************************
18985  SUBROUTINE mp_file_read_at_all_dv(fh, offset, msg, msglen)
18986  REAL(kind=real_8), INTENT(OUT), CONTIGUOUS :: msg(:)
18987  CLASS(mp_file_type), INTENT(IN) :: fh
18988  INTEGER, INTENT(IN), OPTIONAL :: msglen
18989  INTEGER(kind=file_offset), INTENT(IN) :: offset
18990 
18991  INTEGER :: msg_len
18992 #if defined(__parallel)
18993  INTEGER :: ierr
18994 #endif
18995 
18996  msg_len = SIZE(msg)
18997  IF (PRESENT(msglen)) msg_len = msglen
18998 #if defined(__parallel)
18999  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_double_precision, mpi_status_ignore, ierr)
19000  IF (ierr .NE. 0) &
19001  cpabort("mpi_file_read_at_all_dv @ mp_file_read_at_all_dv")
19002 #else
19003  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
19004 #endif
19005  END SUBROUTINE mp_file_read_at_all_dv
19006 
19007 ! **************************************************************************************************
19008 !> \brief ...
19009 !> \param fh ...
19010 !> \param offset ...
19011 !> \param msg ...
19012 ! **************************************************************************************************
19013  SUBROUTINE mp_file_read_at_all_d (fh, offset, msg)
19014  REAL(kind=real_8), INTENT(OUT) :: msg
19015  CLASS(mp_file_type), INTENT(IN) :: fh
19016  INTEGER(kind=file_offset), INTENT(IN) :: offset
19017 
19018 #if defined(__parallel)
19019  INTEGER :: ierr
19020 
19021  ierr = 0
19022  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_double_precision, mpi_status_ignore, ierr)
19023  IF (ierr .NE. 0) &
19024  cpabort("mpi_file_read_at_all_d @ mp_file_read_at_all_d")
19025 #else
19026  READ (unit=fh%handle, pos=offset + 1) msg
19027 #endif
19028  END SUBROUTINE mp_file_read_at_all_d
19029 
19030 ! **************************************************************************************************
19031 !> \brief ...
19032 !> \param ptr ...
19033 !> \param vector_descriptor ...
19034 !> \param index_descriptor ...
19035 !> \return ...
19036 ! **************************************************************************************************
19037  FUNCTION mp_type_make_d (ptr, &
19038  vector_descriptor, index_descriptor) &
19039  result(type_descriptor)
19040  REAL(kind=real_8), DIMENSION(:), TARGET, asynchronous :: ptr
19041  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
19042  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
19043  TYPE(mp_type_descriptor_type) :: type_descriptor
19044 
19045  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_d'
19046 
19047 #if defined(__parallel)
19048  INTEGER :: ierr
19049 #endif
19050 
19051  NULLIFY (type_descriptor%subtype)
19052  type_descriptor%length = SIZE(ptr)
19053 #if defined(__parallel)
19054  type_descriptor%type_handle = mpi_double_precision
19055  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
19056  IF (ierr /= 0) &
19057  cpabort("MPI_Get_address @ "//routinen)
19058 #else
19059  type_descriptor%type_handle = 3
19060 #endif
19061  type_descriptor%vector_descriptor(1:2) = 1
19062  type_descriptor%has_indexing = .false.
19063  type_descriptor%data_d => ptr
19064  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
19065  cpabort(routinen//": Vectors and indices NYI")
19066  END IF
19067  END FUNCTION mp_type_make_d
19068 
19069 ! **************************************************************************************************
19070 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
19071 !> as the Fortran version returns an integer, which we take to be a C_PTR
19072 !> \param DATA data array to allocate
19073 !> \param[in] len length (in data elements) of data array allocation
19074 !> \param[out] stat (optional) allocation status result
19075 ! **************************************************************************************************
19076  SUBROUTINE mp_alloc_mem_d (DATA, len, stat)
19077  REAL(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
19078  INTEGER, INTENT(IN) :: len
19079  INTEGER, INTENT(OUT), OPTIONAL :: stat
19080 
19081 #if defined(__parallel)
19082  INTEGER :: size, ierr, length, &
19083  mp_res
19084  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
19085  TYPE(c_ptr) :: mp_baseptr
19086  mpi_info_type :: mp_info
19087 
19088  length = max(len, 1)
19089  CALL mpi_type_size(mpi_double_precision, size, ierr)
19090  mp_size = int(length, kind=mpi_address_kind)*size
19091  IF (mp_size .GT. mp_max_memory_size) THEN
19092  cpabort("MPI cannot allocate more than 2 GiByte")
19093  END IF
19094  mp_info = mpi_info_null
19095  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
19096  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
19097  IF (PRESENT(stat)) stat = mp_res
19098 #else
19099  INTEGER :: length, mystat
19100  length = max(len, 1)
19101  IF (PRESENT(stat)) THEN
19102  ALLOCATE (DATA(length), stat=mystat)
19103  stat = mystat ! show to convention checker that stat is used
19104  ELSE
19105  ALLOCATE (DATA(length))
19106  END IF
19107 #endif
19108  END SUBROUTINE mp_alloc_mem_d
19109 
19110 ! **************************************************************************************************
19111 !> \brief Deallocates am array, ... this is hackish
19112 !> as the Fortran version takes an integer, which we hope to get by reference
19113 !> \param DATA data array to allocate
19114 !> \param[out] stat (optional) allocation status result
19115 ! **************************************************************************************************
19116  SUBROUTINE mp_free_mem_d (DATA, stat)
19117  REAL(kind=real_8), DIMENSION(:), &
19118  POINTER, asynchronous :: DATA
19119  INTEGER, INTENT(OUT), OPTIONAL :: stat
19120 
19121 #if defined(__parallel)
19122  INTEGER :: mp_res
19123  CALL mpi_free_mem(DATA, mp_res)
19124  IF (PRESENT(stat)) stat = mp_res
19125 #else
19126  DEALLOCATE (data)
19127  IF (PRESENT(stat)) stat = 0
19128 #endif
19129  END SUBROUTINE mp_free_mem_d
19130 ! **************************************************************************************************
19131 !> \brief Shift around the data in msg
19132 !> \param[in,out] msg Rank-2 data to shift
19133 !> \param[in] comm message passing environment identifier
19134 !> \param[in] displ_in displacements (?)
19135 !> \par Example
19136 !> msg will be moved from rank to rank+displ_in (in a circular way)
19137 !> \par Limitations
19138 !> * displ_in will be 1 by default (others not tested)
19139 !> * the message array needs to be the same size on all processes
19140 ! **************************************************************************************************
19141  SUBROUTINE mp_shift_rm(msg, comm, displ_in)
19142 
19143  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
19144  CLASS(mp_comm_type), INTENT(IN) :: comm
19145  INTEGER, INTENT(IN), OPTIONAL :: displ_in
19146 
19147  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_rm'
19148 
19149  INTEGER :: handle, ierror
19150 #if defined(__parallel)
19151  INTEGER :: displ, left, &
19152  msglen, myrank, nprocs, &
19153  right, tag
19154 #endif
19155 
19156  ierror = 0
19157  CALL mp_timeset(routinen, handle)
19158 
19159 #if defined(__parallel)
19160  CALL mpi_comm_rank(comm%handle, myrank, ierror)
19161  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
19162  CALL mpi_comm_size(comm%handle, nprocs, ierror)
19163  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
19164  IF (PRESENT(displ_in)) THEN
19165  displ = displ_in
19166  ELSE
19167  displ = 1
19168  END IF
19169  right = modulo(myrank + displ, nprocs)
19170  left = modulo(myrank - displ, nprocs)
19171  tag = 17
19172  msglen = SIZE(msg)
19173  CALL mpi_sendrecv_replace(msg, msglen, mpi_real, right, tag, left, tag, &
19174  comm%handle, mpi_status_ignore, ierror)
19175  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
19176  CALL add_perf(perf_id=7, count=1, msg_size=msglen*real_4_size)
19177 #else
19178  mark_used(msg)
19179  mark_used(comm)
19180  mark_used(displ_in)
19181 #endif
19182  CALL mp_timestop(handle)
19183 
19184  END SUBROUTINE mp_shift_rm
19185 
19186 ! **************************************************************************************************
19187 !> \brief Shift around the data in msg
19188 !> \param[in,out] msg Data to shift
19189 !> \param[in] comm message passing environment identifier
19190 !> \param[in] displ_in displacements (?)
19191 !> \par Example
19192 !> msg will be moved from rank to rank+displ_in (in a circular way)
19193 !> \par Limitations
19194 !> * displ_in will be 1 by default (others not tested)
19195 !> * the message array needs to be the same size on all processes
19196 ! **************************************************************************************************
19197  SUBROUTINE mp_shift_r (msg, comm, displ_in)
19198 
19199  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
19200  CLASS(mp_comm_type), INTENT(IN) :: comm
19201  INTEGER, INTENT(IN), OPTIONAL :: displ_in
19202 
19203  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_r'
19204 
19205  INTEGER :: handle, ierror
19206 #if defined(__parallel)
19207  INTEGER :: displ, left, &
19208  msglen, myrank, nprocs, &
19209  right, tag
19210 #endif
19211 
19212  ierror = 0
19213  CALL mp_timeset(routinen, handle)
19214 
19215 #if defined(__parallel)
19216  CALL mpi_comm_rank(comm%handle, myrank, ierror)
19217  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
19218  CALL mpi_comm_size(comm%handle, nprocs, ierror)
19219  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
19220  IF (PRESENT(displ_in)) THEN
19221  displ = displ_in
19222  ELSE
19223  displ = 1
19224  END IF
19225  right = modulo(myrank + displ, nprocs)
19226  left = modulo(myrank - displ, nprocs)
19227  tag = 19
19228  msglen = SIZE(msg)
19229  CALL mpi_sendrecv_replace(msg, msglen, mpi_real, right, tag, left, &
19230  tag, comm%handle, mpi_status_ignore, ierror)
19231  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
19232  CALL add_perf(perf_id=7, count=1, msg_size=msglen*real_4_size)
19233 #else
19234  mark_used(msg)
19235  mark_used(comm)
19236  mark_used(displ_in)
19237 #endif
19238  CALL mp_timestop(handle)
19239 
19240  END SUBROUTINE mp_shift_r
19241 
19242 ! **************************************************************************************************
19243 !> \brief All-to-all data exchange, rank-1 data of different sizes
19244 !> \param[in] sb Data to send
19245 !> \param[in] scount Data counts for data sent to other processes
19246 !> \param[in] sdispl Respective data offsets for data sent to process
19247 !> \param[in,out] rb Buffer into which to receive data
19248 !> \param[in] rcount Data counts for data received from other
19249 !> processes
19250 !> \param[in] rdispl Respective data offsets for data received from
19251 !> other processes
19252 !> \param[in] comm Message passing environment identifier
19253 !> \par MPI mapping
19254 !> mpi_alltoallv
19255 !> \par Array sizes
19256 !> The scount, rcount, and the sdispl and rdispl arrays have a
19257 !> size equal to the number of processes.
19258 !> \par Offsets
19259 !> Values in sdispl and rdispl start with 0.
19260 ! **************************************************************************************************
19261  SUBROUTINE mp_alltoall_r11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
19262 
19263  REAL(kind=real_4), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
19264  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
19265  REAL(kind=real_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
19266  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
19267  CLASS(mp_comm_type), INTENT(IN) :: comm
19268 
19269  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r11v'
19270 
19271  INTEGER :: handle
19272 #if defined(__parallel)
19273  INTEGER :: ierr, msglen
19274 #else
19275  INTEGER :: i
19276 #endif
19277 
19278  CALL mp_timeset(routinen, handle)
19279 
19280 #if defined(__parallel)
19281  CALL mpi_alltoallv(sb, scount, sdispl, mpi_real, &
19282  rb, rcount, rdispl, mpi_real, comm%handle, ierr)
19283  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
19284  msglen = sum(scount) + sum(rcount)
19285  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19286 #else
19287  mark_used(comm)
19288  mark_used(scount)
19289  mark_used(sdispl)
19290  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
19291  DO i = 1, rcount(1)
19292  rb(rdispl(1) + i) = sb(sdispl(1) + i)
19293  END DO
19294 #endif
19295  CALL mp_timestop(handle)
19296 
19297  END SUBROUTINE mp_alltoall_r11v
19298 
19299 ! **************************************************************************************************
19300 !> \brief All-to-all data exchange, rank-2 data of different sizes
19301 !> \param sb ...
19302 !> \param scount ...
19303 !> \param sdispl ...
19304 !> \param rb ...
19305 !> \param rcount ...
19306 !> \param rdispl ...
19307 !> \param comm ...
19308 !> \par MPI mapping
19309 !> mpi_alltoallv
19310 !> \note see mp_alltoall_r11v
19311 ! **************************************************************************************************
19312  SUBROUTINE mp_alltoall_r22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
19313 
19314  REAL(kind=real_4), DIMENSION(:, :), &
19315  INTENT(IN), CONTIGUOUS :: sb
19316  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
19317  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, &
19318  INTENT(INOUT) :: rb
19319  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
19320  CLASS(mp_comm_type), INTENT(IN) :: comm
19321 
19322  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r22v'
19323 
19324  INTEGER :: handle
19325 #if defined(__parallel)
19326  INTEGER :: ierr, msglen
19327 #endif
19328 
19329  CALL mp_timeset(routinen, handle)
19330 
19331 #if defined(__parallel)
19332  CALL mpi_alltoallv(sb, scount, sdispl, mpi_real, &
19333  rb, rcount, rdispl, mpi_real, comm%handle, ierr)
19334  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
19335  msglen = sum(scount) + sum(rcount)
19336  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*real_4_size)
19337 #else
19338  mark_used(comm)
19339  mark_used(scount)
19340  mark_used(sdispl)
19341  mark_used(rcount)
19342  mark_used(rdispl)
19343  rb = sb
19344 #endif
19345  CALL mp_timestop(handle)
19346 
19347  END SUBROUTINE mp_alltoall_r22v
19348 
19349 ! **************************************************************************************************
19350 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
19351 !> \param[in] sb array with data to send
19352 !> \param[out] rb array into which data is received
19353 !> \param[in] count number of elements to send/receive (product of the
19354 !> extents of the first two dimensions)
19355 !> \param[in] comm Message passing environment identifier
19356 !> \par Index meaning
19357 !> \par The first two indices specify the data while the last index counts
19358 !> the processes
19359 !> \par Sizes of ranks
19360 !> All processes have the same data size.
19361 !> \par MPI mapping
19362 !> mpi_alltoall
19363 ! **************************************************************************************************
19364  SUBROUTINE mp_alltoall_r (sb, rb, count, comm)
19365 
19366  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
19367  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
19368  INTEGER, INTENT(IN) :: count
19369  CLASS(mp_comm_type), INTENT(IN) :: comm
19370 
19371  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r'
19372 
19373  INTEGER :: handle
19374 #if defined(__parallel)
19375  INTEGER :: ierr, msglen, np
19376 #endif
19377 
19378  CALL mp_timeset(routinen, handle)
19379 
19380 #if defined(__parallel)
19381  CALL mpi_alltoall(sb, count, mpi_real, &
19382  rb, count, mpi_real, comm%handle, ierr)
19383  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19384  CALL mpi_comm_size(comm%handle, np, ierr)
19385  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19386  msglen = 2*count*np
19387  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19388 #else
19389  mark_used(count)
19390  mark_used(comm)
19391  rb = sb
19392 #endif
19393  CALL mp_timestop(handle)
19394 
19395  END SUBROUTINE mp_alltoall_r
19396 
19397 ! **************************************************************************************************
19398 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
19399 !> \param sb ...
19400 !> \param rb ...
19401 !> \param count ...
19402 !> \param commp ...
19403 !> \note see mp_alltoall_r
19404 ! **************************************************************************************************
19405  SUBROUTINE mp_alltoall_r22(sb, rb, count, comm)
19406 
19407  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
19408  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
19409  INTEGER, INTENT(IN) :: count
19410  CLASS(mp_comm_type), INTENT(IN) :: comm
19411 
19412  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r22'
19413 
19414  INTEGER :: handle
19415 #if defined(__parallel)
19416  INTEGER :: ierr, msglen, np
19417 #endif
19418 
19419  CALL mp_timeset(routinen, handle)
19420 
19421 #if defined(__parallel)
19422  CALL mpi_alltoall(sb, count, mpi_real, &
19423  rb, count, mpi_real, comm%handle, ierr)
19424  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19425  CALL mpi_comm_size(comm%handle, np, ierr)
19426  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19427  msglen = 2*SIZE(sb)*np
19428  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19429 #else
19430  mark_used(count)
19431  mark_used(comm)
19432  rb = sb
19433 #endif
19434  CALL mp_timestop(handle)
19435 
19436  END SUBROUTINE mp_alltoall_r22
19437 
19438 ! **************************************************************************************************
19439 !> \brief All-to-all data exchange, rank-3 data with equal sizes
19440 !> \param sb ...
19441 !> \param rb ...
19442 !> \param count ...
19443 !> \param comm ...
19444 !> \note see mp_alltoall_r
19445 ! **************************************************************************************************
19446  SUBROUTINE mp_alltoall_r33(sb, rb, count, comm)
19447 
19448  REAL(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
19449  REAL(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
19450  INTEGER, INTENT(IN) :: count
19451  CLASS(mp_comm_type), INTENT(IN) :: comm
19452 
19453  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r33'
19454 
19455  INTEGER :: handle
19456 #if defined(__parallel)
19457  INTEGER :: ierr, msglen, np
19458 #endif
19459 
19460  CALL mp_timeset(routinen, handle)
19461 
19462 #if defined(__parallel)
19463  CALL mpi_alltoall(sb, count, mpi_real, &
19464  rb, count, mpi_real, comm%handle, ierr)
19465  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19466  CALL mpi_comm_size(comm%handle, np, ierr)
19467  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19468  msglen = 2*count*np
19469  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19470 #else
19471  mark_used(count)
19472  mark_used(comm)
19473  rb = sb
19474 #endif
19475  CALL mp_timestop(handle)
19476 
19477  END SUBROUTINE mp_alltoall_r33
19478 
19479 ! **************************************************************************************************
19480 !> \brief All-to-all data exchange, rank 4 data, equal sizes
19481 !> \param sb ...
19482 !> \param rb ...
19483 !> \param count ...
19484 !> \param comm ...
19485 !> \note see mp_alltoall_r
19486 ! **************************************************************************************************
19487  SUBROUTINE mp_alltoall_r44(sb, rb, count, comm)
19488 
19489  REAL(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
19490  INTENT(IN) :: sb
19491  REAL(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
19492  INTENT(OUT) :: rb
19493  INTEGER, INTENT(IN) :: count
19494  CLASS(mp_comm_type), INTENT(IN) :: comm
19495 
19496  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r44'
19497 
19498  INTEGER :: handle
19499 #if defined(__parallel)
19500  INTEGER :: ierr, msglen, np
19501 #endif
19502 
19503  CALL mp_timeset(routinen, handle)
19504 
19505 #if defined(__parallel)
19506  CALL mpi_alltoall(sb, count, mpi_real, &
19507  rb, count, mpi_real, comm%handle, ierr)
19508  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19509  CALL mpi_comm_size(comm%handle, np, ierr)
19510  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19511  msglen = 2*count*np
19512  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19513 #else
19514  mark_used(count)
19515  mark_used(comm)
19516  rb = sb
19517 #endif
19518  CALL mp_timestop(handle)
19519 
19520  END SUBROUTINE mp_alltoall_r44
19521 
19522 ! **************************************************************************************************
19523 !> \brief All-to-all data exchange, rank 5 data, equal sizes
19524 !> \param sb ...
19525 !> \param rb ...
19526 !> \param count ...
19527 !> \param comm ...
19528 !> \note see mp_alltoall_r
19529 ! **************************************************************************************************
19530  SUBROUTINE mp_alltoall_r55(sb, rb, count, comm)
19531 
19532  REAL(kind=real_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
19533  INTENT(IN) :: sb
19534  REAL(kind=real_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
19535  INTENT(OUT) :: rb
19536  INTEGER, INTENT(IN) :: count
19537  CLASS(mp_comm_type), INTENT(IN) :: comm
19538 
19539  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r55'
19540 
19541  INTEGER :: handle
19542 #if defined(__parallel)
19543  INTEGER :: ierr, msglen, np
19544 #endif
19545 
19546  CALL mp_timeset(routinen, handle)
19547 
19548 #if defined(__parallel)
19549  CALL mpi_alltoall(sb, count, mpi_real, &
19550  rb, count, mpi_real, comm%handle, ierr)
19551  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19552  CALL mpi_comm_size(comm%handle, np, ierr)
19553  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19554  msglen = 2*count*np
19555  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19556 #else
19557  mark_used(count)
19558  mark_used(comm)
19559  rb = sb
19560 #endif
19561  CALL mp_timestop(handle)
19562 
19563  END SUBROUTINE mp_alltoall_r55
19564 
19565 ! **************************************************************************************************
19566 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
19567 !> \param sb ...
19568 !> \param rb ...
19569 !> \param count ...
19570 !> \param comm ...
19571 !> \note see mp_alltoall_r
19572 !> \note User must ensure size consistency.
19573 ! **************************************************************************************************
19574  SUBROUTINE mp_alltoall_r45(sb, rb, count, comm)
19575 
19576  REAL(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
19577  INTENT(IN) :: sb
19578  REAL(kind=real_4), &
19579  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
19580  INTEGER, INTENT(IN) :: count
19581  CLASS(mp_comm_type), INTENT(IN) :: comm
19582 
19583  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r45'
19584 
19585  INTEGER :: handle
19586 #if defined(__parallel)
19587  INTEGER :: ierr, msglen, np
19588 #endif
19589 
19590  CALL mp_timeset(routinen, handle)
19591 
19592 #if defined(__parallel)
19593  CALL mpi_alltoall(sb, count, mpi_real, &
19594  rb, count, mpi_real, comm%handle, ierr)
19595  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19596  CALL mpi_comm_size(comm%handle, np, ierr)
19597  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19598  msglen = 2*count*np
19599  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19600 #else
19601  mark_used(count)
19602  mark_used(comm)
19603  rb = reshape(sb, shape(rb))
19604 #endif
19605  CALL mp_timestop(handle)
19606 
19607  END SUBROUTINE mp_alltoall_r45
19608 
19609 ! **************************************************************************************************
19610 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
19611 !> \param sb ...
19612 !> \param rb ...
19613 !> \param count ...
19614 !> \param comm ...
19615 !> \note see mp_alltoall_r
19616 !> \note User must ensure size consistency.
19617 ! **************************************************************************************************
19618  SUBROUTINE mp_alltoall_r34(sb, rb, count, comm)
19619 
19620  REAL(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, &
19621  INTENT(IN) :: sb
19622  REAL(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
19623  INTENT(OUT) :: rb
19624  INTEGER, INTENT(IN) :: count
19625  CLASS(mp_comm_type), INTENT(IN) :: comm
19626 
19627  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r34'
19628 
19629  INTEGER :: handle
19630 #if defined(__parallel)
19631  INTEGER :: ierr, msglen, np
19632 #endif
19633 
19634  CALL mp_timeset(routinen, handle)
19635 
19636 #if defined(__parallel)
19637  CALL mpi_alltoall(sb, count, mpi_real, &
19638  rb, count, mpi_real, comm%handle, ierr)
19639  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19640  CALL mpi_comm_size(comm%handle, np, ierr)
19641  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19642  msglen = 2*count*np
19643  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19644 #else
19645  mark_used(count)
19646  mark_used(comm)
19647  rb = reshape(sb, shape(rb))
19648 #endif
19649  CALL mp_timestop(handle)
19650 
19651  END SUBROUTINE mp_alltoall_r34
19652 
19653 ! **************************************************************************************************
19654 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
19655 !> \param sb ...
19656 !> \param rb ...
19657 !> \param count ...
19658 !> \param comm ...
19659 !> \note see mp_alltoall_r
19660 !> \note User must ensure size consistency.
19661 ! **************************************************************************************************
19662  SUBROUTINE mp_alltoall_r54(sb, rb, count, comm)
19663 
19664  REAL(kind=real_4), &
19665  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
19666  REAL(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
19667  INTENT(OUT) :: rb
19668  INTEGER, INTENT(IN) :: count
19669  CLASS(mp_comm_type), INTENT(IN) :: comm
19670 
19671  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_r54'
19672 
19673  INTEGER :: handle
19674 #if defined(__parallel)
19675  INTEGER :: ierr, msglen, np
19676 #endif
19677 
19678  CALL mp_timeset(routinen, handle)
19679 
19680 #if defined(__parallel)
19681  CALL mpi_alltoall(sb, count, mpi_real, &
19682  rb, count, mpi_real, comm%handle, ierr)
19683  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
19684  CALL mpi_comm_size(comm%handle, np, ierr)
19685  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
19686  msglen = 2*count*np
19687  CALL add_perf(perf_id=6, count=1, msg_size=msglen*real_4_size)
19688 #else
19689  mark_used(count)
19690  mark_used(comm)
19691  rb = reshape(sb, shape(rb))
19692 #endif
19693  CALL mp_timestop(handle)
19694 
19695  END SUBROUTINE mp_alltoall_r54
19696 
19697 ! **************************************************************************************************
19698 !> \brief Send one datum to another process
19699 !> \param[in] msg Scalar to send
19700 !> \param[in] dest Destination process
19701 !> \param[in] tag Transfer identifier
19702 !> \param[in] comm Message passing environment identifier
19703 !> \par MPI mapping
19704 !> mpi_send
19705 ! **************************************************************************************************
19706  SUBROUTINE mp_send_r (msg, dest, tag, comm)
19707  REAL(kind=real_4), INTENT(IN) :: msg
19708  INTEGER, INTENT(IN) :: dest, tag
19709  CLASS(mp_comm_type), INTENT(IN) :: comm
19710 
19711  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_r'
19712 
19713  INTEGER :: handle
19714 #if defined(__parallel)
19715  INTEGER :: ierr, msglen
19716 #endif
19717 
19718  CALL mp_timeset(routinen, handle)
19719 
19720 #if defined(__parallel)
19721  msglen = 1
19722  CALL mpi_send(msg, msglen, mpi_real, dest, tag, comm%handle, ierr)
19723  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
19724  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_4_size)
19725 #else
19726  mark_used(msg)
19727  mark_used(dest)
19728  mark_used(tag)
19729  mark_used(comm)
19730  ! only defined in parallel
19731  cpabort("not in parallel mode")
19732 #endif
19733  CALL mp_timestop(handle)
19734  END SUBROUTINE mp_send_r
19735 
19736 ! **************************************************************************************************
19737 !> \brief Send rank-1 data to another process
19738 !> \param[in] msg Rank-1 data to send
19739 !> \param dest ...
19740 !> \param tag ...
19741 !> \param comm ...
19742 !> \note see mp_send_r
19743 ! **************************************************************************************************
19744  SUBROUTINE mp_send_rv(msg, dest, tag, comm)
19745  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
19746  INTEGER, INTENT(IN) :: dest, tag
19747  CLASS(mp_comm_type), INTENT(IN) :: comm
19748 
19749  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_rv'
19750 
19751  INTEGER :: handle
19752 #if defined(__parallel)
19753  INTEGER :: ierr, msglen
19754 #endif
19755 
19756  CALL mp_timeset(routinen, handle)
19757 
19758 #if defined(__parallel)
19759  msglen = SIZE(msg)
19760  CALL mpi_send(msg, msglen, mpi_real, dest, tag, comm%handle, ierr)
19761  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
19762  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_4_size)
19763 #else
19764  mark_used(msg)
19765  mark_used(dest)
19766  mark_used(tag)
19767  mark_used(comm)
19768  ! only defined in parallel
19769  cpabort("not in parallel mode")
19770 #endif
19771  CALL mp_timestop(handle)
19772  END SUBROUTINE mp_send_rv
19773 
19774 ! **************************************************************************************************
19775 !> \brief Send rank-2 data to another process
19776 !> \param[in] msg Rank-2 data to send
19777 !> \param dest ...
19778 !> \param tag ...
19779 !> \param comm ...
19780 !> \note see mp_send_r
19781 ! **************************************************************************************************
19782  SUBROUTINE mp_send_rm2(msg, dest, tag, comm)
19783  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
19784  INTEGER, INTENT(IN) :: dest, tag
19785  CLASS(mp_comm_type), INTENT(IN) :: comm
19786 
19787  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_rm2'
19788 
19789  INTEGER :: handle
19790 #if defined(__parallel)
19791  INTEGER :: ierr, msglen
19792 #endif
19793 
19794  CALL mp_timeset(routinen, handle)
19795 
19796 #if defined(__parallel)
19797  msglen = SIZE(msg)
19798  CALL mpi_send(msg, msglen, mpi_real, dest, tag, comm%handle, ierr)
19799  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
19800  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_4_size)
19801 #else
19802  mark_used(msg)
19803  mark_used(dest)
19804  mark_used(tag)
19805  mark_used(comm)
19806  ! only defined in parallel
19807  cpabort("not in parallel mode")
19808 #endif
19809  CALL mp_timestop(handle)
19810  END SUBROUTINE mp_send_rm2
19811 
19812 ! **************************************************************************************************
19813 !> \brief Send rank-3 data to another process
19814 !> \param[in] msg Rank-3 data to send
19815 !> \param dest ...
19816 !> \param tag ...
19817 !> \param comm ...
19818 !> \note see mp_send_r
19819 ! **************************************************************************************************
19820  SUBROUTINE mp_send_rm3(msg, dest, tag, comm)
19821  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
19822  INTEGER, INTENT(IN) :: dest, tag
19823  CLASS(mp_comm_type), INTENT(IN) :: comm
19824 
19825  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
19826 
19827  INTEGER :: handle
19828 #if defined(__parallel)
19829  INTEGER :: ierr, msglen
19830 #endif
19831 
19832  CALL mp_timeset(routinen, handle)
19833 
19834 #if defined(__parallel)
19835  msglen = SIZE(msg)
19836  CALL mpi_send(msg, msglen, mpi_real, dest, tag, comm%handle, ierr)
19837  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
19838  CALL add_perf(perf_id=13, count=1, msg_size=msglen*real_4_size)
19839 #else
19840  mark_used(msg)
19841  mark_used(dest)
19842  mark_used(tag)
19843  mark_used(comm)
19844  ! only defined in parallel
19845  cpabort("not in parallel mode")
19846 #endif
19847  CALL mp_timestop(handle)
19848  END SUBROUTINE mp_send_rm3
19849 
19850 ! **************************************************************************************************
19851 !> \brief Receive one datum from another process
19852 !> \param[in,out] msg Place received data into this variable
19853 !> \param[in,out] source Process to receive from
19854 !> \param[in,out] tag Transfer identifier
19855 !> \param[in] comm Message passing environment identifier
19856 !> \par MPI mapping
19857 !> mpi_send
19858 ! **************************************************************************************************
19859  SUBROUTINE mp_recv_r (msg, source, tag, comm)
19860  REAL(kind=real_4), INTENT(INOUT) :: msg
19861  INTEGER, INTENT(INOUT) :: source, tag
19862  CLASS(mp_comm_type), INTENT(IN) :: comm
19863 
19864  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_r'
19865 
19866  INTEGER :: handle
19867 #if defined(__parallel)
19868  INTEGER :: ierr, msglen
19869  mpi_status_type :: status
19870 #endif
19871 
19872  CALL mp_timeset(routinen, handle)
19873 
19874 #if defined(__parallel)
19875  msglen = 1
19876  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
19877  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, mpi_status_ignore, ierr)
19878  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19879  ELSE
19880  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, status, ierr)
19881  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19882  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_4_size)
19883  source = status mpi_status_extract(mpi_source)
19884  tag = status mpi_status_extract(mpi_tag)
19885  END IF
19886 #else
19887  mark_used(msg)
19888  mark_used(source)
19889  mark_used(tag)
19890  mark_used(comm)
19891  ! only defined in parallel
19892  cpabort("not in parallel mode")
19893 #endif
19894  CALL mp_timestop(handle)
19895  END SUBROUTINE mp_recv_r
19896 
19897 ! **************************************************************************************************
19898 !> \brief Receive rank-1 data from another process
19899 !> \param[in,out] msg Place received data into this rank-1 array
19900 !> \param source ...
19901 !> \param tag ...
19902 !> \param comm ...
19903 !> \note see mp_recv_r
19904 ! **************************************************************************************************
19905  SUBROUTINE mp_recv_rv(msg, source, tag, comm)
19906  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
19907  INTEGER, INTENT(INOUT) :: source, tag
19908  CLASS(mp_comm_type), INTENT(IN) :: comm
19909 
19910  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_rv'
19911 
19912  INTEGER :: handle
19913 #if defined(__parallel)
19914  INTEGER :: ierr, msglen
19915  mpi_status_type :: status
19916 #endif
19917 
19918  CALL mp_timeset(routinen, handle)
19919 
19920 #if defined(__parallel)
19921  msglen = SIZE(msg)
19922  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
19923  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, mpi_status_ignore, ierr)
19924  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19925  ELSE
19926  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, status, ierr)
19927  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19928  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_4_size)
19929  source = status mpi_status_extract(mpi_source)
19930  tag = status mpi_status_extract(mpi_tag)
19931  END IF
19932 #else
19933  mark_used(msg)
19934  mark_used(source)
19935  mark_used(tag)
19936  mark_used(comm)
19937  ! only defined in parallel
19938  cpabort("not in parallel mode")
19939 #endif
19940  CALL mp_timestop(handle)
19941  END SUBROUTINE mp_recv_rv
19942 
19943 ! **************************************************************************************************
19944 !> \brief Receive rank-2 data from another process
19945 !> \param[in,out] msg Place received data into this rank-2 array
19946 !> \param source ...
19947 !> \param tag ...
19948 !> \param comm ...
19949 !> \note see mp_recv_r
19950 ! **************************************************************************************************
19951  SUBROUTINE mp_recv_rm2(msg, source, tag, comm)
19952  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
19953  INTEGER, INTENT(INOUT) :: source, tag
19954  CLASS(mp_comm_type), INTENT(IN) :: comm
19955 
19956  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_rm2'
19957 
19958  INTEGER :: handle
19959 #if defined(__parallel)
19960  INTEGER :: ierr, msglen
19961  mpi_status_type :: status
19962 #endif
19963 
19964  CALL mp_timeset(routinen, handle)
19965 
19966 #if defined(__parallel)
19967  msglen = SIZE(msg)
19968  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
19969  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, mpi_status_ignore, ierr)
19970  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19971  ELSE
19972  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, status, ierr)
19973  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
19974  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_4_size)
19975  source = status mpi_status_extract(mpi_source)
19976  tag = status mpi_status_extract(mpi_tag)
19977  END IF
19978 #else
19979  mark_used(msg)
19980  mark_used(source)
19981  mark_used(tag)
19982  mark_used(comm)
19983  ! only defined in parallel
19984  cpabort("not in parallel mode")
19985 #endif
19986  CALL mp_timestop(handle)
19987  END SUBROUTINE mp_recv_rm2
19988 
19989 ! **************************************************************************************************
19990 !> \brief Receive rank-3 data from another process
19991 !> \param[in,out] msg Place received data into this rank-3 array
19992 !> \param source ...
19993 !> \param tag ...
19994 !> \param comm ...
19995 !> \note see mp_recv_r
19996 ! **************************************************************************************************
19997  SUBROUTINE mp_recv_rm3(msg, source, tag, comm)
19998  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
19999  INTEGER, INTENT(INOUT) :: source, tag
20000  CLASS(mp_comm_type), INTENT(IN) :: comm
20001 
20002  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_rm3'
20003 
20004  INTEGER :: handle
20005 #if defined(__parallel)
20006  INTEGER :: ierr, msglen
20007  mpi_status_type :: status
20008 #endif
20009 
20010  CALL mp_timeset(routinen, handle)
20011 
20012 #if defined(__parallel)
20013  msglen = SIZE(msg)
20014  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
20015  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, mpi_status_ignore, ierr)
20016  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
20017  ELSE
20018  CALL mpi_recv(msg, msglen, mpi_real, source, tag, comm%handle, status, ierr)
20019  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
20020  CALL add_perf(perf_id=14, count=1, msg_size=msglen*real_4_size)
20021  source = status mpi_status_extract(mpi_source)
20022  tag = status mpi_status_extract(mpi_tag)
20023  END IF
20024 #else
20025  mark_used(msg)
20026  mark_used(source)
20027  mark_used(tag)
20028  mark_used(comm)
20029  ! only defined in parallel
20030  cpabort("not in parallel mode")
20031 #endif
20032  CALL mp_timestop(handle)
20033  END SUBROUTINE mp_recv_rm3
20034 
20035 ! **************************************************************************************************
20036 !> \brief Broadcasts a datum to all processes.
20037 !> \param[in] msg Datum to broadcast
20038 !> \param[in] source Processes which broadcasts
20039 !> \param[in] comm Message passing environment identifier
20040 !> \par MPI mapping
20041 !> mpi_bcast
20042 ! **************************************************************************************************
20043  SUBROUTINE mp_bcast_r (msg, source, comm)
20044  REAL(kind=real_4), INTENT(INOUT) :: msg
20045  INTEGER, INTENT(IN) :: source
20046  CLASS(mp_comm_type), INTENT(IN) :: comm
20047 
20048  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_r'
20049 
20050  INTEGER :: handle
20051 #if defined(__parallel)
20052  INTEGER :: ierr, msglen
20053 #endif
20054 
20055  CALL mp_timeset(routinen, handle)
20056 
20057 #if defined(__parallel)
20058  msglen = 1
20059  CALL mpi_bcast(msg, msglen, mpi_real, source, comm%handle, ierr)
20060  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20061  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20062 #else
20063  mark_used(msg)
20064  mark_used(source)
20065  mark_used(comm)
20066 #endif
20067  CALL mp_timestop(handle)
20068  END SUBROUTINE mp_bcast_r
20069 
20070 ! **************************************************************************************************
20071 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
20072 !> \param[in] msg Datum to broadcast
20073 !> \param[in] comm Message passing environment identifier
20074 !> \par MPI mapping
20075 !> mpi_bcast
20076 ! **************************************************************************************************
20077  SUBROUTINE mp_bcast_r_src(msg, comm)
20078  REAL(kind=real_4), INTENT(INOUT) :: msg
20079  CLASS(mp_comm_type), INTENT(IN) :: comm
20080 
20081  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_r_src'
20082 
20083  INTEGER :: handle
20084 #if defined(__parallel)
20085  INTEGER :: ierr, msglen
20086 #endif
20087 
20088  CALL mp_timeset(routinen, handle)
20089 
20090 #if defined(__parallel)
20091  msglen = 1
20092  CALL mpi_bcast(msg, msglen, mpi_real, comm%source, comm%handle, ierr)
20093  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20094  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20095 #else
20096  mark_used(msg)
20097  mark_used(comm)
20098 #endif
20099  CALL mp_timestop(handle)
20100  END SUBROUTINE mp_bcast_r_src
20101 
20102 ! **************************************************************************************************
20103 !> \brief Broadcasts a datum to all processes.
20104 !> \param[in] msg Datum to broadcast
20105 !> \param[in] source Processes which broadcasts
20106 !> \param[in] comm Message passing environment identifier
20107 !> \par MPI mapping
20108 !> mpi_bcast
20109 ! **************************************************************************************************
20110  SUBROUTINE mp_ibcast_r (msg, source, comm, request)
20111  REAL(kind=real_4), INTENT(INOUT) :: msg
20112  INTEGER, INTENT(IN) :: source
20113  CLASS(mp_comm_type), INTENT(IN) :: comm
20114  TYPE(mp_request_type), INTENT(OUT) :: request
20115 
20116  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_r'
20117 
20118  INTEGER :: handle
20119 #if defined(__parallel)
20120  INTEGER :: ierr, msglen
20121 #endif
20122 
20123  CALL mp_timeset(routinen, handle)
20124 
20125 #if defined(__parallel)
20126  msglen = 1
20127  CALL mpi_ibcast(msg, msglen, mpi_real, source, comm%handle, request%handle, ierr)
20128  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
20129  CALL add_perf(perf_id=22, count=1, msg_size=msglen*real_4_size)
20130 #else
20131  mark_used(msg)
20132  mark_used(source)
20133  mark_used(comm)
20134  request = mp_request_null
20135 #endif
20136  CALL mp_timestop(handle)
20137  END SUBROUTINE mp_ibcast_r
20138 
20139 ! **************************************************************************************************
20140 !> \brief Broadcasts rank-1 data to all processes
20141 !> \param[in] msg Data to broadcast
20142 !> \param source ...
20143 !> \param comm ...
20144 !> \note see mp_bcast_r1
20145 ! **************************************************************************************************
20146  SUBROUTINE mp_bcast_rv(msg, source, comm)
20147  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
20148  INTEGER, INTENT(IN) :: source
20149  CLASS(mp_comm_type), INTENT(IN) :: comm
20150 
20151  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_rv'
20152 
20153  INTEGER :: handle
20154 #if defined(__parallel)
20155  INTEGER :: ierr, msglen
20156 #endif
20157 
20158  CALL mp_timeset(routinen, handle)
20159 
20160 #if defined(__parallel)
20161  msglen = SIZE(msg)
20162  CALL mpi_bcast(msg, msglen, mpi_real, source, comm%handle, ierr)
20163  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20164  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20165 #else
20166  mark_used(msg)
20167  mark_used(source)
20168  mark_used(comm)
20169 #endif
20170  CALL mp_timestop(handle)
20171  END SUBROUTINE mp_bcast_rv
20172 
20173 ! **************************************************************************************************
20174 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
20175 !> \param[in] msg Data to broadcast
20176 !> \param comm ...
20177 !> \note see mp_bcast_r1
20178 ! **************************************************************************************************
20179  SUBROUTINE mp_bcast_rv_src(msg, comm)
20180  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
20181  CLASS(mp_comm_type), INTENT(IN) :: comm
20182 
20183  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_rv_src'
20184 
20185  INTEGER :: handle
20186 #if defined(__parallel)
20187  INTEGER :: ierr, msglen
20188 #endif
20189 
20190  CALL mp_timeset(routinen, handle)
20191 
20192 #if defined(__parallel)
20193  msglen = SIZE(msg)
20194  CALL mpi_bcast(msg, msglen, mpi_real, comm%source, comm%handle, ierr)
20195  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20196  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20197 #else
20198  mark_used(msg)
20199  mark_used(comm)
20200 #endif
20201  CALL mp_timestop(handle)
20202  END SUBROUTINE mp_bcast_rv_src
20203 
20204 ! **************************************************************************************************
20205 !> \brief Broadcasts rank-1 data to all processes
20206 !> \param[in] msg Data to broadcast
20207 !> \param source ...
20208 !> \param comm ...
20209 !> \note see mp_bcast_r1
20210 ! **************************************************************************************************
20211  SUBROUTINE mp_ibcast_rv(msg, source, comm, request)
20212  REAL(kind=real_4), INTENT(INOUT) :: msg(:)
20213  INTEGER, INTENT(IN) :: source
20214  CLASS(mp_comm_type), INTENT(IN) :: comm
20215  TYPE(mp_request_type) :: request
20216 
20217  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_rv'
20218 
20219  INTEGER :: handle
20220 #if defined(__parallel)
20221  INTEGER :: ierr, msglen
20222 #endif
20223 
20224  CALL mp_timeset(routinen, handle)
20225 
20226 #if defined(__parallel)
20227 #if !defined(__GNUC__) || __GNUC__ >= 9
20228  cpassert(is_contiguous(msg))
20229 #endif
20230  msglen = SIZE(msg)
20231  CALL mpi_ibcast(msg, msglen, mpi_real, source, comm%handle, request%handle, ierr)
20232  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
20233  CALL add_perf(perf_id=22, count=1, msg_size=msglen*real_4_size)
20234 #else
20235  mark_used(msg)
20236  mark_used(source)
20237  mark_used(comm)
20238  request = mp_request_null
20239 #endif
20240  CALL mp_timestop(handle)
20241  END SUBROUTINE mp_ibcast_rv
20242 
20243 ! **************************************************************************************************
20244 !> \brief Broadcasts rank-2 data to all processes
20245 !> \param[in] msg Data to broadcast
20246 !> \param source ...
20247 !> \param comm ...
20248 !> \note see mp_bcast_r1
20249 ! **************************************************************************************************
20250  SUBROUTINE mp_bcast_rm(msg, source, comm)
20251  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
20252  INTEGER, INTENT(IN) :: source
20253  CLASS(mp_comm_type), INTENT(IN) :: comm
20254 
20255  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_rm'
20256 
20257  INTEGER :: handle
20258 #if defined(__parallel)
20259  INTEGER :: ierr, msglen
20260 #endif
20261 
20262  CALL mp_timeset(routinen, handle)
20263 
20264 #if defined(__parallel)
20265  msglen = SIZE(msg)
20266  CALL mpi_bcast(msg, msglen, mpi_real, source, comm%handle, ierr)
20267  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20268  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20269 #else
20270  mark_used(msg)
20271  mark_used(source)
20272  mark_used(comm)
20273 #endif
20274  CALL mp_timestop(handle)
20275  END SUBROUTINE mp_bcast_rm
20276 
20277 ! **************************************************************************************************
20278 !> \brief Broadcasts rank-2 data to all processes
20279 !> \param[in] msg Data to broadcast
20280 !> \param source ...
20281 !> \param comm ...
20282 !> \note see mp_bcast_r1
20283 ! **************************************************************************************************
20284  SUBROUTINE mp_bcast_rm_src(msg, comm)
20285  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
20286  CLASS(mp_comm_type), INTENT(IN) :: comm
20287 
20288  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_rm_src'
20289 
20290  INTEGER :: handle
20291 #if defined(__parallel)
20292  INTEGER :: ierr, msglen
20293 #endif
20294 
20295  CALL mp_timeset(routinen, handle)
20296 
20297 #if defined(__parallel)
20298  msglen = SIZE(msg)
20299  CALL mpi_bcast(msg, msglen, mpi_real, comm%source, comm%handle, ierr)
20300  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20301  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20302 #else
20303  mark_used(msg)
20304  mark_used(comm)
20305 #endif
20306  CALL mp_timestop(handle)
20307  END SUBROUTINE mp_bcast_rm_src
20308 
20309 ! **************************************************************************************************
20310 !> \brief Broadcasts rank-3 data to all processes
20311 !> \param[in] msg Data to broadcast
20312 !> \param source ...
20313 !> \param comm ...
20314 !> \note see mp_bcast_r1
20315 ! **************************************************************************************************
20316  SUBROUTINE mp_bcast_r3(msg, source, comm)
20317  REAL(kind=real_4), CONTIGUOUS :: msg(:, :, :)
20318  INTEGER, INTENT(IN) :: source
20319  CLASS(mp_comm_type), INTENT(IN) :: comm
20320 
20321  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_r3'
20322 
20323  INTEGER :: handle
20324 #if defined(__parallel)
20325  INTEGER :: ierr, msglen
20326 #endif
20327 
20328  CALL mp_timeset(routinen, handle)
20329 
20330 #if defined(__parallel)
20331  msglen = SIZE(msg)
20332  CALL mpi_bcast(msg, msglen, mpi_real, source, comm%handle, ierr)
20333  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20334  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20335 #else
20336  mark_used(msg)
20337  mark_used(source)
20338  mark_used(comm)
20339 #endif
20340  CALL mp_timestop(handle)
20341  END SUBROUTINE mp_bcast_r3
20342 
20343 ! **************************************************************************************************
20344 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
20345 !> \param[in] msg Data to broadcast
20346 !> \param source ...
20347 !> \param comm ...
20348 !> \note see mp_bcast_r1
20349 ! **************************************************************************************************
20350  SUBROUTINE mp_bcast_r3_src(msg, comm)
20351  REAL(kind=real_4), CONTIGUOUS :: msg(:, :, :)
20352  CLASS(mp_comm_type), INTENT(IN) :: comm
20353 
20354  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_r3_src'
20355 
20356  INTEGER :: handle
20357 #if defined(__parallel)
20358  INTEGER :: ierr, msglen
20359 #endif
20360 
20361  CALL mp_timeset(routinen, handle)
20362 
20363 #if defined(__parallel)
20364  msglen = SIZE(msg)
20365  CALL mpi_bcast(msg, msglen, mpi_real, comm%source, comm%handle, ierr)
20366  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
20367  CALL add_perf(perf_id=2, count=1, msg_size=msglen*real_4_size)
20368 #else
20369  mark_used(msg)
20370  mark_used(comm)
20371 #endif
20372  CALL mp_timestop(handle)
20373  END SUBROUTINE mp_bcast_r3_src
20374 
20375 ! **************************************************************************************************
20376 !> \brief Sums a datum from all processes with result left on all processes.
20377 !> \param[in,out] msg Datum to sum (input) and result (output)
20378 !> \param[in] comm Message passing environment identifier
20379 !> \par MPI mapping
20380 !> mpi_allreduce
20381 ! **************************************************************************************************
20382  SUBROUTINE mp_sum_r (msg, comm)
20383  REAL(kind=real_4), INTENT(INOUT) :: msg
20384  CLASS(mp_comm_type), INTENT(IN) :: comm
20385 
20386  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_r'
20387 
20388  INTEGER :: handle
20389 #if defined(__parallel)
20390  INTEGER :: ierr, msglen
20391 #endif
20392 
20393  CALL mp_timeset(routinen, handle)
20394 
20395 #if defined(__parallel)
20396  msglen = 1
20397  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_sum, comm%handle, ierr)
20398  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20399  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20400 #else
20401  mark_used(msg)
20402  mark_used(comm)
20403 #endif
20404  CALL mp_timestop(handle)
20405  END SUBROUTINE mp_sum_r
20406 
20407 ! **************************************************************************************************
20408 !> \brief Element-wise sum of a rank-1 array on all processes.
20409 !> \param[in,out] msg Vector to sum and result
20410 !> \param comm ...
20411 !> \note see mp_sum_r
20412 ! **************************************************************************************************
20413  SUBROUTINE mp_sum_rv(msg, comm)
20414  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
20415  CLASS(mp_comm_type), INTENT(IN) :: comm
20416 
20417  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_rv'
20418 
20419  INTEGER :: handle
20420 #if defined(__parallel)
20421  INTEGER :: ierr, msglen
20422 #endif
20423 
20424  CALL mp_timeset(routinen, handle)
20425 
20426 #if defined(__parallel)
20427  msglen = SIZE(msg)
20428  IF (msglen > 0) THEN
20429  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_sum, comm%handle, ierr)
20430  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20431  END IF
20432  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20433 #else
20434  mark_used(msg)
20435  mark_used(comm)
20436 #endif
20437  CALL mp_timestop(handle)
20438  END SUBROUTINE mp_sum_rv
20439 
20440 ! **************************************************************************************************
20441 !> \brief Element-wise sum of a rank-1 array on all processes.
20442 !> \param[in,out] msg Vector to sum and result
20443 !> \param comm ...
20444 !> \note see mp_sum_r
20445 ! **************************************************************************************************
20446  SUBROUTINE mp_isum_rv(msg, comm, request)
20447  REAL(kind=real_4), INTENT(INOUT) :: msg(:)
20448  CLASS(mp_comm_type), INTENT(IN) :: comm
20449  TYPE(mp_request_type), INTENT(OUT) :: request
20450 
20451  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_rv'
20452 
20453  INTEGER :: handle
20454 #if defined(__parallel)
20455  INTEGER :: ierr, msglen
20456 #endif
20457 
20458  CALL mp_timeset(routinen, handle)
20459 
20460 #if defined(__parallel)
20461 #if !defined(__GNUC__) || __GNUC__ >= 9
20462  cpassert(is_contiguous(msg))
20463 #endif
20464  msglen = SIZE(msg)
20465  IF (msglen > 0) THEN
20466  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_real, mpi_sum, comm%handle, request%handle, ierr)
20467  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
20468  ELSE
20469  request = mp_request_null
20470  END IF
20471  CALL add_perf(perf_id=23, count=1, msg_size=msglen*real_4_size)
20472 #else
20473  mark_used(msg)
20474  mark_used(comm)
20475  request = mp_request_null
20476 #endif
20477  CALL mp_timestop(handle)
20478  END SUBROUTINE mp_isum_rv
20479 
20480 ! **************************************************************************************************
20481 !> \brief Element-wise sum of a rank-2 array on all processes.
20482 !> \param[in] msg Matrix to sum and result
20483 !> \param comm ...
20484 !> \note see mp_sum_r
20485 ! **************************************************************************************************
20486  SUBROUTINE mp_sum_rm(msg, comm)
20487  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
20488  CLASS(mp_comm_type), INTENT(IN) :: comm
20489 
20490  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_rm'
20491 
20492  INTEGER :: handle
20493 #if defined(__parallel)
20494  INTEGER, PARAMETER :: max_msg = 2**25
20495  INTEGER :: ierr, m1, msglen, step, msglensum
20496 #endif
20497 
20498  CALL mp_timeset(routinen, handle)
20499 
20500 #if defined(__parallel)
20501  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
20502  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
20503  msglensum = 0
20504  DO m1 = lbound(msg, 2), ubound(msg, 2), step
20505  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
20506  msglensum = msglensum + msglen
20507  IF (msglen > 0) THEN
20508  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_real, mpi_sum, comm%handle, ierr)
20509  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20510  END IF
20511  END DO
20512  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*real_4_size)
20513 #else
20514  mark_used(msg)
20515  mark_used(comm)
20516 #endif
20517  CALL mp_timestop(handle)
20518  END SUBROUTINE mp_sum_rm
20519 
20520 ! **************************************************************************************************
20521 !> \brief Element-wise sum of a rank-3 array on all processes.
20522 !> \param[in] msg Array to sum and result
20523 !> \param comm ...
20524 !> \note see mp_sum_r
20525 ! **************************************************************************************************
20526  SUBROUTINE mp_sum_rm3(msg, comm)
20527  REAL(kind=real_4), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
20528  CLASS(mp_comm_type), INTENT(IN) :: comm
20529 
20530  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_rm3'
20531 
20532  INTEGER :: handle
20533 #if defined(__parallel)
20534  INTEGER :: ierr, msglen
20535 #endif
20536 
20537  CALL mp_timeset(routinen, handle)
20538 
20539 #if defined(__parallel)
20540  msglen = SIZE(msg)
20541  IF (msglen > 0) THEN
20542  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_sum, comm%handle, ierr)
20543  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20544  END IF
20545  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20546 #else
20547  mark_used(msg)
20548  mark_used(comm)
20549 #endif
20550  CALL mp_timestop(handle)
20551  END SUBROUTINE mp_sum_rm3
20552 
20553 ! **************************************************************************************************
20554 !> \brief Element-wise sum of a rank-4 array on all processes.
20555 !> \param[in] msg Array to sum and result
20556 !> \param comm ...
20557 !> \note see mp_sum_r
20558 ! **************************************************************************************************
20559  SUBROUTINE mp_sum_rm4(msg, comm)
20560  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
20561  CLASS(mp_comm_type), INTENT(IN) :: comm
20562 
20563  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_rm4'
20564 
20565  INTEGER :: handle
20566 #if defined(__parallel)
20567  INTEGER :: ierr, msglen
20568 #endif
20569 
20570  CALL mp_timeset(routinen, handle)
20571 
20572 #if defined(__parallel)
20573  msglen = SIZE(msg)
20574  IF (msglen > 0) THEN
20575  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_sum, comm%handle, ierr)
20576  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20577  END IF
20578  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20579 #else
20580  mark_used(msg)
20581  mark_used(comm)
20582 #endif
20583  CALL mp_timestop(handle)
20584  END SUBROUTINE mp_sum_rm4
20585 
20586 ! **************************************************************************************************
20587 !> \brief Element-wise sum of data from all processes with result left only on
20588 !> one.
20589 !> \param[in,out] msg Vector to sum (input) and (only on process root)
20590 !> result (output)
20591 !> \param root ...
20592 !> \param[in] comm Message passing environment identifier
20593 !> \par MPI mapping
20594 !> mpi_reduce
20595 ! **************************************************************************************************
20596  SUBROUTINE mp_sum_root_rv(msg, root, comm)
20597  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
20598  INTEGER, INTENT(IN) :: root
20599  CLASS(mp_comm_type), INTENT(IN) :: comm
20600 
20601  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rv'
20602 
20603  INTEGER :: handle
20604 #if defined(__parallel)
20605  INTEGER :: ierr, m1, msglen, taskid
20606  REAL(kind=real_4), ALLOCATABLE :: res(:)
20607 #endif
20608 
20609  CALL mp_timeset(routinen, handle)
20610 
20611 #if defined(__parallel)
20612  msglen = SIZE(msg)
20613  CALL mpi_comm_rank(comm%handle, taskid, ierr)
20614  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
20615  IF (msglen > 0) THEN
20616  m1 = SIZE(msg, 1)
20617  ALLOCATE (res(m1))
20618  CALL mpi_reduce(msg, res, msglen, mpi_real, mpi_sum, &
20619  root, comm%handle, ierr)
20620  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
20621  IF (taskid == root) THEN
20622  msg = res
20623  END IF
20624  DEALLOCATE (res)
20625  END IF
20626  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20627 #else
20628  mark_used(msg)
20629  mark_used(root)
20630  mark_used(comm)
20631 #endif
20632  CALL mp_timestop(handle)
20633  END SUBROUTINE mp_sum_root_rv
20634 
20635 ! **************************************************************************************************
20636 !> \brief Element-wise sum of data from all processes with result left only on
20637 !> one.
20638 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
20639 !> result (output)
20640 !> \param root ...
20641 !> \param comm ...
20642 !> \note see mp_sum_root_rv
20643 ! **************************************************************************************************
20644  SUBROUTINE mp_sum_root_rm(msg, root, comm)
20645  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
20646  INTEGER, INTENT(IN) :: root
20647  CLASS(mp_comm_type), INTENT(IN) :: comm
20648 
20649  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
20650 
20651  INTEGER :: handle
20652 #if defined(__parallel)
20653  INTEGER :: ierr, m1, m2, msglen, taskid
20654  REAL(kind=real_4), ALLOCATABLE :: res(:, :)
20655 #endif
20656 
20657  CALL mp_timeset(routinen, handle)
20658 
20659 #if defined(__parallel)
20660  msglen = SIZE(msg)
20661  CALL mpi_comm_rank(comm%handle, taskid, ierr)
20662  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
20663  IF (msglen > 0) THEN
20664  m1 = SIZE(msg, 1)
20665  m2 = SIZE(msg, 2)
20666  ALLOCATE (res(m1, m2))
20667  CALL mpi_reduce(msg, res, msglen, mpi_real, mpi_sum, root, comm%handle, ierr)
20668  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
20669  IF (taskid == root) THEN
20670  msg = res
20671  END IF
20672  DEALLOCATE (res)
20673  END IF
20674  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20675 #else
20676  mark_used(root)
20677  mark_used(msg)
20678  mark_used(comm)
20679 #endif
20680  CALL mp_timestop(handle)
20681  END SUBROUTINE mp_sum_root_rm
20682 
20683 ! **************************************************************************************************
20684 !> \brief Partial sum of data from all processes with result on each process.
20685 !> \param[in] msg Matrix to sum (input)
20686 !> \param[out] res Matrix containing result (output)
20687 !> \param[in] comm Message passing environment identifier
20688 ! **************************************************************************************************
20689  SUBROUTINE mp_sum_partial_rm(msg, res, comm)
20690  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
20691  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: res(:, :)
20692  CLASS(mp_comm_type), INTENT(IN) :: comm
20693 
20694  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_rm'
20695 
20696  INTEGER :: handle
20697 #if defined(__parallel)
20698  INTEGER :: ierr, msglen, taskid
20699 #endif
20700 
20701  CALL mp_timeset(routinen, handle)
20702 
20703 #if defined(__parallel)
20704  msglen = SIZE(msg)
20705  CALL mpi_comm_rank(comm%handle, taskid, ierr)
20706  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
20707  IF (msglen > 0) THEN
20708  CALL mpi_scan(msg, res, msglen, mpi_real, mpi_sum, comm%handle, ierr)
20709  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
20710  END IF
20711  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20712  ! perf_id is same as for other summation routines
20713 #else
20714  res = msg
20715  mark_used(comm)
20716 #endif
20717  CALL mp_timestop(handle)
20718  END SUBROUTINE mp_sum_partial_rm
20719 
20720 ! **************************************************************************************************
20721 !> \brief Finds the maximum of a datum with the result left on all processes.
20722 !> \param[in,out] msg Find maximum among these data (input) and
20723 !> maximum (output)
20724 !> \param[in] comm Message passing environment identifier
20725 !> \par MPI mapping
20726 !> mpi_allreduce
20727 ! **************************************************************************************************
20728  SUBROUTINE mp_max_r (msg, comm)
20729  REAL(kind=real_4), INTENT(INOUT) :: msg
20730  CLASS(mp_comm_type), INTENT(IN) :: comm
20731 
20732  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_r'
20733 
20734  INTEGER :: handle
20735 #if defined(__parallel)
20736  INTEGER :: ierr, msglen
20737 #endif
20738 
20739  CALL mp_timeset(routinen, handle)
20740 
20741 #if defined(__parallel)
20742  msglen = 1
20743  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_max, comm%handle, ierr)
20744  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20745  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20746 #else
20747  mark_used(msg)
20748  mark_used(comm)
20749 #endif
20750  CALL mp_timestop(handle)
20751  END SUBROUTINE mp_max_r
20752 
20753 ! **************************************************************************************************
20754 !> \brief Finds the maximum of a datum with the result left on all processes.
20755 !> \param[in,out] msg Find maximum among these data (input) and
20756 !> maximum (output)
20757 !> \param[in] comm Message passing environment identifier
20758 !> \par MPI mapping
20759 !> mpi_allreduce
20760 ! **************************************************************************************************
20761  SUBROUTINE mp_max_root_r (msg, root, comm)
20762  REAL(kind=real_4), INTENT(INOUT) :: msg
20763  INTEGER, INTENT(IN) :: root
20764  CLASS(mp_comm_type), INTENT(IN) :: comm
20765 
20766  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_r'
20767 
20768  INTEGER :: handle
20769 #if defined(__parallel)
20770  INTEGER :: ierr, msglen
20771  REAL(kind=real_4) :: res
20772 #endif
20773 
20774  CALL mp_timeset(routinen, handle)
20775 
20776 #if defined(__parallel)
20777  msglen = 1
20778  CALL mpi_reduce(msg, res, msglen, mpi_real, mpi_max, root, comm%handle, ierr)
20779  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
20780  IF (root == comm%mepos) msg = res
20781  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20782 #else
20783  mark_used(msg)
20784  mark_used(comm)
20785  mark_used(root)
20786 #endif
20787  CALL mp_timestop(handle)
20788  END SUBROUTINE mp_max_root_r
20789 
20790 ! **************************************************************************************************
20791 !> \brief Finds the element-wise maximum of a vector with the result left on
20792 !> all processes.
20793 !> \param[in,out] msg Find maximum among these data (input) and
20794 !> maximum (output)
20795 !> \param comm ...
20796 !> \note see mp_max_r
20797 ! **************************************************************************************************
20798  SUBROUTINE mp_max_rv(msg, comm)
20799  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
20800  CLASS(mp_comm_type), INTENT(IN) :: comm
20801 
20802  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_rv'
20803 
20804  INTEGER :: handle
20805 #if defined(__parallel)
20806  INTEGER :: ierr, msglen
20807 #endif
20808 
20809  CALL mp_timeset(routinen, handle)
20810 
20811 #if defined(__parallel)
20812  msglen = SIZE(msg)
20813  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_max, comm%handle, ierr)
20814  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20815  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20816 #else
20817  mark_used(msg)
20818  mark_used(comm)
20819 #endif
20820  CALL mp_timestop(handle)
20821  END SUBROUTINE mp_max_rv
20822 
20823 ! **************************************************************************************************
20824 !> \brief Finds the element-wise maximum of a vector with the result left on
20825 !> all processes.
20826 !> \param[in,out] msg Find maximum among these data (input) and
20827 !> maximum (output)
20828 !> \param comm ...
20829 !> \note see mp_max_r
20830 ! **************************************************************************************************
20831  SUBROUTINE mp_max_root_rm(msg, root, comm)
20832  REAL(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
20833  INTEGER :: root
20834  CLASS(mp_comm_type), INTENT(IN) :: comm
20835 
20836  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_rm'
20837 
20838  INTEGER :: handle
20839 #if defined(__parallel)
20840  INTEGER :: ierr, msglen
20841  REAL(kind=real_4) :: res(SIZE(msg, 1), SIZE(msg, 2))
20842 #endif
20843 
20844  CALL mp_timeset(routinen, handle)
20845 
20846 #if defined(__parallel)
20847  msglen = SIZE(msg)
20848  CALL mpi_reduce(msg, res, msglen, mpi_real, mpi_max, root, comm%handle, ierr)
20849  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20850  IF (root == comm%mepos) msg = res
20851  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20852 #else
20853  mark_used(msg)
20854  mark_used(comm)
20855  mark_used(root)
20856 #endif
20857  CALL mp_timestop(handle)
20858  END SUBROUTINE mp_max_root_rm
20859 
20860 ! **************************************************************************************************
20861 !> \brief Finds the minimum of a datum with the result left on all processes.
20862 !> \param[in,out] msg Find minimum among these data (input) and
20863 !> maximum (output)
20864 !> \param[in] comm Message passing environment identifier
20865 !> \par MPI mapping
20866 !> mpi_allreduce
20867 ! **************************************************************************************************
20868  SUBROUTINE mp_min_r (msg, comm)
20869  REAL(kind=real_4), INTENT(INOUT) :: msg
20870  CLASS(mp_comm_type), INTENT(IN) :: comm
20871 
20872  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_r'
20873 
20874  INTEGER :: handle
20875 #if defined(__parallel)
20876  INTEGER :: ierr, msglen
20877 #endif
20878 
20879  CALL mp_timeset(routinen, handle)
20880 
20881 #if defined(__parallel)
20882  msglen = 1
20883  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_min, comm%handle, ierr)
20884  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20885  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20886 #else
20887  mark_used(msg)
20888  mark_used(comm)
20889 #endif
20890  CALL mp_timestop(handle)
20891  END SUBROUTINE mp_min_r
20892 
20893 ! **************************************************************************************************
20894 !> \brief Finds the element-wise minimum of vector with the result left on
20895 !> all processes.
20896 !> \param[in,out] msg Find minimum among these data (input) and
20897 !> maximum (output)
20898 !> \param comm ...
20899 !> \par MPI mapping
20900 !> mpi_allreduce
20901 !> \note see mp_min_r
20902 ! **************************************************************************************************
20903  SUBROUTINE mp_min_rv(msg, comm)
20904  REAL(kind=real_4), INTENT(INOUT), CONTIGUOUS :: msg(:)
20905  CLASS(mp_comm_type), INTENT(IN) :: comm
20906 
20907  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_rv'
20908 
20909  INTEGER :: handle
20910 #if defined(__parallel)
20911  INTEGER :: ierr, msglen
20912 #endif
20913 
20914  CALL mp_timeset(routinen, handle)
20915 
20916 #if defined(__parallel)
20917  msglen = SIZE(msg)
20918  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_min, comm%handle, ierr)
20919  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20920  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20921 #else
20922  mark_used(msg)
20923  mark_used(comm)
20924 #endif
20925  CALL mp_timestop(handle)
20926  END SUBROUTINE mp_min_rv
20927 
20928 ! **************************************************************************************************
20929 !> \brief Multiplies a set of numbers scattered across a number of processes,
20930 !> then replicates the result.
20931 !> \param[in,out] msg a number to multiply (input) and result (output)
20932 !> \param[in] comm message passing environment identifier
20933 !> \par MPI mapping
20934 !> mpi_allreduce
20935 ! **************************************************************************************************
20936  SUBROUTINE mp_prod_r (msg, comm)
20937  REAL(kind=real_4), INTENT(INOUT) :: msg
20938  CLASS(mp_comm_type), INTENT(IN) :: comm
20939 
20940  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_r'
20941 
20942  INTEGER :: handle
20943 #if defined(__parallel)
20944  INTEGER :: ierr, msglen
20945 #endif
20946 
20947  CALL mp_timeset(routinen, handle)
20948 
20949 #if defined(__parallel)
20950  msglen = 1
20951  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_real, mpi_prod, comm%handle, ierr)
20952  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
20953  CALL add_perf(perf_id=3, count=1, msg_size=msglen*real_4_size)
20954 #else
20955  mark_used(msg)
20956  mark_used(comm)
20957 #endif
20958  CALL mp_timestop(handle)
20959  END SUBROUTINE mp_prod_r
20960 
20961 ! **************************************************************************************************
20962 !> \brief Scatters data from one processes to all others
20963 !> \param[in] msg_scatter Data to scatter (for root process)
20964 !> \param[out] msg Received data
20965 !> \param[in] root Process which scatters data
20966 !> \param[in] comm Message passing environment identifier
20967 !> \par MPI mapping
20968 !> mpi_scatter
20969 ! **************************************************************************************************
20970  SUBROUTINE mp_scatter_rv(msg_scatter, msg, root, comm)
20971  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
20972  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg(:)
20973  INTEGER, INTENT(IN) :: root
20974  CLASS(mp_comm_type), INTENT(IN) :: comm
20975 
20976  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_rv'
20977 
20978  INTEGER :: handle
20979 #if defined(__parallel)
20980  INTEGER :: ierr, msglen
20981 #endif
20982 
20983  CALL mp_timeset(routinen, handle)
20984 
20985 #if defined(__parallel)
20986  msglen = SIZE(msg)
20987  CALL mpi_scatter(msg_scatter, msglen, mpi_real, msg, &
20988  msglen, mpi_real, root, comm%handle, ierr)
20989  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
20990  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
20991 #else
20992  mark_used(root)
20993  mark_used(comm)
20994  msg = msg_scatter
20995 #endif
20996  CALL mp_timestop(handle)
20997  END SUBROUTINE mp_scatter_rv
20998 
20999 ! **************************************************************************************************
21000 !> \brief Scatters data from one processes to all others
21001 !> \param[in] msg_scatter Data to scatter (for root process)
21002 !> \param[in] root Process which scatters data
21003 !> \param[in] comm Message passing environment identifier
21004 !> \par MPI mapping
21005 !> mpi_scatter
21006 ! **************************************************************************************************
21007  SUBROUTINE mp_iscatter_r (msg_scatter, msg, root, comm, request)
21008  REAL(kind=real_4), INTENT(IN) :: msg_scatter(:)
21009  REAL(kind=real_4), INTENT(INOUT) :: msg
21010  INTEGER, INTENT(IN) :: root
21011  CLASS(mp_comm_type), INTENT(IN) :: comm
21012  TYPE(mp_request_type), INTENT(OUT) :: request
21013 
21014  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_r'
21015 
21016  INTEGER :: handle
21017 #if defined(__parallel)
21018  INTEGER :: ierr, msglen
21019 #endif
21020 
21021  CALL mp_timeset(routinen, handle)
21022 
21023 #if defined(__parallel)
21024 #if !defined(__GNUC__) || __GNUC__ >= 9
21025  cpassert(is_contiguous(msg_scatter))
21026 #endif
21027  msglen = 1
21028  CALL mpi_iscatter(msg_scatter, msglen, mpi_real, msg, &
21029  msglen, mpi_real, root, comm%handle, request%handle, ierr)
21030  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
21031  CALL add_perf(perf_id=24, count=1, msg_size=1*real_4_size)
21032 #else
21033  mark_used(root)
21034  mark_used(comm)
21035  msg = msg_scatter(1)
21036  request = mp_request_null
21037 #endif
21038  CALL mp_timestop(handle)
21039  END SUBROUTINE mp_iscatter_r
21040 
21041 ! **************************************************************************************************
21042 !> \brief Scatters data from one processes to all others
21043 !> \param[in] msg_scatter Data to scatter (for root process)
21044 !> \param[in] root Process which scatters data
21045 !> \param[in] comm Message passing environment identifier
21046 !> \par MPI mapping
21047 !> mpi_scatter
21048 ! **************************************************************************************************
21049  SUBROUTINE mp_iscatter_rv2(msg_scatter, msg, root, comm, request)
21050  REAL(kind=real_4), INTENT(IN) :: msg_scatter(:, :)
21051  REAL(kind=real_4), INTENT(INOUT) :: msg(:)
21052  INTEGER, INTENT(IN) :: root
21053  CLASS(mp_comm_type), INTENT(IN) :: comm
21054  TYPE(mp_request_type), INTENT(OUT) :: request
21055 
21056  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_rv2'
21057 
21058  INTEGER :: handle
21059 #if defined(__parallel)
21060  INTEGER :: ierr, msglen
21061 #endif
21062 
21063  CALL mp_timeset(routinen, handle)
21064 
21065 #if defined(__parallel)
21066 #if !defined(__GNUC__) || __GNUC__ >= 9
21067  cpassert(is_contiguous(msg_scatter))
21068 #endif
21069  msglen = SIZE(msg)
21070  CALL mpi_iscatter(msg_scatter, msglen, mpi_real, msg, &
21071  msglen, mpi_real, root, comm%handle, request%handle, ierr)
21072  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
21073  CALL add_perf(perf_id=24, count=1, msg_size=1*real_4_size)
21074 #else
21075  mark_used(root)
21076  mark_used(comm)
21077  msg(:) = msg_scatter(:, 1)
21078  request = mp_request_null
21079 #endif
21080  CALL mp_timestop(handle)
21081  END SUBROUTINE mp_iscatter_rv2
21082 
21083 ! **************************************************************************************************
21084 !> \brief Scatters data from one processes to all others
21085 !> \param[in] msg_scatter Data to scatter (for root process)
21086 !> \param[in] root Process which scatters data
21087 !> \param[in] comm Message passing environment identifier
21088 !> \par MPI mapping
21089 !> mpi_scatter
21090 ! **************************************************************************************************
21091  SUBROUTINE mp_iscatterv_rv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
21092  REAL(kind=real_4), INTENT(IN) :: msg_scatter(:)
21093  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
21094  REAL(kind=real_4), INTENT(INOUT) :: msg(:)
21095  INTEGER, INTENT(IN) :: recvcount, root
21096  CLASS(mp_comm_type), INTENT(IN) :: comm
21097  TYPE(mp_request_type), INTENT(OUT) :: request
21098 
21099  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_rv'
21100 
21101  INTEGER :: handle
21102 #if defined(__parallel)
21103  INTEGER :: ierr
21104 #endif
21105 
21106  CALL mp_timeset(routinen, handle)
21107 
21108 #if defined(__parallel)
21109 #if !defined(__GNUC__) || __GNUC__ >= 9
21110  cpassert(is_contiguous(msg_scatter))
21111  cpassert(is_contiguous(msg))
21112  cpassert(is_contiguous(sendcounts))
21113  cpassert(is_contiguous(displs))
21114 #endif
21115  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_real, msg, &
21116  recvcount, mpi_real, root, comm%handle, request%handle, ierr)
21117  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
21118  CALL add_perf(perf_id=24, count=1, msg_size=1*real_4_size)
21119 #else
21120  mark_used(sendcounts)
21121  mark_used(displs)
21122  mark_used(recvcount)
21123  mark_used(root)
21124  mark_used(comm)
21125  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
21126  request = mp_request_null
21127 #endif
21128  CALL mp_timestop(handle)
21129  END SUBROUTINE mp_iscatterv_rv
21130 
21131 ! **************************************************************************************************
21132 !> \brief Gathers a datum from all processes to one
21133 !> \param[in] msg Datum to send to root
21134 !> \param[out] msg_gather Received data (on root)
21135 !> \param[in] root Process which gathers the data
21136 !> \param[in] comm Message passing environment identifier
21137 !> \par MPI mapping
21138 !> mpi_gather
21139 ! **************************************************************************************************
21140  SUBROUTINE mp_gather_r (msg, msg_gather, root, comm)
21141  REAL(kind=real_4), INTENT(IN) :: msg
21142  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
21143  INTEGER, INTENT(IN) :: root
21144  CLASS(mp_comm_type), INTENT(IN) :: comm
21145 
21146  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_r'
21147 
21148  INTEGER :: handle
21149 #if defined(__parallel)
21150  INTEGER :: ierr, msglen
21151 #endif
21152 
21153  CALL mp_timeset(routinen, handle)
21154 
21155 #if defined(__parallel)
21156  msglen = 1
21157  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21158  msglen, mpi_real, root, comm%handle, ierr)
21159  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21160  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21161 #else
21162  mark_used(root)
21163  mark_used(comm)
21164  msg_gather(1) = msg
21165 #endif
21166  CALL mp_timestop(handle)
21167  END SUBROUTINE mp_gather_r
21168 
21169 ! **************************************************************************************************
21170 !> \brief Gathers a datum from all processes to one, uses the source process of comm
21171 !> \param[in] msg Datum to send to root
21172 !> \param[out] msg_gather Received data (on root)
21173 !> \param[in] comm Message passing environment identifier
21174 !> \par MPI mapping
21175 !> mpi_gather
21176 ! **************************************************************************************************
21177  SUBROUTINE mp_gather_r_src(msg, msg_gather, comm)
21178  REAL(kind=real_4), INTENT(IN) :: msg
21179  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
21180  CLASS(mp_comm_type), INTENT(IN) :: comm
21181 
21182  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_r_src'
21183 
21184  INTEGER :: handle
21185 #if defined(__parallel)
21186  INTEGER :: ierr, msglen
21187 #endif
21188 
21189  CALL mp_timeset(routinen, handle)
21190 
21191 #if defined(__parallel)
21192  msglen = 1
21193  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21194  msglen, mpi_real, comm%source, comm%handle, ierr)
21195  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21196  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21197 #else
21198  mark_used(comm)
21199  msg_gather(1) = msg
21200 #endif
21201  CALL mp_timestop(handle)
21202  END SUBROUTINE mp_gather_r_src
21203 
21204 ! **************************************************************************************************
21205 !> \brief Gathers data from all processes to one
21206 !> \param[in] msg Datum to send to root
21207 !> \param msg_gather ...
21208 !> \param root ...
21209 !> \param comm ...
21210 !> \par Data length
21211 !> All data (msg) is equal-sized
21212 !> \par MPI mapping
21213 !> mpi_gather
21214 !> \note see mp_gather_r
21215 ! **************************************************************************************************
21216  SUBROUTINE mp_gather_rv(msg, msg_gather, root, comm)
21217  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
21218  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
21219  INTEGER, INTENT(IN) :: root
21220  CLASS(mp_comm_type), INTENT(IN) :: comm
21221 
21222  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_rv'
21223 
21224  INTEGER :: handle
21225 #if defined(__parallel)
21226  INTEGER :: ierr, msglen
21227 #endif
21228 
21229  CALL mp_timeset(routinen, handle)
21230 
21231 #if defined(__parallel)
21232  msglen = SIZE(msg)
21233  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21234  msglen, mpi_real, root, comm%handle, ierr)
21235  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21236  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21237 #else
21238  mark_used(root)
21239  mark_used(comm)
21240  msg_gather = msg
21241 #endif
21242  CALL mp_timestop(handle)
21243  END SUBROUTINE mp_gather_rv
21244 
21245 ! **************************************************************************************************
21246 !> \brief Gathers data from all processes to one. Gathers from comm%source
21247 !> \param[in] msg Datum to send to root
21248 !> \param msg_gather ...
21249 !> \param comm ...
21250 !> \par Data length
21251 !> All data (msg) is equal-sized
21252 !> \par MPI mapping
21253 !> mpi_gather
21254 !> \note see mp_gather_r
21255 ! **************************************************************************************************
21256  SUBROUTINE mp_gather_rv_src(msg, msg_gather, comm)
21257  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
21258  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
21259  CLASS(mp_comm_type), INTENT(IN) :: comm
21260 
21261  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_rv_src'
21262 
21263  INTEGER :: handle
21264 #if defined(__parallel)
21265  INTEGER :: ierr, msglen
21266 #endif
21267 
21268  CALL mp_timeset(routinen, handle)
21269 
21270 #if defined(__parallel)
21271  msglen = SIZE(msg)
21272  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21273  msglen, mpi_real, comm%source, comm%handle, ierr)
21274  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21275  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21276 #else
21277  mark_used(comm)
21278  msg_gather = msg
21279 #endif
21280  CALL mp_timestop(handle)
21281  END SUBROUTINE mp_gather_rv_src
21282 
21283 ! **************************************************************************************************
21284 !> \brief Gathers data from all processes to one
21285 !> \param[in] msg Datum to send to root
21286 !> \param msg_gather ...
21287 !> \param root ...
21288 !> \param comm ...
21289 !> \par Data length
21290 !> All data (msg) is equal-sized
21291 !> \par MPI mapping
21292 !> mpi_gather
21293 !> \note see mp_gather_r
21294 ! **************************************************************************************************
21295  SUBROUTINE mp_gather_rm(msg, msg_gather, root, comm)
21296  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
21297  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
21298  INTEGER, INTENT(IN) :: root
21299  CLASS(mp_comm_type), INTENT(IN) :: comm
21300 
21301  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_rm'
21302 
21303  INTEGER :: handle
21304 #if defined(__parallel)
21305  INTEGER :: ierr, msglen
21306 #endif
21307 
21308  CALL mp_timeset(routinen, handle)
21309 
21310 #if defined(__parallel)
21311  msglen = SIZE(msg)
21312  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21313  msglen, mpi_real, root, comm%handle, ierr)
21314  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21315  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21316 #else
21317  mark_used(root)
21318  mark_used(comm)
21319  msg_gather = msg
21320 #endif
21321  CALL mp_timestop(handle)
21322  END SUBROUTINE mp_gather_rm
21323 
21324 ! **************************************************************************************************
21325 !> \brief Gathers data from all processes to one. Gathers from comm%source
21326 !> \param[in] msg Datum to send to root
21327 !> \param msg_gather ...
21328 !> \param comm ...
21329 !> \par Data length
21330 !> All data (msg) is equal-sized
21331 !> \par MPI mapping
21332 !> mpi_gather
21333 !> \note see mp_gather_r
21334 ! **************************************************************************************************
21335  SUBROUTINE mp_gather_rm_src(msg, msg_gather, comm)
21336  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
21337  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
21338  CLASS(mp_comm_type), INTENT(IN) :: comm
21339 
21340  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_rm_src'
21341 
21342  INTEGER :: handle
21343 #if defined(__parallel)
21344  INTEGER :: ierr, msglen
21345 #endif
21346 
21347  CALL mp_timeset(routinen, handle)
21348 
21349 #if defined(__parallel)
21350  msglen = SIZE(msg)
21351  CALL mpi_gather(msg, msglen, mpi_real, msg_gather, &
21352  msglen, mpi_real, comm%source, comm%handle, ierr)
21353  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
21354  CALL add_perf(perf_id=4, count=1, msg_size=msglen*real_4_size)
21355 #else
21356  mark_used(comm)
21357  msg_gather = msg
21358 #endif
21359  CALL mp_timestop(handle)
21360  END SUBROUTINE mp_gather_rm_src
21361 
21362 ! **************************************************************************************************
21363 !> \brief Gathers data from all processes to one.
21364 !> \param[in] sendbuf Data to send to root
21365 !> \param[out] recvbuf Received data (on root)
21366 !> \param[in] recvcounts Sizes of data received from processes
21367 !> \param[in] displs Offsets of data received from processes
21368 !> \param[in] root Process which gathers the data
21369 !> \param[in] comm Message passing environment identifier
21370 !> \par Data length
21371 !> Data can have different lengths
21372 !> \par Offsets
21373 !> Offsets start at 0
21374 !> \par MPI mapping
21375 !> mpi_gather
21376 ! **************************************************************************************************
21377  SUBROUTINE mp_gatherv_rv(sendbuf, recvbuf, recvcounts, displs, root, comm)
21378 
21379  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
21380  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
21381  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
21382  INTEGER, INTENT(IN) :: root
21383  CLASS(mp_comm_type), INTENT(IN) :: comm
21384 
21385  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_rv'
21386 
21387  INTEGER :: handle
21388 #if defined(__parallel)
21389  INTEGER :: ierr, sendcount
21390 #endif
21391 
21392  CALL mp_timeset(routinen, handle)
21393 
21394 #if defined(__parallel)
21395  sendcount = SIZE(sendbuf)
21396  CALL mpi_gatherv(sendbuf, sendcount, mpi_real, &
21397  recvbuf, recvcounts, displs, mpi_real, &
21398  root, comm%handle, ierr)
21399  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
21400  CALL add_perf(perf_id=4, &
21401  count=1, &
21402  msg_size=sendcount*real_4_size)
21403 #else
21404  mark_used(recvcounts)
21405  mark_used(root)
21406  mark_used(comm)
21407  recvbuf(1 + displs(1):) = sendbuf
21408 #endif
21409  CALL mp_timestop(handle)
21410  END SUBROUTINE mp_gatherv_rv
21411 
21412 ! **************************************************************************************************
21413 !> \brief Gathers data from all processes to one. Gathers from comm%source
21414 !> \param[in] sendbuf Data to send to root
21415 !> \param[out] recvbuf Received data (on root)
21416 !> \param[in] recvcounts Sizes of data received from processes
21417 !> \param[in] displs Offsets of data received from processes
21418 !> \param[in] comm Message passing environment identifier
21419 !> \par Data length
21420 !> Data can have different lengths
21421 !> \par Offsets
21422 !> Offsets start at 0
21423 !> \par MPI mapping
21424 !> mpi_gather
21425 ! **************************************************************************************************
21426  SUBROUTINE mp_gatherv_rv_src(sendbuf, recvbuf, recvcounts, displs, comm)
21427 
21428  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
21429  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
21430  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
21431  CLASS(mp_comm_type), INTENT(IN) :: comm
21432 
21433  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_rv_src'
21434 
21435  INTEGER :: handle
21436 #if defined(__parallel)
21437  INTEGER :: ierr, sendcount
21438 #endif
21439 
21440  CALL mp_timeset(routinen, handle)
21441 
21442 #if defined(__parallel)
21443  sendcount = SIZE(sendbuf)
21444  CALL mpi_gatherv(sendbuf, sendcount, mpi_real, &
21445  recvbuf, recvcounts, displs, mpi_real, &
21446  comm%source, comm%handle, ierr)
21447  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
21448  CALL add_perf(perf_id=4, &
21449  count=1, &
21450  msg_size=sendcount*real_4_size)
21451 #else
21452  mark_used(recvcounts)
21453  mark_used(comm)
21454  recvbuf(1 + displs(1):) = sendbuf
21455 #endif
21456  CALL mp_timestop(handle)
21457  END SUBROUTINE mp_gatherv_rv_src
21458 
21459 ! **************************************************************************************************
21460 !> \brief Gathers data from all processes to one.
21461 !> \param[in] sendbuf Data to send to root
21462 !> \param[out] recvbuf Received data (on root)
21463 !> \param[in] recvcounts Sizes of data received from processes
21464 !> \param[in] displs Offsets of data received from processes
21465 !> \param[in] root Process which gathers the data
21466 !> \param[in] comm Message passing environment identifier
21467 !> \par Data length
21468 !> Data can have different lengths
21469 !> \par Offsets
21470 !> Offsets start at 0
21471 !> \par MPI mapping
21472 !> mpi_gather
21473 ! **************************************************************************************************
21474  SUBROUTINE mp_gatherv_rm2(sendbuf, recvbuf, recvcounts, displs, root, comm)
21475 
21476  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
21477  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
21478  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
21479  INTEGER, INTENT(IN) :: root
21480  CLASS(mp_comm_type), INTENT(IN) :: comm
21481 
21482  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_rm2'
21483 
21484  INTEGER :: handle
21485 #if defined(__parallel)
21486  INTEGER :: ierr, sendcount
21487 #endif
21488 
21489  CALL mp_timeset(routinen, handle)
21490 
21491 #if defined(__parallel)
21492  sendcount = SIZE(sendbuf)
21493  CALL mpi_gatherv(sendbuf, sendcount, mpi_real, &
21494  recvbuf, recvcounts, displs, mpi_real, &
21495  root, comm%handle, ierr)
21496  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
21497  CALL add_perf(perf_id=4, &
21498  count=1, &
21499  msg_size=sendcount*real_4_size)
21500 #else
21501  mark_used(recvcounts)
21502  mark_used(root)
21503  mark_used(comm)
21504  recvbuf(:, 1 + displs(1):) = sendbuf
21505 #endif
21506  CALL mp_timestop(handle)
21507  END SUBROUTINE mp_gatherv_rm2
21508 
21509 ! **************************************************************************************************
21510 !> \brief Gathers data from all processes to one.
21511 !> \param[in] sendbuf Data to send to root
21512 !> \param[out] recvbuf Received data (on root)
21513 !> \param[in] recvcounts Sizes of data received from processes
21514 !> \param[in] displs Offsets of data received from processes
21515 !> \param[in] comm Message passing environment identifier
21516 !> \par Data length
21517 !> Data can have different lengths
21518 !> \par Offsets
21519 !> Offsets start at 0
21520 !> \par MPI mapping
21521 !> mpi_gather
21522 ! **************************************************************************************************
21523  SUBROUTINE mp_gatherv_rm2_src(sendbuf, recvbuf, recvcounts, displs, comm)
21524 
21525  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
21526  REAL(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
21527  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
21528  CLASS(mp_comm_type), INTENT(IN) :: comm
21529 
21530  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_rm2_src'
21531 
21532  INTEGER :: handle
21533 #if defined(__parallel)
21534  INTEGER :: ierr, sendcount
21535 #endif
21536 
21537  CALL mp_timeset(routinen, handle)
21538 
21539 #if defined(__parallel)
21540  sendcount = SIZE(sendbuf)
21541  CALL mpi_gatherv(sendbuf, sendcount, mpi_real, &
21542  recvbuf, recvcounts, displs, mpi_real, &
21543  comm%source, comm%handle, ierr)
21544  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
21545  CALL add_perf(perf_id=4, &
21546  count=1, &
21547  msg_size=sendcount*real_4_size)
21548 #else
21549  mark_used(recvcounts)
21550  mark_used(comm)
21551  recvbuf(:, 1 + displs(1):) = sendbuf
21552 #endif
21553  CALL mp_timestop(handle)
21554  END SUBROUTINE mp_gatherv_rm2_src
21555 
21556 ! **************************************************************************************************
21557 !> \brief Gathers data from all processes to one.
21558 !> \param[in] sendbuf Data to send to root
21559 !> \param[out] recvbuf Received data (on root)
21560 !> \param[in] recvcounts Sizes of data received from processes
21561 !> \param[in] displs Offsets of data received from processes
21562 !> \param[in] root Process which gathers the data
21563 !> \param[in] comm Message passing environment identifier
21564 !> \par Data length
21565 !> Data can have different lengths
21566 !> \par Offsets
21567 !> Offsets start at 0
21568 !> \par MPI mapping
21569 !> mpi_gather
21570 ! **************************************************************************************************
21571  SUBROUTINE mp_igatherv_rv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
21572  REAL(kind=real_4), DIMENSION(:), INTENT(IN) :: sendbuf
21573  REAL(kind=real_4), DIMENSION(:), INTENT(OUT) :: recvbuf
21574  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
21575  INTEGER, INTENT(IN) :: sendcount, root
21576  CLASS(mp_comm_type), INTENT(IN) :: comm
21577  TYPE(mp_request_type), INTENT(OUT) :: request
21578 
21579  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_rv'
21580 
21581  INTEGER :: handle
21582 #if defined(__parallel)
21583  INTEGER :: ierr
21584 #endif
21585 
21586  CALL mp_timeset(routinen, handle)
21587 
21588 #if defined(__parallel)
21589 #if !defined(__GNUC__) || __GNUC__ >= 9
21590  cpassert(is_contiguous(sendbuf))
21591  cpassert(is_contiguous(recvbuf))
21592  cpassert(is_contiguous(recvcounts))
21593  cpassert(is_contiguous(displs))
21594 #endif
21595  CALL mpi_igatherv(sendbuf, sendcount, mpi_real, &
21596  recvbuf, recvcounts, displs, mpi_real, &
21597  root, comm%handle, request%handle, ierr)
21598  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
21599  CALL add_perf(perf_id=24, &
21600  count=1, &
21601  msg_size=sendcount*real_4_size)
21602 #else
21603  mark_used(sendcount)
21604  mark_used(recvcounts)
21605  mark_used(root)
21606  mark_used(comm)
21607  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
21608  request = mp_request_null
21609 #endif
21610  CALL mp_timestop(handle)
21611  END SUBROUTINE mp_igatherv_rv
21612 
21613 ! **************************************************************************************************
21614 !> \brief Gathers a datum from all processes and all processes receive the
21615 !> same data
21616 !> \param[in] msgout Datum to send
21617 !> \param[out] msgin Received data
21618 !> \param[in] comm Message passing environment identifier
21619 !> \par Data size
21620 !> All processes send equal-sized data
21621 !> \par MPI mapping
21622 !> mpi_allgather
21623 ! **************************************************************************************************
21624  SUBROUTINE mp_allgather_r (msgout, msgin, comm)
21625  REAL(kind=real_4), INTENT(IN) :: msgout
21626  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:)
21627  CLASS(mp_comm_type), INTENT(IN) :: comm
21628 
21629  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r'
21630 
21631  INTEGER :: handle
21632 #if defined(__parallel)
21633  INTEGER :: ierr, rcount, scount
21634 #endif
21635 
21636  CALL mp_timeset(routinen, handle)
21637 
21638 #if defined(__parallel)
21639  scount = 1
21640  rcount = 1
21641  CALL mpi_allgather(msgout, scount, mpi_real, &
21642  msgin, rcount, mpi_real, &
21643  comm%handle, ierr)
21644  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21645 #else
21646  mark_used(comm)
21647  msgin = msgout
21648 #endif
21649  CALL mp_timestop(handle)
21650  END SUBROUTINE mp_allgather_r
21651 
21652 ! **************************************************************************************************
21653 !> \brief Gathers a datum from all processes and all processes receive the
21654 !> same data
21655 !> \param[in] msgout Datum to send
21656 !> \param[out] msgin Received data
21657 !> \param[in] comm Message passing environment identifier
21658 !> \par Data size
21659 !> All processes send equal-sized data
21660 !> \par MPI mapping
21661 !> mpi_allgather
21662 ! **************************************************************************************************
21663  SUBROUTINE mp_allgather_r2(msgout, msgin, comm)
21664  REAL(kind=real_4), INTENT(IN) :: msgout
21665  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
21666  CLASS(mp_comm_type), INTENT(IN) :: comm
21667 
21668  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r2'
21669 
21670  INTEGER :: handle
21671 #if defined(__parallel)
21672  INTEGER :: ierr, rcount, scount
21673 #endif
21674 
21675  CALL mp_timeset(routinen, handle)
21676 
21677 #if defined(__parallel)
21678  scount = 1
21679  rcount = 1
21680  CALL mpi_allgather(msgout, scount, mpi_real, &
21681  msgin, rcount, mpi_real, &
21682  comm%handle, ierr)
21683  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21684 #else
21685  mark_used(comm)
21686  msgin = msgout
21687 #endif
21688  CALL mp_timestop(handle)
21689  END SUBROUTINE mp_allgather_r2
21690 
21691 ! **************************************************************************************************
21692 !> \brief Gathers a datum from all processes and all processes receive the
21693 !> same data
21694 !> \param[in] msgout Datum to send
21695 !> \param[out] msgin Received data
21696 !> \param[in] comm Message passing environment identifier
21697 !> \par Data size
21698 !> All processes send equal-sized data
21699 !> \par MPI mapping
21700 !> mpi_allgather
21701 ! **************************************************************************************************
21702  SUBROUTINE mp_iallgather_r (msgout, msgin, comm, request)
21703  REAL(kind=real_4), INTENT(IN) :: msgout
21704  REAL(kind=real_4), INTENT(OUT) :: msgin(:)
21705  CLASS(mp_comm_type), INTENT(IN) :: comm
21706  TYPE(mp_request_type), INTENT(OUT) :: request
21707 
21708  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r'
21709 
21710  INTEGER :: handle
21711 #if defined(__parallel)
21712  INTEGER :: ierr, rcount, scount
21713 #endif
21714 
21715  CALL mp_timeset(routinen, handle)
21716 
21717 #if defined(__parallel)
21718 #if !defined(__GNUC__) || __GNUC__ >= 9
21719  cpassert(is_contiguous(msgin))
21720 #endif
21721  scount = 1
21722  rcount = 1
21723  CALL mpi_iallgather(msgout, scount, mpi_real, &
21724  msgin, rcount, mpi_real, &
21725  comm%handle, request%handle, ierr)
21726  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21727 #else
21728  mark_used(comm)
21729  msgin = msgout
21730  request = mp_request_null
21731 #endif
21732  CALL mp_timestop(handle)
21733  END SUBROUTINE mp_iallgather_r
21734 
21735 ! **************************************************************************************************
21736 !> \brief Gathers vector data from all processes and all processes receive the
21737 !> same data
21738 !> \param[in] msgout Rank-1 data to send
21739 !> \param[out] msgin Received data
21740 !> \param[in] comm Message passing environment identifier
21741 !> \par Data size
21742 !> All processes send equal-sized data
21743 !> \par Ranks
21744 !> The last rank counts the processes
21745 !> \par MPI mapping
21746 !> mpi_allgather
21747 ! **************************************************************************************************
21748  SUBROUTINE mp_allgather_r12(msgout, msgin, comm)
21749  REAL(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:)
21750  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
21751  CLASS(mp_comm_type), INTENT(IN) :: comm
21752 
21753  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r12'
21754 
21755  INTEGER :: handle
21756 #if defined(__parallel)
21757  INTEGER :: ierr, rcount, scount
21758 #endif
21759 
21760  CALL mp_timeset(routinen, handle)
21761 
21762 #if defined(__parallel)
21763  scount = SIZE(msgout(:))
21764  rcount = scount
21765  CALL mpi_allgather(msgout, scount, mpi_real, &
21766  msgin, rcount, mpi_real, &
21767  comm%handle, ierr)
21768  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21769 #else
21770  mark_used(comm)
21771  msgin(:, 1) = msgout(:)
21772 #endif
21773  CALL mp_timestop(handle)
21774  END SUBROUTINE mp_allgather_r12
21775 
21776 ! **************************************************************************************************
21777 !> \brief Gathers matrix data from all processes and all processes receive the
21778 !> same data
21779 !> \param[in] msgout Rank-2 data to send
21780 !> \param msgin ...
21781 !> \param comm ...
21782 !> \note see mp_allgather_r12
21783 ! **************************************************************************************************
21784  SUBROUTINE mp_allgather_r23(msgout, msgin, comm)
21785  REAL(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
21786  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
21787  CLASS(mp_comm_type), INTENT(IN) :: comm
21788 
21789  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r23'
21790 
21791  INTEGER :: handle
21792 #if defined(__parallel)
21793  INTEGER :: ierr, rcount, scount
21794 #endif
21795 
21796  CALL mp_timeset(routinen, handle)
21797 
21798 #if defined(__parallel)
21799  scount = SIZE(msgout(:, :))
21800  rcount = scount
21801  CALL mpi_allgather(msgout, scount, mpi_real, &
21802  msgin, rcount, mpi_real, &
21803  comm%handle, ierr)
21804  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21805 #else
21806  mark_used(comm)
21807  msgin(:, :, 1) = msgout(:, :)
21808 #endif
21809  CALL mp_timestop(handle)
21810  END SUBROUTINE mp_allgather_r23
21811 
21812 ! **************************************************************************************************
21813 !> \brief Gathers rank-3 data from all processes and all processes receive the
21814 !> same data
21815 !> \param[in] msgout Rank-3 data to send
21816 !> \param msgin ...
21817 !> \param comm ...
21818 !> \note see mp_allgather_r12
21819 ! **************************************************************************************************
21820  SUBROUTINE mp_allgather_r34(msgout, msgin, comm)
21821  REAL(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
21822  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
21823  CLASS(mp_comm_type), INTENT(IN) :: comm
21824 
21825  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r34'
21826 
21827  INTEGER :: handle
21828 #if defined(__parallel)
21829  INTEGER :: ierr, rcount, scount
21830 #endif
21831 
21832  CALL mp_timeset(routinen, handle)
21833 
21834 #if defined(__parallel)
21835  scount = SIZE(msgout(:, :, :))
21836  rcount = scount
21837  CALL mpi_allgather(msgout, scount, mpi_real, &
21838  msgin, rcount, mpi_real, &
21839  comm%handle, ierr)
21840  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21841 #else
21842  mark_used(comm)
21843  msgin(:, :, :, 1) = msgout(:, :, :)
21844 #endif
21845  CALL mp_timestop(handle)
21846  END SUBROUTINE mp_allgather_r34
21847 
21848 ! **************************************************************************************************
21849 !> \brief Gathers rank-2 data from all processes and all processes receive the
21850 !> same data
21851 !> \param[in] msgout Rank-2 data to send
21852 !> \param msgin ...
21853 !> \param comm ...
21854 !> \note see mp_allgather_r12
21855 ! **************************************************************************************************
21856  SUBROUTINE mp_allgather_r22(msgout, msgin, comm)
21857  REAL(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
21858  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
21859  CLASS(mp_comm_type), INTENT(IN) :: comm
21860 
21861  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_r22'
21862 
21863  INTEGER :: handle
21864 #if defined(__parallel)
21865  INTEGER :: ierr, rcount, scount
21866 #endif
21867 
21868  CALL mp_timeset(routinen, handle)
21869 
21870 #if defined(__parallel)
21871  scount = SIZE(msgout(:, :))
21872  rcount = scount
21873  CALL mpi_allgather(msgout, scount, mpi_real, &
21874  msgin, rcount, mpi_real, &
21875  comm%handle, ierr)
21876  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
21877 #else
21878  mark_used(comm)
21879  msgin(:, :) = msgout(:, :)
21880 #endif
21881  CALL mp_timestop(handle)
21882  END SUBROUTINE mp_allgather_r22
21883 
21884 ! **************************************************************************************************
21885 !> \brief Gathers rank-1 data from all processes and all processes receive the
21886 !> same data
21887 !> \param[in] msgout Rank-1 data to send
21888 !> \param msgin ...
21889 !> \param comm ...
21890 !> \param request ...
21891 !> \note see mp_allgather_r11
21892 ! **************************************************************************************************
21893  SUBROUTINE mp_iallgather_r11(msgout, msgin, comm, request)
21894  REAL(kind=real_4), INTENT(IN) :: msgout(:)
21895  REAL(kind=real_4), INTENT(OUT) :: msgin(:)
21896  CLASS(mp_comm_type), INTENT(IN) :: comm
21897  TYPE(mp_request_type), INTENT(OUT) :: request
21898 
21899  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r11'
21900 
21901  INTEGER :: handle
21902 #if defined(__parallel)
21903  INTEGER :: ierr, rcount, scount
21904 #endif
21905 
21906  CALL mp_timeset(routinen, handle)
21907 
21908 #if defined(__parallel)
21909 #if !defined(__GNUC__) || __GNUC__ >= 9
21910  cpassert(is_contiguous(msgout))
21911  cpassert(is_contiguous(msgin))
21912 #endif
21913  scount = SIZE(msgout(:))
21914  rcount = scount
21915  CALL mpi_iallgather(msgout, scount, mpi_real, &
21916  msgin, rcount, mpi_real, &
21917  comm%handle, request%handle, ierr)
21918  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
21919 #else
21920  mark_used(comm)
21921  msgin = msgout
21922  request = mp_request_null
21923 #endif
21924  CALL mp_timestop(handle)
21925  END SUBROUTINE mp_iallgather_r11
21926 
21927 ! **************************************************************************************************
21928 !> \brief Gathers rank-2 data from all processes and all processes receive the
21929 !> same data
21930 !> \param[in] msgout Rank-2 data to send
21931 !> \param msgin ...
21932 !> \param comm ...
21933 !> \param request ...
21934 !> \note see mp_allgather_r12
21935 ! **************************************************************************************************
21936  SUBROUTINE mp_iallgather_r13(msgout, msgin, comm, request)
21937  REAL(kind=real_4), INTENT(IN) :: msgout(:)
21938  REAL(kind=real_4), INTENT(OUT) :: msgin(:, :, :)
21939  CLASS(mp_comm_type), INTENT(IN) :: comm
21940  TYPE(mp_request_type), INTENT(OUT) :: request
21941 
21942  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r13'
21943 
21944  INTEGER :: handle
21945 #if defined(__parallel)
21946  INTEGER :: ierr, rcount, scount
21947 #endif
21948 
21949  CALL mp_timeset(routinen, handle)
21950 
21951 #if defined(__parallel)
21952 #if !defined(__GNUC__) || __GNUC__ >= 9
21953  cpassert(is_contiguous(msgout))
21954  cpassert(is_contiguous(msgin))
21955 #endif
21956 
21957  scount = SIZE(msgout(:))
21958  rcount = scount
21959  CALL mpi_iallgather(msgout, scount, mpi_real, &
21960  msgin, rcount, mpi_real, &
21961  comm%handle, request%handle, ierr)
21962  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
21963 #else
21964  mark_used(comm)
21965  msgin(:, 1, 1) = msgout(:)
21966  request = mp_request_null
21967 #endif
21968  CALL mp_timestop(handle)
21969  END SUBROUTINE mp_iallgather_r13
21970 
21971 ! **************************************************************************************************
21972 !> \brief Gathers rank-2 data from all processes and all processes receive the
21973 !> same data
21974 !> \param[in] msgout Rank-2 data to send
21975 !> \param msgin ...
21976 !> \param comm ...
21977 !> \param request ...
21978 !> \note see mp_allgather_r12
21979 ! **************************************************************************************************
21980  SUBROUTINE mp_iallgather_r22(msgout, msgin, comm, request)
21981  REAL(kind=real_4), INTENT(IN) :: msgout(:, :)
21982  REAL(kind=real_4), INTENT(OUT) :: msgin(:, :)
21983  CLASS(mp_comm_type), INTENT(IN) :: comm
21984  TYPE(mp_request_type), INTENT(OUT) :: request
21985 
21986  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r22'
21987 
21988  INTEGER :: handle
21989 #if defined(__parallel)
21990  INTEGER :: ierr, rcount, scount
21991 #endif
21992 
21993  CALL mp_timeset(routinen, handle)
21994 
21995 #if defined(__parallel)
21996 #if !defined(__GNUC__) || __GNUC__ >= 9
21997  cpassert(is_contiguous(msgout))
21998  cpassert(is_contiguous(msgin))
21999 #endif
22000 
22001  scount = SIZE(msgout(:, :))
22002  rcount = scount
22003  CALL mpi_iallgather(msgout, scount, mpi_real, &
22004  msgin, rcount, mpi_real, &
22005  comm%handle, request%handle, ierr)
22006  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
22007 #else
22008  mark_used(comm)
22009  msgin(:, :) = msgout(:, :)
22010  request = mp_request_null
22011 #endif
22012  CALL mp_timestop(handle)
22013  END SUBROUTINE mp_iallgather_r22
22014 
22015 ! **************************************************************************************************
22016 !> \brief Gathers rank-2 data from all processes and all processes receive the
22017 !> same data
22018 !> \param[in] msgout Rank-2 data to send
22019 !> \param msgin ...
22020 !> \param comm ...
22021 !> \param request ...
22022 !> \note see mp_allgather_r12
22023 ! **************************************************************************************************
22024  SUBROUTINE mp_iallgather_r24(msgout, msgin, comm, request)
22025  REAL(kind=real_4), INTENT(IN) :: msgout(:, :)
22026  REAL(kind=real_4), INTENT(OUT) :: msgin(:, :, :, :)
22027  CLASS(mp_comm_type), INTENT(IN) :: comm
22028  TYPE(mp_request_type), INTENT(OUT) :: request
22029 
22030  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r24'
22031 
22032  INTEGER :: handle
22033 #if defined(__parallel)
22034  INTEGER :: ierr, rcount, scount
22035 #endif
22036 
22037  CALL mp_timeset(routinen, handle)
22038 
22039 #if defined(__parallel)
22040 #if !defined(__GNUC__) || __GNUC__ >= 9
22041  cpassert(is_contiguous(msgout))
22042  cpassert(is_contiguous(msgin))
22043 #endif
22044 
22045  scount = SIZE(msgout(:, :))
22046  rcount = scount
22047  CALL mpi_iallgather(msgout, scount, mpi_real, &
22048  msgin, rcount, mpi_real, &
22049  comm%handle, request%handle, ierr)
22050  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
22051 #else
22052  mark_used(comm)
22053  msgin(:, :, 1, 1) = msgout(:, :)
22054  request = mp_request_null
22055 #endif
22056  CALL mp_timestop(handle)
22057  END SUBROUTINE mp_iallgather_r24
22058 
22059 ! **************************************************************************************************
22060 !> \brief Gathers rank-3 data from all processes and all processes receive the
22061 !> same data
22062 !> \param[in] msgout Rank-3 data to send
22063 !> \param msgin ...
22064 !> \param comm ...
22065 !> \param request ...
22066 !> \note see mp_allgather_r12
22067 ! **************************************************************************************************
22068  SUBROUTINE mp_iallgather_r33(msgout, msgin, comm, request)
22069  REAL(kind=real_4), INTENT(IN) :: msgout(:, :, :)
22070  REAL(kind=real_4), INTENT(OUT) :: msgin(:, :, :)
22071  CLASS(mp_comm_type), INTENT(IN) :: comm
22072  TYPE(mp_request_type), INTENT(OUT) :: request
22073 
22074  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_r33'
22075 
22076  INTEGER :: handle
22077 #if defined(__parallel)
22078  INTEGER :: ierr, rcount, scount
22079 #endif
22080 
22081  CALL mp_timeset(routinen, handle)
22082 
22083 #if defined(__parallel)
22084 #if !defined(__GNUC__) || __GNUC__ >= 9
22085  cpassert(is_contiguous(msgout))
22086  cpassert(is_contiguous(msgin))
22087 #endif
22088 
22089  scount = SIZE(msgout(:, :, :))
22090  rcount = scount
22091  CALL mpi_iallgather(msgout, scount, mpi_real, &
22092  msgin, rcount, mpi_real, &
22093  comm%handle, request%handle, ierr)
22094  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
22095 #else
22096  mark_used(comm)
22097  msgin(:, :, :) = msgout(:, :, :)
22098  request = mp_request_null
22099 #endif
22100  CALL mp_timestop(handle)
22101  END SUBROUTINE mp_iallgather_r33
22102 
22103 ! **************************************************************************************************
22104 !> \brief Gathers vector data from all processes and all processes receive the
22105 !> same data
22106 !> \param[in] msgout Rank-1 data to send
22107 !> \param[out] msgin Received data
22108 !> \param[in] rcount Size of sent data for every process
22109 !> \param[in] rdispl Offset of sent data for every process
22110 !> \param[in] comm Message passing environment identifier
22111 !> \par Data size
22112 !> Processes can send different-sized data
22113 !> \par Ranks
22114 !> The last rank counts the processes
22115 !> \par Offsets
22116 !> Offsets are from 0
22117 !> \par MPI mapping
22118 !> mpi_allgather
22119 ! **************************************************************************************************
22120  SUBROUTINE mp_allgatherv_rv(msgout, msgin, rcount, rdispl, comm)
22121  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
22122  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
22123  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
22124  CLASS(mp_comm_type), INTENT(IN) :: comm
22125 
22126  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_rv'
22127 
22128  INTEGER :: handle
22129 #if defined(__parallel)
22130  INTEGER :: ierr, scount
22131 #endif
22132 
22133  CALL mp_timeset(routinen, handle)
22134 
22135 #if defined(__parallel)
22136  scount = SIZE(msgout)
22137  CALL mpi_allgatherv(msgout, scount, mpi_real, msgin, rcount, &
22138  rdispl, mpi_real, comm%handle, ierr)
22139  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
22140 #else
22141  mark_used(rcount)
22142  mark_used(rdispl)
22143  mark_used(comm)
22144  msgin = msgout
22145 #endif
22146  CALL mp_timestop(handle)
22147  END SUBROUTINE mp_allgatherv_rv
22148 
22149 ! **************************************************************************************************
22150 !> \brief Gathers vector data from all processes and all processes receive the
22151 !> same data
22152 !> \param[in] msgout Rank-1 data to send
22153 !> \param[out] msgin Received data
22154 !> \param[in] rcount Size of sent data for every process
22155 !> \param[in] rdispl Offset of sent data for every process
22156 !> \param[in] comm Message passing environment identifier
22157 !> \par Data size
22158 !> Processes can send different-sized data
22159 !> \par Ranks
22160 !> The last rank counts the processes
22161 !> \par Offsets
22162 !> Offsets are from 0
22163 !> \par MPI mapping
22164 !> mpi_allgather
22165 ! **************************************************************************************************
22166  SUBROUTINE mp_allgatherv_rm2(msgout, msgin, rcount, rdispl, comm)
22167  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
22168  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
22169  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
22170  CLASS(mp_comm_type), INTENT(IN) :: comm
22171 
22172  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_rv'
22173 
22174  INTEGER :: handle
22175 #if defined(__parallel)
22176  INTEGER :: ierr, scount
22177 #endif
22178 
22179  CALL mp_timeset(routinen, handle)
22180 
22181 #if defined(__parallel)
22182  scount = SIZE(msgout)
22183  CALL mpi_allgatherv(msgout, scount, mpi_real, msgin, rcount, &
22184  rdispl, mpi_real, comm%handle, ierr)
22185  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
22186 #else
22187  mark_used(rcount)
22188  mark_used(rdispl)
22189  mark_used(comm)
22190  msgin = msgout
22191 #endif
22192  CALL mp_timestop(handle)
22193  END SUBROUTINE mp_allgatherv_rm2
22194 
22195 ! **************************************************************************************************
22196 !> \brief Gathers vector data from all processes and all processes receive the
22197 !> same data
22198 !> \param[in] msgout Rank-1 data to send
22199 !> \param[out] msgin Received data
22200 !> \param[in] rcount Size of sent data for every process
22201 !> \param[in] rdispl Offset of sent data for every process
22202 !> \param[in] comm Message passing environment identifier
22203 !> \par Data size
22204 !> Processes can send different-sized data
22205 !> \par Ranks
22206 !> The last rank counts the processes
22207 !> \par Offsets
22208 !> Offsets are from 0
22209 !> \par MPI mapping
22210 !> mpi_allgather
22211 ! **************************************************************************************************
22212  SUBROUTINE mp_iallgatherv_rv(msgout, msgin, rcount, rdispl, comm, request)
22213  REAL(kind=real_4), INTENT(IN) :: msgout(:)
22214  REAL(kind=real_4), INTENT(OUT) :: msgin(:)
22215  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
22216  CLASS(mp_comm_type), INTENT(IN) :: comm
22217  TYPE(mp_request_type), INTENT(OUT) :: request
22218 
22219  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_rv'
22220 
22221  INTEGER :: handle
22222 #if defined(__parallel)
22223  INTEGER :: ierr, scount, rsize
22224 #endif
22225 
22226  CALL mp_timeset(routinen, handle)
22227 
22228 #if defined(__parallel)
22229 #if !defined(__GNUC__) || __GNUC__ >= 9
22230  cpassert(is_contiguous(msgout))
22231  cpassert(is_contiguous(msgin))
22232  cpassert(is_contiguous(rcount))
22233  cpassert(is_contiguous(rdispl))
22234 #endif
22235 
22236  scount = SIZE(msgout)
22237  rsize = SIZE(rcount)
22238  CALL mp_iallgatherv_rv_internal(msgout, scount, msgin, rsize, rcount, &
22239  rdispl, comm, request, ierr)
22240  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
22241 #else
22242  mark_used(rcount)
22243  mark_used(rdispl)
22244  mark_used(comm)
22245  msgin = msgout
22246  request = mp_request_null
22247 #endif
22248  CALL mp_timestop(handle)
22249  END SUBROUTINE mp_iallgatherv_rv
22250 
22251 ! **************************************************************************************************
22252 !> \brief Gathers vector data from all processes and all processes receive the
22253 !> same data
22254 !> \param[in] msgout Rank-1 data to send
22255 !> \param[out] msgin Received data
22256 !> \param[in] rcount Size of sent data for every process
22257 !> \param[in] rdispl Offset of sent data for every process
22258 !> \param[in] comm Message passing environment identifier
22259 !> \par Data size
22260 !> Processes can send different-sized data
22261 !> \par Ranks
22262 !> The last rank counts the processes
22263 !> \par Offsets
22264 !> Offsets are from 0
22265 !> \par MPI mapping
22266 !> mpi_allgather
22267 ! **************************************************************************************************
22268  SUBROUTINE mp_iallgatherv_rv2(msgout, msgin, rcount, rdispl, comm, request)
22269  REAL(kind=real_4), INTENT(IN) :: msgout(:)
22270  REAL(kind=real_4), INTENT(OUT) :: msgin(:)
22271  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
22272  CLASS(mp_comm_type), INTENT(IN) :: comm
22273  TYPE(mp_request_type), INTENT(OUT) :: request
22274 
22275  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_rv2'
22276 
22277  INTEGER :: handle
22278 #if defined(__parallel)
22279  INTEGER :: ierr, scount, rsize
22280 #endif
22281 
22282  CALL mp_timeset(routinen, handle)
22283 
22284 #if defined(__parallel)
22285 #if !defined(__GNUC__) || __GNUC__ >= 9
22286  cpassert(is_contiguous(msgout))
22287  cpassert(is_contiguous(msgin))
22288  cpassert(is_contiguous(rcount))
22289  cpassert(is_contiguous(rdispl))
22290 #endif
22291 
22292  scount = SIZE(msgout)
22293  rsize = SIZE(rcount)
22294  CALL mp_iallgatherv_rv_internal(msgout, scount, msgin, rsize, rcount, &
22295  rdispl, comm, request, ierr)
22296  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
22297 #else
22298  mark_used(rcount)
22299  mark_used(rdispl)
22300  mark_used(comm)
22301  msgin = msgout
22302  request = mp_request_null
22303 #endif
22304  CALL mp_timestop(handle)
22305  END SUBROUTINE mp_iallgatherv_rv2
22306 
22307 ! **************************************************************************************************
22308 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
22309 !> the issue is with the rank of rcount and rdispl
22310 !> \param count ...
22311 !> \param array_of_requests ...
22312 !> \param array_of_statuses ...
22313 !> \param ierr ...
22314 !> \author Alfio Lazzaro
22315 ! **************************************************************************************************
22316 #if defined(__parallel)
22317  SUBROUTINE mp_iallgatherv_rv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
22318  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
22319  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
22320  INTEGER, INTENT(IN) :: rsize
22321  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
22322  CLASS(mp_comm_type), INTENT(IN) :: comm
22323  TYPE(mp_request_type), INTENT(OUT) :: request
22324  INTEGER, INTENT(INOUT) :: ierr
22325 
22326  CALL mpi_iallgatherv(msgout, scount, mpi_real, msgin, rcount, &
22327  rdispl, mpi_real, comm%handle, request%handle, ierr)
22328 
22329  END SUBROUTINE mp_iallgatherv_rv_internal
22330 #endif
22331 
22332 ! **************************************************************************************************
22333 !> \brief Sums a vector and partitions the result among processes
22334 !> \param[in] msgout Data to sum
22335 !> \param[out] msgin Received portion of summed data
22336 !> \param[in] rcount Partition sizes of the summed data for
22337 !> every process
22338 !> \param[in] comm Message passing environment identifier
22339 ! **************************************************************************************************
22340  SUBROUTINE mp_sum_scatter_rv(msgout, msgin, rcount, comm)
22341  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
22342  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
22343  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
22344  CLASS(mp_comm_type), INTENT(IN) :: comm
22345 
22346  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_rv'
22347 
22348  INTEGER :: handle
22349 #if defined(__parallel)
22350  INTEGER :: ierr
22351 #endif
22352 
22353  CALL mp_timeset(routinen, handle)
22354 
22355 #if defined(__parallel)
22356  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_real, mpi_sum, &
22357  comm%handle, ierr)
22358  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
22359 
22360  CALL add_perf(perf_id=3, count=1, &
22361  msg_size=rcount(1)*2*real_4_size)
22362 #else
22363  mark_used(rcount)
22364  mark_used(comm)
22365  msgin = msgout(:, 1)
22366 #endif
22367  CALL mp_timestop(handle)
22368  END SUBROUTINE mp_sum_scatter_rv
22369 
22370 ! **************************************************************************************************
22371 !> \brief Sends and receives vector data
22372 !> \param[in] msgin Data to send
22373 !> \param[in] dest Process to send data to
22374 !> \param[out] msgout Received data
22375 !> \param[in] source Process from which to receive
22376 !> \param[in] comm Message passing environment identifier
22377 !> \param[in] tag Send and recv tag (default: 0)
22378 ! **************************************************************************************************
22379  SUBROUTINE mp_sendrecv_r (msgin, dest, msgout, source, comm, tag)
22380  REAL(kind=real_4), INTENT(IN) :: msgin
22381  INTEGER, INTENT(IN) :: dest
22382  REAL(kind=real_4), INTENT(OUT) :: msgout
22383  INTEGER, INTENT(IN) :: source
22384  CLASS(mp_comm_type), INTENT(IN) :: comm
22385  INTEGER, INTENT(IN), OPTIONAL :: tag
22386 
22387  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_r'
22388 
22389  INTEGER :: handle
22390 #if defined(__parallel)
22391  INTEGER :: ierr, msglen_in, msglen_out, &
22392  recv_tag, send_tag
22393 #endif
22394 
22395  CALL mp_timeset(routinen, handle)
22396 
22397 #if defined(__parallel)
22398  msglen_in = 1
22399  msglen_out = 1
22400  send_tag = 0 ! cannot think of something better here, this might be dangerous
22401  recv_tag = 0 ! cannot think of something better here, this might be dangerous
22402  IF (PRESENT(tag)) THEN
22403  send_tag = tag
22404  recv_tag = tag
22405  END IF
22406  CALL mpi_sendrecv(msgin, msglen_in, mpi_real, dest, send_tag, msgout, &
22407  msglen_out, mpi_real, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
22408  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
22409  CALL add_perf(perf_id=7, count=1, &
22410  msg_size=(msglen_in + msglen_out)*real_4_size/2)
22411 #else
22412  mark_used(dest)
22413  mark_used(source)
22414  mark_used(comm)
22415  mark_used(tag)
22416  msgout = msgin
22417 #endif
22418  CALL mp_timestop(handle)
22419  END SUBROUTINE mp_sendrecv_r
22420 
22421 ! **************************************************************************************************
22422 !> \brief Sends and receives vector data
22423 !> \param[in] msgin Data to send
22424 !> \param[in] dest Process to send data to
22425 !> \param[out] msgout Received data
22426 !> \param[in] source Process from which to receive
22427 !> \param[in] comm Message passing environment identifier
22428 !> \param[in] tag Send and recv tag (default: 0)
22429 ! **************************************************************************************************
22430  SUBROUTINE mp_sendrecv_rv(msgin, dest, msgout, source, comm, tag)
22431  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:)
22432  INTEGER, INTENT(IN) :: dest
22433  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:)
22434  INTEGER, INTENT(IN) :: source
22435  CLASS(mp_comm_type), INTENT(IN) :: comm
22436  INTEGER, INTENT(IN), OPTIONAL :: tag
22437 
22438  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_rv'
22439 
22440  INTEGER :: handle
22441 #if defined(__parallel)
22442  INTEGER :: ierr, msglen_in, msglen_out, &
22443  recv_tag, send_tag
22444 #endif
22445 
22446  CALL mp_timeset(routinen, handle)
22447 
22448 #if defined(__parallel)
22449  msglen_in = SIZE(msgin)
22450  msglen_out = SIZE(msgout)
22451  send_tag = 0 ! cannot think of something better here, this might be dangerous
22452  recv_tag = 0 ! cannot think of something better here, this might be dangerous
22453  IF (PRESENT(tag)) THEN
22454  send_tag = tag
22455  recv_tag = tag
22456  END IF
22457  CALL mpi_sendrecv(msgin, msglen_in, mpi_real, dest, send_tag, msgout, &
22458  msglen_out, mpi_real, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
22459  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
22460  CALL add_perf(perf_id=7, count=1, &
22461  msg_size=(msglen_in + msglen_out)*real_4_size/2)
22462 #else
22463  mark_used(dest)
22464  mark_used(source)
22465  mark_used(comm)
22466  mark_used(tag)
22467  msgout = msgin
22468 #endif
22469  CALL mp_timestop(handle)
22470  END SUBROUTINE mp_sendrecv_rv
22471 
22472 ! **************************************************************************************************
22473 !> \brief Sends and receives matrix data
22474 !> \param msgin ...
22475 !> \param dest ...
22476 !> \param msgout ...
22477 !> \param source ...
22478 !> \param comm ...
22479 !> \param tag ...
22480 !> \note see mp_sendrecv_rv
22481 ! **************************************************************************************************
22482  SUBROUTINE mp_sendrecv_rm2(msgin, dest, msgout, source, comm, tag)
22483  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
22484  INTEGER, INTENT(IN) :: dest
22485  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
22486  INTEGER, INTENT(IN) :: source
22487  CLASS(mp_comm_type), INTENT(IN) :: comm
22488  INTEGER, INTENT(IN), OPTIONAL :: tag
22489 
22490  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_rm2'
22491 
22492  INTEGER :: handle
22493 #if defined(__parallel)
22494  INTEGER :: ierr, msglen_in, msglen_out, &
22495  recv_tag, send_tag
22496 #endif
22497 
22498  CALL mp_timeset(routinen, handle)
22499 
22500 #if defined(__parallel)
22501  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
22502  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
22503  send_tag = 0 ! cannot think of something better here, this might be dangerous
22504  recv_tag = 0 ! cannot think of something better here, this might be dangerous
22505  IF (PRESENT(tag)) THEN
22506  send_tag = tag
22507  recv_tag = tag
22508  END IF
22509  CALL mpi_sendrecv(msgin, msglen_in, mpi_real, dest, send_tag, msgout, &
22510  msglen_out, mpi_real, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
22511  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
22512  CALL add_perf(perf_id=7, count=1, &
22513  msg_size=(msglen_in + msglen_out)*real_4_size/2)
22514 #else
22515  mark_used(dest)
22516  mark_used(source)
22517  mark_used(comm)
22518  mark_used(tag)
22519  msgout = msgin
22520 #endif
22521  CALL mp_timestop(handle)
22522  END SUBROUTINE mp_sendrecv_rm2
22523 
22524 ! **************************************************************************************************
22525 !> \brief Sends and receives rank-3 data
22526 !> \param msgin ...
22527 !> \param dest ...
22528 !> \param msgout ...
22529 !> \param source ...
22530 !> \param comm ...
22531 !> \note see mp_sendrecv_rv
22532 ! **************************************************************************************************
22533  SUBROUTINE mp_sendrecv_rm3(msgin, dest, msgout, source, comm, tag)
22534  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
22535  INTEGER, INTENT(IN) :: dest
22536  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
22537  INTEGER, INTENT(IN) :: source
22538  CLASS(mp_comm_type), INTENT(IN) :: comm
22539  INTEGER, INTENT(IN), OPTIONAL :: tag
22540 
22541  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_rm3'
22542 
22543  INTEGER :: handle
22544 #if defined(__parallel)
22545  INTEGER :: ierr, msglen_in, msglen_out, &
22546  recv_tag, send_tag
22547 #endif
22548 
22549  CALL mp_timeset(routinen, handle)
22550 
22551 #if defined(__parallel)
22552  msglen_in = SIZE(msgin)
22553  msglen_out = SIZE(msgout)
22554  send_tag = 0 ! cannot think of something better here, this might be dangerous
22555  recv_tag = 0 ! cannot think of something better here, this might be dangerous
22556  IF (PRESENT(tag)) THEN
22557  send_tag = tag
22558  recv_tag = tag
22559  END IF
22560  CALL mpi_sendrecv(msgin, msglen_in, mpi_real, dest, send_tag, msgout, &
22561  msglen_out, mpi_real, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
22562  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
22563  CALL add_perf(perf_id=7, count=1, &
22564  msg_size=(msglen_in + msglen_out)*real_4_size/2)
22565 #else
22566  mark_used(dest)
22567  mark_used(source)
22568  mark_used(comm)
22569  mark_used(tag)
22570  msgout = msgin
22571 #endif
22572  CALL mp_timestop(handle)
22573  END SUBROUTINE mp_sendrecv_rm3
22574 
22575 ! **************************************************************************************************
22576 !> \brief Sends and receives rank-4 data
22577 !> \param msgin ...
22578 !> \param dest ...
22579 !> \param msgout ...
22580 !> \param source ...
22581 !> \param comm ...
22582 !> \note see mp_sendrecv_rv
22583 ! **************************************************************************************************
22584  SUBROUTINE mp_sendrecv_rm4(msgin, dest, msgout, source, comm, tag)
22585  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
22586  INTEGER, INTENT(IN) :: dest
22587  REAL(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
22588  INTEGER, INTENT(IN) :: source
22589  CLASS(mp_comm_type), INTENT(IN) :: comm
22590  INTEGER, INTENT(IN), OPTIONAL :: tag
22591 
22592  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_rm4'
22593 
22594  INTEGER :: handle
22595 #if defined(__parallel)
22596  INTEGER :: ierr, msglen_in, msglen_out, &
22597  recv_tag, send_tag
22598 #endif
22599 
22600  CALL mp_timeset(routinen, handle)
22601 
22602 #if defined(__parallel)
22603  msglen_in = SIZE(msgin)
22604  msglen_out = SIZE(msgout)
22605  send_tag = 0 ! cannot think of something better here, this might be dangerous
22606  recv_tag = 0 ! cannot think of something better here, this might be dangerous
22607  IF (PRESENT(tag)) THEN
22608  send_tag = tag
22609  recv_tag = tag
22610  END IF
22611  CALL mpi_sendrecv(msgin, msglen_in, mpi_real, dest, send_tag, msgout, &
22612  msglen_out, mpi_real, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
22613  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
22614  CALL add_perf(perf_id=7, count=1, &
22615  msg_size=(msglen_in + msglen_out)*real_4_size/2)
22616 #else
22617  mark_used(dest)
22618  mark_used(source)
22619  mark_used(comm)
22620  mark_used(tag)
22621  msgout = msgin
22622 #endif
22623  CALL mp_timestop(handle)
22624  END SUBROUTINE mp_sendrecv_rm4
22625 
22626 ! **************************************************************************************************
22627 !> \brief Non-blocking send and receive of a scalar
22628 !> \param[in] msgin Scalar data to send
22629 !> \param[in] dest Which process to send to
22630 !> \param[out] msgout Receive data into this pointer
22631 !> \param[in] source Process to receive from
22632 !> \param[in] comm Message passing environment identifier
22633 !> \param[out] send_request Request handle for the send
22634 !> \param[out] recv_request Request handle for the receive
22635 !> \param[in] tag (optional) tag to differentiate requests
22636 !> \par Implementation
22637 !> Calls mpi_isend and mpi_irecv.
22638 !> \par History
22639 !> 02.2005 created [Alfio Lazzaro]
22640 ! **************************************************************************************************
22641  SUBROUTINE mp_isendrecv_r (msgin, dest, msgout, source, comm, send_request, &
22642  recv_request, tag)
22643  REAL(kind=real_4), INTENT(IN) :: msgin
22644  INTEGER, INTENT(IN) :: dest
22645  REAL(kind=real_4), INTENT(INOUT) :: msgout
22646  INTEGER, INTENT(IN) :: source
22647  CLASS(mp_comm_type), INTENT(IN) :: comm
22648  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
22649  INTEGER, INTENT(in), OPTIONAL :: tag
22650 
22651  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_r'
22652 
22653  INTEGER :: handle
22654 #if defined(__parallel)
22655  INTEGER :: ierr, my_tag
22656 #endif
22657 
22658  CALL mp_timeset(routinen, handle)
22659 
22660 #if defined(__parallel)
22661  my_tag = 0
22662  IF (PRESENT(tag)) my_tag = tag
22663 
22664  CALL mpi_irecv(msgout, 1, mpi_real, source, my_tag, &
22665  comm%handle, recv_request%handle, ierr)
22666  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
22667 
22668  CALL mpi_isend(msgin, 1, mpi_real, dest, my_tag, &
22669  comm%handle, send_request%handle, ierr)
22670  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
22671 
22672  CALL add_perf(perf_id=8, count=1, msg_size=2*real_4_size)
22673 #else
22674  mark_used(dest)
22675  mark_used(source)
22676  mark_used(comm)
22677  mark_used(tag)
22678  send_request = mp_request_null
22679  recv_request = mp_request_null
22680  msgout = msgin
22681 #endif
22682  CALL mp_timestop(handle)
22683  END SUBROUTINE mp_isendrecv_r
22684 
22685 ! **************************************************************************************************
22686 !> \brief Non-blocking send and receive of a vector
22687 !> \param[in] msgin Vector data to send
22688 !> \param[in] dest Which process to send to
22689 !> \param[out] msgout Receive data into this pointer
22690 !> \param[in] source Process to receive from
22691 !> \param[in] comm Message passing environment identifier
22692 !> \param[out] send_request Request handle for the send
22693 !> \param[out] recv_request Request handle for the receive
22694 !> \param[in] tag (optional) tag to differentiate requests
22695 !> \par Implementation
22696 !> Calls mpi_isend and mpi_irecv.
22697 !> \par History
22698 !> 11.2004 created [Joost VandeVondele]
22699 !> \note
22700 !> arrays can be pointers or assumed shape, but they must be contiguous!
22701 ! **************************************************************************************************
22702  SUBROUTINE mp_isendrecv_rv(msgin, dest, msgout, source, comm, send_request, &
22703  recv_request, tag)
22704  REAL(kind=real_4), DIMENSION(:), INTENT(IN) :: msgin
22705  INTEGER, INTENT(IN) :: dest
22706  REAL(kind=real_4), DIMENSION(:), INTENT(INOUT) :: msgout
22707  INTEGER, INTENT(IN) :: source
22708  CLASS(mp_comm_type), INTENT(IN) :: comm
22709  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
22710  INTEGER, INTENT(in), OPTIONAL :: tag
22711 
22712  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_rv'
22713 
22714  INTEGER :: handle
22715 #if defined(__parallel)
22716  INTEGER :: ierr, msglen, my_tag
22717  REAL(kind=real_4) :: foo
22718 #endif
22719 
22720  CALL mp_timeset(routinen, handle)
22721 
22722 #if defined(__parallel)
22723 #if !defined(__GNUC__) || __GNUC__ >= 9
22724  cpassert(is_contiguous(msgout))
22725  cpassert(is_contiguous(msgin))
22726 #endif
22727 
22728  my_tag = 0
22729  IF (PRESENT(tag)) my_tag = tag
22730 
22731  msglen = SIZE(msgout, 1)
22732  IF (msglen > 0) THEN
22733  CALL mpi_irecv(msgout(1), msglen, mpi_real, source, my_tag, &
22734  comm%handle, recv_request%handle, ierr)
22735  ELSE
22736  CALL mpi_irecv(foo, msglen, mpi_real, source, my_tag, &
22737  comm%handle, recv_request%handle, ierr)
22738  END IF
22739  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
22740 
22741  msglen = SIZE(msgin, 1)
22742  IF (msglen > 0) THEN
22743  CALL mpi_isend(msgin(1), msglen, mpi_real, dest, my_tag, &
22744  comm%handle, send_request%handle, ierr)
22745  ELSE
22746  CALL mpi_isend(foo, msglen, mpi_real, dest, my_tag, &
22747  comm%handle, send_request%handle, ierr)
22748  END IF
22749  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
22750 
22751  msglen = (msglen + SIZE(msgout, 1) + 1)/2
22752  CALL add_perf(perf_id=8, count=1, msg_size=msglen*real_4_size)
22753 #else
22754  mark_used(dest)
22755  mark_used(source)
22756  mark_used(comm)
22757  mark_used(tag)
22758  send_request = mp_request_null
22759  recv_request = mp_request_null
22760  msgout = msgin
22761 #endif
22762  CALL mp_timestop(handle)
22763  END SUBROUTINE mp_isendrecv_rv
22764 
22765 ! **************************************************************************************************
22766 !> \brief Non-blocking send of vector data
22767 !> \param msgin ...
22768 !> \param dest ...
22769 !> \param comm ...
22770 !> \param request ...
22771 !> \param tag ...
22772 !> \par History
22773 !> 08.2003 created [f&j]
22774 !> \note see mp_isendrecv_rv
22775 !> \note
22776 !> arrays can be pointers or assumed shape, but they must be contiguous!
22777 ! **************************************************************************************************
22778  SUBROUTINE mp_isend_rv(msgin, dest, comm, request, tag)
22779  REAL(kind=real_4), DIMENSION(:), INTENT(IN) :: msgin
22780  INTEGER, INTENT(IN) :: dest
22781  CLASS(mp_comm_type), INTENT(IN) :: comm
22782  TYPE(mp_request_type), INTENT(out) :: request
22783  INTEGER, INTENT(in), OPTIONAL :: tag
22784 
22785  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_rv'
22786 
22787  INTEGER :: handle, ierr
22788 #if defined(__parallel)
22789  INTEGER :: msglen, my_tag
22790  REAL(kind=real_4) :: foo(1)
22791 #endif
22792 
22793  CALL mp_timeset(routinen, handle)
22794 
22795 #if defined(__parallel)
22796 #if !defined(__GNUC__) || __GNUC__ >= 9
22797  cpassert(is_contiguous(msgin))
22798 #endif
22799  my_tag = 0
22800  IF (PRESENT(tag)) my_tag = tag
22801 
22802  msglen = SIZE(msgin)
22803  IF (msglen > 0) THEN
22804  CALL mpi_isend(msgin(1), msglen, mpi_real, dest, my_tag, &
22805  comm%handle, request%handle, ierr)
22806  ELSE
22807  CALL mpi_isend(foo, msglen, mpi_real, dest, my_tag, &
22808  comm%handle, request%handle, ierr)
22809  END IF
22810  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
22811 
22812  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_4_size)
22813 #else
22814  mark_used(msgin)
22815  mark_used(dest)
22816  mark_used(comm)
22817  mark_used(request)
22818  mark_used(tag)
22819  ierr = 1
22820  request = mp_request_null
22821  CALL mp_stop(ierr, "mp_isend called in non parallel case")
22822 #endif
22823  CALL mp_timestop(handle)
22824  END SUBROUTINE mp_isend_rv
22825 
22826 ! **************************************************************************************************
22827 !> \brief Non-blocking send of matrix data
22828 !> \param msgin ...
22829 !> \param dest ...
22830 !> \param comm ...
22831 !> \param request ...
22832 !> \param tag ...
22833 !> \par History
22834 !> 2009-11-25 [UB] Made type-generic for templates
22835 !> \author fawzi
22836 !> \note see mp_isendrecv_rv
22837 !> \note see mp_isend_rv
22838 !> \note
22839 !> arrays can be pointers or assumed shape, but they must be contiguous!
22840 ! **************************************************************************************************
22841  SUBROUTINE mp_isend_rm2(msgin, dest, comm, request, tag)
22842  REAL(kind=real_4), DIMENSION(:, :), INTENT(IN) :: msgin
22843  INTEGER, INTENT(IN) :: dest
22844  CLASS(mp_comm_type), INTENT(IN) :: comm
22845  TYPE(mp_request_type), INTENT(out) :: request
22846  INTEGER, INTENT(in), OPTIONAL :: tag
22847 
22848  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_rm2'
22849 
22850  INTEGER :: handle, ierr
22851 #if defined(__parallel)
22852  INTEGER :: msglen, my_tag
22853  REAL(kind=real_4) :: foo(1)
22854 #endif
22855 
22856  CALL mp_timeset(routinen, handle)
22857 
22858 #if defined(__parallel)
22859 #if !defined(__GNUC__) || __GNUC__ >= 9
22860  cpassert(is_contiguous(msgin))
22861 #endif
22862 
22863  my_tag = 0
22864  IF (PRESENT(tag)) my_tag = tag
22865 
22866  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
22867  IF (msglen > 0) THEN
22868  CALL mpi_isend(msgin(1, 1), msglen, mpi_real, dest, my_tag, &
22869  comm%handle, request%handle, ierr)
22870  ELSE
22871  CALL mpi_isend(foo, msglen, mpi_real, dest, my_tag, &
22872  comm%handle, request%handle, ierr)
22873  END IF
22874  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
22875 
22876  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_4_size)
22877 #else
22878  mark_used(msgin)
22879  mark_used(dest)
22880  mark_used(comm)
22881  mark_used(request)
22882  mark_used(tag)
22883  ierr = 1
22884  request = mp_request_null
22885  CALL mp_stop(ierr, "mp_isend called in non parallel case")
22886 #endif
22887  CALL mp_timestop(handle)
22888  END SUBROUTINE mp_isend_rm2
22889 
22890 ! **************************************************************************************************
22891 !> \brief Non-blocking send of rank-3 data
22892 !> \param msgin ...
22893 !> \param dest ...
22894 !> \param comm ...
22895 !> \param request ...
22896 !> \param tag ...
22897 !> \par History
22898 !> 9.2008 added _rm3 subroutine [Iain Bethune]
22899 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
22900 !> 2009-11-25 [UB] Made type-generic for templates
22901 !> \author fawzi
22902 !> \note see mp_isendrecv_rv
22903 !> \note see mp_isend_rv
22904 !> \note
22905 !> arrays can be pointers or assumed shape, but they must be contiguous!
22906 ! **************************************************************************************************
22907  SUBROUTINE mp_isend_rm3(msgin, dest, comm, request, tag)
22908  REAL(kind=real_4), DIMENSION(:, :, :), INTENT(IN) :: msgin
22909  INTEGER, INTENT(IN) :: dest
22910  CLASS(mp_comm_type), INTENT(IN) :: comm
22911  TYPE(mp_request_type), INTENT(out) :: request
22912  INTEGER, INTENT(in), OPTIONAL :: tag
22913 
22914  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_rm3'
22915 
22916  INTEGER :: handle, ierr
22917 #if defined(__parallel)
22918  INTEGER :: msglen, my_tag
22919  REAL(kind=real_4) :: foo(1)
22920 #endif
22921 
22922  CALL mp_timeset(routinen, handle)
22923 
22924 #if defined(__parallel)
22925 #if !defined(__GNUC__) || __GNUC__ >= 9
22926  cpassert(is_contiguous(msgin))
22927 #endif
22928 
22929  my_tag = 0
22930  IF (PRESENT(tag)) my_tag = tag
22931 
22932  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
22933  IF (msglen > 0) THEN
22934  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_real, dest, my_tag, &
22935  comm%handle, request%handle, ierr)
22936  ELSE
22937  CALL mpi_isend(foo, msglen, mpi_real, dest, my_tag, &
22938  comm%handle, request%handle, ierr)
22939  END IF
22940  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
22941 
22942  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_4_size)
22943 #else
22944  mark_used(msgin)
22945  mark_used(dest)
22946  mark_used(comm)
22947  mark_used(request)
22948  mark_used(tag)
22949  ierr = 1
22950  request = mp_request_null
22951  CALL mp_stop(ierr, "mp_isend called in non parallel case")
22952 #endif
22953  CALL mp_timestop(handle)
22954  END SUBROUTINE mp_isend_rm3
22955 
22956 ! **************************************************************************************************
22957 !> \brief Non-blocking send of rank-4 data
22958 !> \param msgin the input message
22959 !> \param dest the destination processor
22960 !> \param comm the communicator object
22961 !> \param request the communication request id
22962 !> \param tag the message tag
22963 !> \par History
22964 !> 2.2016 added _rm4 subroutine [Nico Holmberg]
22965 !> \author fawzi
22966 !> \note see mp_isend_rv
22967 !> \note
22968 !> arrays can be pointers or assumed shape, but they must be contiguous!
22969 ! **************************************************************************************************
22970  SUBROUTINE mp_isend_rm4(msgin, dest, comm, request, tag)
22971  REAL(kind=real_4), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
22972  INTEGER, INTENT(IN) :: dest
22973  CLASS(mp_comm_type), INTENT(IN) :: comm
22974  TYPE(mp_request_type), INTENT(out) :: request
22975  INTEGER, INTENT(in), OPTIONAL :: tag
22976 
22977  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_rm4'
22978 
22979  INTEGER :: handle, ierr
22980 #if defined(__parallel)
22981  INTEGER :: msglen, my_tag
22982  REAL(kind=real_4) :: foo(1)
22983 #endif
22984 
22985  CALL mp_timeset(routinen, handle)
22986 
22987 #if defined(__parallel)
22988 #if !defined(__GNUC__) || __GNUC__ >= 9
22989  cpassert(is_contiguous(msgin))
22990 #endif
22991 
22992  my_tag = 0
22993  IF (PRESENT(tag)) my_tag = tag
22994 
22995  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
22996  IF (msglen > 0) THEN
22997  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_real, dest, my_tag, &
22998  comm%handle, request%handle, ierr)
22999  ELSE
23000  CALL mpi_isend(foo, msglen, mpi_real, dest, my_tag, &
23001  comm%handle, request%handle, ierr)
23002  END IF
23003  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
23004 
23005  CALL add_perf(perf_id=11, count=1, msg_size=msglen*real_4_size)
23006 #else
23007  mark_used(msgin)
23008  mark_used(dest)
23009  mark_used(comm)
23010  mark_used(request)
23011  mark_used(tag)
23012  ierr = 1
23013  request = mp_request_null
23014  CALL mp_stop(ierr, "mp_isend called in non parallel case")
23015 #endif
23016  CALL mp_timestop(handle)
23017  END SUBROUTINE mp_isend_rm4
23018 
23019 ! **************************************************************************************************
23020 !> \brief Non-blocking receive of vector data
23021 !> \param msgout ...
23022 !> \param source ...
23023 !> \param comm ...
23024 !> \param request ...
23025 !> \param tag ...
23026 !> \par History
23027 !> 08.2003 created [f&j]
23028 !> 2009-11-25 [UB] Made type-generic for templates
23029 !> \note see mp_isendrecv_rv
23030 !> \note
23031 !> arrays can be pointers or assumed shape, but they must be contiguous!
23032 ! **************************************************************************************************
23033  SUBROUTINE mp_irecv_rv(msgout, source, comm, request, tag)
23034  REAL(kind=real_4), DIMENSION(:), INTENT(INOUT) :: msgout
23035  INTEGER, INTENT(IN) :: source
23036  CLASS(mp_comm_type), INTENT(IN) :: comm
23037  TYPE(mp_request_type), INTENT(out) :: request
23038  INTEGER, INTENT(in), OPTIONAL :: tag
23039 
23040  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_rv'
23041 
23042  INTEGER :: handle
23043 #if defined(__parallel)
23044  INTEGER :: ierr, msglen, my_tag
23045  REAL(kind=real_4) :: foo(1)
23046 #endif
23047 
23048  CALL mp_timeset(routinen, handle)
23049 
23050 #if defined(__parallel)
23051 #if !defined(__GNUC__) || __GNUC__ >= 9
23052  cpassert(is_contiguous(msgout))
23053 #endif
23054 
23055  my_tag = 0
23056  IF (PRESENT(tag)) my_tag = tag
23057 
23058  msglen = SIZE(msgout)
23059  IF (msglen > 0) THEN
23060  CALL mpi_irecv(msgout(1), msglen, mpi_real, source, my_tag, &
23061  comm%handle, request%handle, ierr)
23062  ELSE
23063  CALL mpi_irecv(foo, msglen, mpi_real, source, my_tag, &
23064  comm%handle, request%handle, ierr)
23065  END IF
23066  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
23067 
23068  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_4_size)
23069 #else
23070  cpabort("mp_irecv called in non parallel case")
23071  mark_used(msgout)
23072  mark_used(source)
23073  mark_used(comm)
23074  mark_used(tag)
23075  request = mp_request_null
23076 #endif
23077  CALL mp_timestop(handle)
23078  END SUBROUTINE mp_irecv_rv
23079 
23080 ! **************************************************************************************************
23081 !> \brief Non-blocking receive of matrix data
23082 !> \param msgout ...
23083 !> \param source ...
23084 !> \param comm ...
23085 !> \param request ...
23086 !> \param tag ...
23087 !> \par History
23088 !> 2009-11-25 [UB] Made type-generic for templates
23089 !> \author fawzi
23090 !> \note see mp_isendrecv_rv
23091 !> \note see mp_irecv_rv
23092 !> \note
23093 !> arrays can be pointers or assumed shape, but they must be contiguous!
23094 ! **************************************************************************************************
23095  SUBROUTINE mp_irecv_rm2(msgout, source, comm, request, tag)
23096  REAL(kind=real_4), DIMENSION(:, :), INTENT(INOUT) :: msgout
23097  INTEGER, INTENT(IN) :: source
23098  CLASS(mp_comm_type), INTENT(IN) :: comm
23099  TYPE(mp_request_type), INTENT(out) :: request
23100  INTEGER, INTENT(in), OPTIONAL :: tag
23101 
23102  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_rm2'
23103 
23104  INTEGER :: handle
23105 #if defined(__parallel)
23106  INTEGER :: ierr, msglen, my_tag
23107  REAL(kind=real_4) :: foo(1)
23108 #endif
23109 
23110  CALL mp_timeset(routinen, handle)
23111 
23112 #if defined(__parallel)
23113 #if !defined(__GNUC__) || __GNUC__ >= 9
23114  cpassert(is_contiguous(msgout))
23115 #endif
23116 
23117  my_tag = 0
23118  IF (PRESENT(tag)) my_tag = tag
23119 
23120  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
23121  IF (msglen > 0) THEN
23122  CALL mpi_irecv(msgout(1, 1), msglen, mpi_real, source, my_tag, &
23123  comm%handle, request%handle, ierr)
23124  ELSE
23125  CALL mpi_irecv(foo, msglen, mpi_real, source, my_tag, &
23126  comm%handle, request%handle, ierr)
23127  END IF
23128  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
23129 
23130  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_4_size)
23131 #else
23132  mark_used(msgout)
23133  mark_used(source)
23134  mark_used(comm)
23135  mark_used(tag)
23136  request = mp_request_null
23137  cpabort("mp_irecv called in non parallel case")
23138 #endif
23139  CALL mp_timestop(handle)
23140  END SUBROUTINE mp_irecv_rm2
23141 
23142 ! **************************************************************************************************
23143 !> \brief Non-blocking send of rank-3 data
23144 !> \param msgout ...
23145 !> \param source ...
23146 !> \param comm ...
23147 !> \param request ...
23148 !> \param tag ...
23149 !> \par History
23150 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
23151 !> 2009-11-25 [UB] Made type-generic for templates
23152 !> \author fawzi
23153 !> \note see mp_isendrecv_rv
23154 !> \note see mp_irecv_rv
23155 !> \note
23156 !> arrays can be pointers or assumed shape, but they must be contiguous!
23157 ! **************************************************************************************************
23158  SUBROUTINE mp_irecv_rm3(msgout, source, comm, request, tag)
23159  REAL(kind=real_4), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
23160  INTEGER, INTENT(IN) :: source
23161  CLASS(mp_comm_type), INTENT(IN) :: comm
23162  TYPE(mp_request_type), INTENT(out) :: request
23163  INTEGER, INTENT(in), OPTIONAL :: tag
23164 
23165  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_rm3'
23166 
23167  INTEGER :: handle
23168 #if defined(__parallel)
23169  INTEGER :: ierr, msglen, my_tag
23170  REAL(kind=real_4) :: foo(1)
23171 #endif
23172 
23173  CALL mp_timeset(routinen, handle)
23174 
23175 #if defined(__parallel)
23176 #if !defined(__GNUC__) || __GNUC__ >= 9
23177  cpassert(is_contiguous(msgout))
23178 #endif
23179 
23180  my_tag = 0
23181  IF (PRESENT(tag)) my_tag = tag
23182 
23183  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
23184  IF (msglen > 0) THEN
23185  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_real, source, my_tag, &
23186  comm%handle, request%handle, ierr)
23187  ELSE
23188  CALL mpi_irecv(foo, msglen, mpi_real, source, my_tag, &
23189  comm%handle, request%handle, ierr)
23190  END IF
23191  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
23192 
23193  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_4_size)
23194 #else
23195  mark_used(msgout)
23196  mark_used(source)
23197  mark_used(comm)
23198  mark_used(tag)
23199  request = mp_request_null
23200  cpabort("mp_irecv called in non parallel case")
23201 #endif
23202  CALL mp_timestop(handle)
23203  END SUBROUTINE mp_irecv_rm3
23204 
23205 ! **************************************************************************************************
23206 !> \brief Non-blocking receive of rank-4 data
23207 !> \param msgout the output message
23208 !> \param source the source processor
23209 !> \param comm the communicator object
23210 !> \param request the communication request id
23211 !> \param tag the message tag
23212 !> \par History
23213 !> 2.2016 added _rm4 subroutine [Nico Holmberg]
23214 !> \author fawzi
23215 !> \note see mp_irecv_rv
23216 !> \note
23217 !> arrays can be pointers or assumed shape, but they must be contiguous!
23218 ! **************************************************************************************************
23219  SUBROUTINE mp_irecv_rm4(msgout, source, comm, request, tag)
23220  REAL(kind=real_4), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
23221  INTEGER, INTENT(IN) :: source
23222  CLASS(mp_comm_type), INTENT(IN) :: comm
23223  TYPE(mp_request_type), INTENT(out) :: request
23224  INTEGER, INTENT(in), OPTIONAL :: tag
23225 
23226  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_rm4'
23227 
23228  INTEGER :: handle
23229 #if defined(__parallel)
23230  INTEGER :: ierr, msglen, my_tag
23231  REAL(kind=real_4) :: foo(1)
23232 #endif
23233 
23234  CALL mp_timeset(routinen, handle)
23235 
23236 #if defined(__parallel)
23237 #if !defined(__GNUC__) || __GNUC__ >= 9
23238  cpassert(is_contiguous(msgout))
23239 #endif
23240 
23241  my_tag = 0
23242  IF (PRESENT(tag)) my_tag = tag
23243 
23244  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
23245  IF (msglen > 0) THEN
23246  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_real, source, my_tag, &
23247  comm%handle, request%handle, ierr)
23248  ELSE
23249  CALL mpi_irecv(foo, msglen, mpi_real, source, my_tag, &
23250  comm%handle, request%handle, ierr)
23251  END IF
23252  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
23253 
23254  CALL add_perf(perf_id=12, count=1, msg_size=msglen*real_4_size)
23255 #else
23256  mark_used(msgout)
23257  mark_used(source)
23258  mark_used(comm)
23259  mark_used(tag)
23260  request = mp_request_null
23261  cpabort("mp_irecv called in non parallel case")
23262 #endif
23263  CALL mp_timestop(handle)
23264  END SUBROUTINE mp_irecv_rm4
23265 
23266 ! **************************************************************************************************
23267 !> \brief Window initialization function for vector data
23268 !> \param base ...
23269 !> \param comm ...
23270 !> \param win ...
23271 !> \par History
23272 !> 02.2015 created [Alfio Lazzaro]
23273 !> \note
23274 !> arrays can be pointers or assumed shape, but they must be contiguous!
23275 ! **************************************************************************************************
23276  SUBROUTINE mp_win_create_rv(base, comm, win)
23277  REAL(kind=real_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
23278  TYPE(mp_comm_type), INTENT(IN) :: comm
23279  CLASS(mp_win_type), INTENT(INOUT) :: win
23280 
23281  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_rv'
23282 
23283  INTEGER :: handle
23284 #if defined(__parallel)
23285  INTEGER :: ierr
23286  INTEGER(kind=mpi_address_kind) :: len
23287  REAL(kind=real_4) :: foo(1)
23288 #endif
23289 
23290  CALL mp_timeset(routinen, handle)
23291 
23292 #if defined(__parallel)
23293 
23294  len = SIZE(base)*real_4_size
23295  IF (len > 0) THEN
23296  CALL mpi_win_create(base(1), len, real_4_size, mpi_info_null, comm%handle, win%handle, ierr)
23297  ELSE
23298  CALL mpi_win_create(foo, len, real_4_size, mpi_info_null, comm%handle, win%handle, ierr)
23299  END IF
23300  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
23301 
23302  CALL add_perf(perf_id=20, count=1)
23303 #else
23304  mark_used(base)
23305  mark_used(comm)
23306  win%handle = mp_win_null_handle
23307 #endif
23308  CALL mp_timestop(handle)
23309  END SUBROUTINE mp_win_create_rv
23310 
23311 ! **************************************************************************************************
23312 !> \brief Single-sided get function for vector data
23313 !> \param base ...
23314 !> \param comm ...
23315 !> \param win ...
23316 !> \par History
23317 !> 02.2015 created [Alfio Lazzaro]
23318 !> \note
23319 !> arrays can be pointers or assumed shape, but they must be contiguous!
23320 ! **************************************************************************************************
23321  SUBROUTINE mp_rget_rv(base, source, win, win_data, myproc, disp, request, &
23322  origin_datatype, target_datatype)
23323  REAL(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
23324  INTEGER, INTENT(IN) :: source
23325  CLASS(mp_win_type), INTENT(IN) :: win
23326  REAL(kind=real_4), DIMENSION(:), INTENT(IN) :: win_data
23327  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
23328  TYPE(mp_request_type), INTENT(OUT) :: request
23329  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
23330 
23331  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_rv'
23332 
23333  INTEGER :: handle
23334 #if defined(__parallel)
23335  INTEGER :: ierr, len, &
23336  origin_len, target_len
23337  LOGICAL :: do_local_copy
23338  INTEGER(kind=mpi_address_kind) :: disp_aint
23339  mpi_data_type :: handle_origin_datatype, handle_target_datatype
23340 #endif
23341 
23342  CALL mp_timeset(routinen, handle)
23343 
23344 #if defined(__parallel)
23345  len = SIZE(base)
23346  disp_aint = 0
23347  IF (PRESENT(disp)) THEN
23348  disp_aint = int(disp, kind=mpi_address_kind)
23349  END IF
23350  handle_origin_datatype = mpi_real
23351  origin_len = len
23352  IF (PRESENT(origin_datatype)) THEN
23353  handle_origin_datatype = origin_datatype%type_handle
23354  origin_len = 1
23355  END IF
23356  handle_target_datatype = mpi_real
23357  target_len = len
23358  IF (PRESENT(target_datatype)) THEN
23359  handle_target_datatype = target_datatype%type_handle
23360  target_len = 1
23361  END IF
23362  IF (len > 0) THEN
23363  do_local_copy = .false.
23364  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
23365  IF (myproc .EQ. source) do_local_copy = .true.
23366  END IF
23367  IF (do_local_copy) THEN
23368  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
23369  base(:) = win_data(disp_aint + 1:disp_aint + len)
23370  !$OMP END PARALLEL WORKSHARE
23371  request = mp_request_null
23372  ierr = 0
23373  ELSE
23374  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
23375  target_len, handle_target_datatype, win%handle, request%handle, ierr)
23376  END IF
23377  ELSE
23378  request = mp_request_null
23379  ierr = 0
23380  END IF
23381  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
23382 
23383  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*real_4_size)
23384 #else
23385  mark_used(source)
23386  mark_used(win)
23387  mark_used(myproc)
23388  mark_used(origin_datatype)
23389  mark_used(target_datatype)
23390 
23391  request = mp_request_null
23392  !
23393  IF (PRESENT(disp)) THEN
23394  base(:) = win_data(disp + 1:disp + SIZE(base))
23395  ELSE
23396  base(:) = win_data(:SIZE(base))
23397  END IF
23398 
23399 #endif
23400  CALL mp_timestop(handle)
23401  END SUBROUTINE mp_rget_rv
23402 
23403 ! **************************************************************************************************
23404 !> \brief ...
23405 !> \param count ...
23406 !> \param lengths ...
23407 !> \param displs ...
23408 !> \return ...
23409 ! ***************************************************************************
23410  FUNCTION mp_type_indexed_make_r (count, lengths, displs) &
23411  result(type_descriptor)
23412  INTEGER, INTENT(IN) :: count
23413  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
23414  TYPE(mp_type_descriptor_type) :: type_descriptor
23415 
23416  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_r'
23417 
23418  INTEGER :: handle
23419 #if defined(__parallel)
23420  INTEGER :: ierr
23421 #endif
23422 
23423  CALL mp_timeset(routinen, handle)
23424 
23425 #if defined(__parallel)
23426  CALL mpi_type_indexed(count, lengths, displs, mpi_real, &
23427  type_descriptor%type_handle, ierr)
23428  IF (ierr /= 0) &
23429  cpabort("MPI_Type_Indexed @ "//routinen)
23430  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
23431  IF (ierr /= 0) &
23432  cpabort("MPI_Type_commit @ "//routinen)
23433 #else
23434  type_descriptor%type_handle = 1
23435 #endif
23436  type_descriptor%length = count
23437  NULLIFY (type_descriptor%subtype)
23438  type_descriptor%vector_descriptor(1:2) = 1
23439  type_descriptor%has_indexing = .true.
23440  type_descriptor%index_descriptor%index => lengths
23441  type_descriptor%index_descriptor%chunks => displs
23442 
23443  CALL mp_timestop(handle)
23444 
23445  END FUNCTION mp_type_indexed_make_r
23446 
23447 ! **************************************************************************************************
23448 !> \brief Allocates special parallel memory
23449 !> \param[in] DATA pointer to integer array to allocate
23450 !> \param[in] len number of integers to allocate
23451 !> \param[out] stat (optional) allocation status result
23452 !> \author UB
23453 ! **************************************************************************************************
23454  SUBROUTINE mp_allocate_r (DATA, len, stat)
23455  REAL(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
23456  INTEGER, INTENT(IN) :: len
23457  INTEGER, INTENT(OUT), OPTIONAL :: stat
23458 
23459  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_r'
23460 
23461  INTEGER :: handle, ierr
23462 
23463  CALL mp_timeset(routinen, handle)
23464 
23465 #if defined(__parallel)
23466  NULLIFY (data)
23467  CALL mp_alloc_mem(DATA, len, stat=ierr)
23468  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
23469  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
23470  CALL add_perf(perf_id=15, count=1)
23471 #else
23472  ALLOCATE (DATA(len), stat=ierr)
23473  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
23474  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
23475 #endif
23476  IF (PRESENT(stat)) stat = ierr
23477  CALL mp_timestop(handle)
23478  END SUBROUTINE mp_allocate_r
23479 
23480 ! **************************************************************************************************
23481 !> \brief Deallocates special parallel memory
23482 !> \param[in] DATA pointer to special memory to deallocate
23483 !> \param stat ...
23484 !> \author UB
23485 ! **************************************************************************************************
23486  SUBROUTINE mp_deallocate_r (DATA, stat)
23487  REAL(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
23488  INTEGER, INTENT(OUT), OPTIONAL :: stat
23489 
23490  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_r'
23491 
23492  INTEGER :: handle
23493 #if defined(__parallel)
23494  INTEGER :: ierr
23495 #endif
23496 
23497  CALL mp_timeset(routinen, handle)
23498 
23499 #if defined(__parallel)
23500  CALL mp_free_mem(DATA, ierr)
23501  IF (PRESENT(stat)) THEN
23502  stat = ierr
23503  ELSE
23504  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
23505  END IF
23506  NULLIFY (data)
23507  CALL add_perf(perf_id=15, count=1)
23508 #else
23509  DEALLOCATE (data)
23510  IF (PRESENT(stat)) stat = 0
23511 #endif
23512  CALL mp_timestop(handle)
23513  END SUBROUTINE mp_deallocate_r
23514 
23515 ! **************************************************************************************************
23516 !> \brief (parallel) Blocking individual file write using explicit offsets
23517 !> (serial) Unformatted stream write
23518 !> \param[in] fh file handle (file storage unit)
23519 !> \param[in] offset file offset (position)
23520 !> \param[in] msg data to be written to the file
23521 !> \param msglen ...
23522 !> \par MPI-I/O mapping mpi_file_write_at
23523 !> \par STREAM-I/O mapping WRITE
23524 !> \param[in](optional) msglen number of the elements of data
23525 ! **************************************************************************************************
23526  SUBROUTINE mp_file_write_at_rv(fh, offset, msg, msglen)
23527  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
23528  CLASS(mp_file_type), INTENT(IN) :: fh
23529  INTEGER, INTENT(IN), OPTIONAL :: msglen
23530  INTEGER(kind=file_offset), INTENT(IN) :: offset
23531 
23532  INTEGER :: msg_len
23533 #if defined(__parallel)
23534  INTEGER :: ierr
23535 #endif
23536 
23537  msg_len = SIZE(msg)
23538  IF (PRESENT(msglen)) msg_len = msglen
23539 #if defined(__parallel)
23540  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_real, mpi_status_ignore, ierr)
23541  IF (ierr .NE. 0) &
23542  cpabort("mpi_file_write_at_rv @ mp_file_write_at_rv")
23543 #else
23544  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
23545 #endif
23546  END SUBROUTINE mp_file_write_at_rv
23547 
23548 ! **************************************************************************************************
23549 !> \brief ...
23550 !> \param fh ...
23551 !> \param offset ...
23552 !> \param msg ...
23553 ! **************************************************************************************************
23554  SUBROUTINE mp_file_write_at_r (fh, offset, msg)
23555  REAL(kind=real_4), INTENT(IN) :: msg
23556  CLASS(mp_file_type), INTENT(IN) :: fh
23557  INTEGER(kind=file_offset), INTENT(IN) :: offset
23558 
23559 #if defined(__parallel)
23560  INTEGER :: ierr
23561 
23562  ierr = 0
23563  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_real, mpi_status_ignore, ierr)
23564  IF (ierr .NE. 0) &
23565  cpabort("mpi_file_write_at_r @ mp_file_write_at_r")
23566 #else
23567  WRITE (unit=fh%handle, pos=offset + 1) msg
23568 #endif
23569  END SUBROUTINE mp_file_write_at_r
23570 
23571 ! **************************************************************************************************
23572 !> \brief (parallel) Blocking collective file write using explicit offsets
23573 !> (serial) Unformatted stream write
23574 !> \param fh ...
23575 !> \param offset ...
23576 !> \param msg ...
23577 !> \param msglen ...
23578 !> \par MPI-I/O mapping mpi_file_write_at_all
23579 !> \par STREAM-I/O mapping WRITE
23580 ! **************************************************************************************************
23581  SUBROUTINE mp_file_write_at_all_rv(fh, offset, msg, msglen)
23582  REAL(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
23583  CLASS(mp_file_type), INTENT(IN) :: fh
23584  INTEGER, INTENT(IN), OPTIONAL :: msglen
23585  INTEGER(kind=file_offset), INTENT(IN) :: offset
23586 
23587  INTEGER :: msg_len
23588 #if defined(__parallel)
23589  INTEGER :: ierr
23590 #endif
23591 
23592  msg_len = SIZE(msg)
23593  IF (PRESENT(msglen)) msg_len = msglen
23594 #if defined(__parallel)
23595  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_real, mpi_status_ignore, ierr)
23596  IF (ierr .NE. 0) &
23597  cpabort("mpi_file_write_at_all_rv @ mp_file_write_at_all_rv")
23598 #else
23599  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
23600 #endif
23601  END SUBROUTINE mp_file_write_at_all_rv
23602 
23603 ! **************************************************************************************************
23604 !> \brief ...
23605 !> \param fh ...
23606 !> \param offset ...
23607 !> \param msg ...
23608 ! **************************************************************************************************
23609  SUBROUTINE mp_file_write_at_all_r (fh, offset, msg)
23610  REAL(kind=real_4), INTENT(IN) :: msg
23611  CLASS(mp_file_type), INTENT(IN) :: fh
23612  INTEGER(kind=file_offset), INTENT(IN) :: offset
23613 
23614 #if defined(__parallel)
23615  INTEGER :: ierr
23616 
23617  ierr = 0
23618  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_real, mpi_status_ignore, ierr)
23619  IF (ierr .NE. 0) &
23620  cpabort("mpi_file_write_at_all_r @ mp_file_write_at_all_r")
23621 #else
23622  WRITE (unit=fh%handle, pos=offset + 1) msg
23623 #endif
23624  END SUBROUTINE mp_file_write_at_all_r
23625 
23626 ! **************************************************************************************************
23627 !> \brief (parallel) Blocking individual file read using explicit offsets
23628 !> (serial) Unformatted stream read
23629 !> \param[in] fh file handle (file storage unit)
23630 !> \param[in] offset file offset (position)
23631 !> \param[out] msg data to be read from the file
23632 !> \param msglen ...
23633 !> \par MPI-I/O mapping mpi_file_read_at
23634 !> \par STREAM-I/O mapping READ
23635 !> \param[in](optional) msglen number of elements of data
23636 ! **************************************************************************************************
23637  SUBROUTINE mp_file_read_at_rv(fh, offset, msg, msglen)
23638  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msg(:)
23639  CLASS(mp_file_type), INTENT(IN) :: fh
23640  INTEGER, INTENT(IN), OPTIONAL :: msglen
23641  INTEGER(kind=file_offset), INTENT(IN) :: offset
23642 
23643  INTEGER :: msg_len
23644 #if defined(__parallel)
23645  INTEGER :: ierr
23646 #endif
23647 
23648  msg_len = SIZE(msg)
23649  IF (PRESENT(msglen)) msg_len = msglen
23650 #if defined(__parallel)
23651  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_real, mpi_status_ignore, ierr)
23652  IF (ierr .NE. 0) &
23653  cpabort("mpi_file_read_at_rv @ mp_file_read_at_rv")
23654 #else
23655  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
23656 #endif
23657  END SUBROUTINE mp_file_read_at_rv
23658 
23659 ! **************************************************************************************************
23660 !> \brief ...
23661 !> \param fh ...
23662 !> \param offset ...
23663 !> \param msg ...
23664 ! **************************************************************************************************
23665  SUBROUTINE mp_file_read_at_r (fh, offset, msg)
23666  REAL(kind=real_4), INTENT(OUT) :: msg
23667  CLASS(mp_file_type), INTENT(IN) :: fh
23668  INTEGER(kind=file_offset), INTENT(IN) :: offset
23669 
23670 #if defined(__parallel)
23671  INTEGER :: ierr
23672 
23673  ierr = 0
23674  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_real, mpi_status_ignore, ierr)
23675  IF (ierr .NE. 0) &
23676  cpabort("mpi_file_read_at_r @ mp_file_read_at_r")
23677 #else
23678  READ (unit=fh%handle, pos=offset + 1) msg
23679 #endif
23680  END SUBROUTINE mp_file_read_at_r
23681 
23682 ! **************************************************************************************************
23683 !> \brief (parallel) Blocking collective file read using explicit offsets
23684 !> (serial) Unformatted stream read
23685 !> \param fh ...
23686 !> \param offset ...
23687 !> \param msg ...
23688 !> \param msglen ...
23689 !> \par MPI-I/O mapping mpi_file_read_at_all
23690 !> \par STREAM-I/O mapping READ
23691 ! **************************************************************************************************
23692  SUBROUTINE mp_file_read_at_all_rv(fh, offset, msg, msglen)
23693  REAL(kind=real_4), INTENT(OUT), CONTIGUOUS :: msg(:)
23694  CLASS(mp_file_type), INTENT(IN) :: fh
23695  INTEGER, INTENT(IN), OPTIONAL :: msglen
23696  INTEGER(kind=file_offset), INTENT(IN) :: offset
23697 
23698  INTEGER :: msg_len
23699 #if defined(__parallel)
23700  INTEGER :: ierr
23701 #endif
23702 
23703  msg_len = SIZE(msg)
23704  IF (PRESENT(msglen)) msg_len = msglen
23705 #if defined(__parallel)
23706  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_real, mpi_status_ignore, ierr)
23707  IF (ierr .NE. 0) &
23708  cpabort("mpi_file_read_at_all_rv @ mp_file_read_at_all_rv")
23709 #else
23710  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
23711 #endif
23712  END SUBROUTINE mp_file_read_at_all_rv
23713 
23714 ! **************************************************************************************************
23715 !> \brief ...
23716 !> \param fh ...
23717 !> \param offset ...
23718 !> \param msg ...
23719 ! **************************************************************************************************
23720  SUBROUTINE mp_file_read_at_all_r (fh, offset, msg)
23721  REAL(kind=real_4), INTENT(OUT) :: msg
23722  CLASS(mp_file_type), INTENT(IN) :: fh
23723  INTEGER(kind=file_offset), INTENT(IN) :: offset
23724 
23725 #if defined(__parallel)
23726  INTEGER :: ierr
23727 
23728  ierr = 0
23729  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_real, mpi_status_ignore, ierr)
23730  IF (ierr .NE. 0) &
23731  cpabort("mpi_file_read_at_all_r @ mp_file_read_at_all_r")
23732 #else
23733  READ (unit=fh%handle, pos=offset + 1) msg
23734 #endif
23735  END SUBROUTINE mp_file_read_at_all_r
23736 
23737 ! **************************************************************************************************
23738 !> \brief ...
23739 !> \param ptr ...
23740 !> \param vector_descriptor ...
23741 !> \param index_descriptor ...
23742 !> \return ...
23743 ! **************************************************************************************************
23744  FUNCTION mp_type_make_r (ptr, &
23745  vector_descriptor, index_descriptor) &
23746  result(type_descriptor)
23747  REAL(kind=real_4), DIMENSION(:), TARGET, asynchronous :: ptr
23748  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
23749  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
23750  TYPE(mp_type_descriptor_type) :: type_descriptor
23751 
23752  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_r'
23753 
23754 #if defined(__parallel)
23755  INTEGER :: ierr
23756 #endif
23757 
23758  NULLIFY (type_descriptor%subtype)
23759  type_descriptor%length = SIZE(ptr)
23760 #if defined(__parallel)
23761  type_descriptor%type_handle = mpi_real
23762  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
23763  IF (ierr /= 0) &
23764  cpabort("MPI_Get_address @ "//routinen)
23765 #else
23766  type_descriptor%type_handle = 1
23767 #endif
23768  type_descriptor%vector_descriptor(1:2) = 1
23769  type_descriptor%has_indexing = .false.
23770  type_descriptor%data_r => ptr
23771  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
23772  cpabort(routinen//": Vectors and indices NYI")
23773  END IF
23774  END FUNCTION mp_type_make_r
23775 
23776 ! **************************************************************************************************
23777 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
23778 !> as the Fortran version returns an integer, which we take to be a C_PTR
23779 !> \param DATA data array to allocate
23780 !> \param[in] len length (in data elements) of data array allocation
23781 !> \param[out] stat (optional) allocation status result
23782 ! **************************************************************************************************
23783  SUBROUTINE mp_alloc_mem_r (DATA, len, stat)
23784  REAL(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: DATA
23785  INTEGER, INTENT(IN) :: len
23786  INTEGER, INTENT(OUT), OPTIONAL :: stat
23787 
23788 #if defined(__parallel)
23789  INTEGER :: size, ierr, length, &
23790  mp_res
23791  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
23792  TYPE(c_ptr) :: mp_baseptr
23793  mpi_info_type :: mp_info
23794 
23795  length = max(len, 1)
23796  CALL mpi_type_size(mpi_real, size, ierr)
23797  mp_size = int(length, kind=mpi_address_kind)*size
23798  IF (mp_size .GT. mp_max_memory_size) THEN
23799  cpabort("MPI cannot allocate more than 2 GiByte")
23800  END IF
23801  mp_info = mpi_info_null
23802  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
23803  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
23804  IF (PRESENT(stat)) stat = mp_res
23805 #else
23806  INTEGER :: length, mystat
23807  length = max(len, 1)
23808  IF (PRESENT(stat)) THEN
23809  ALLOCATE (DATA(length), stat=mystat)
23810  stat = mystat ! show to convention checker that stat is used
23811  ELSE
23812  ALLOCATE (DATA(length))
23813  END IF
23814 #endif
23815  END SUBROUTINE mp_alloc_mem_r
23816 
23817 ! **************************************************************************************************
23818 !> \brief Deallocates am array, ... this is hackish
23819 !> as the Fortran version takes an integer, which we hope to get by reference
23820 !> \param DATA data array to allocate
23821 !> \param[out] stat (optional) allocation status result
23822 ! **************************************************************************************************
23823  SUBROUTINE mp_free_mem_r (DATA, stat)
23824  REAL(kind=real_4), DIMENSION(:), &
23825  POINTER, asynchronous :: DATA
23826  INTEGER, INTENT(OUT), OPTIONAL :: stat
23827 
23828 #if defined(__parallel)
23829  INTEGER :: mp_res
23830  CALL mpi_free_mem(DATA, mp_res)
23831  IF (PRESENT(stat)) stat = mp_res
23832 #else
23833  DEALLOCATE (data)
23834  IF (PRESENT(stat)) stat = 0
23835 #endif
23836  END SUBROUTINE mp_free_mem_r
23837 ! **************************************************************************************************
23838 !> \brief Shift around the data in msg
23839 !> \param[in,out] msg Rank-2 data to shift
23840 !> \param[in] comm message passing environment identifier
23841 !> \param[in] displ_in displacements (?)
23842 !> \par Example
23843 !> msg will be moved from rank to rank+displ_in (in a circular way)
23844 !> \par Limitations
23845 !> * displ_in will be 1 by default (others not tested)
23846 !> * the message array needs to be the same size on all processes
23847 ! **************************************************************************************************
23848  SUBROUTINE mp_shift_zm(msg, comm, displ_in)
23849 
23850  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
23851  CLASS(mp_comm_type), INTENT(IN) :: comm
23852  INTEGER, INTENT(IN), OPTIONAL :: displ_in
23853 
23854  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_zm'
23855 
23856  INTEGER :: handle, ierror
23857 #if defined(__parallel)
23858  INTEGER :: displ, left, &
23859  msglen, myrank, nprocs, &
23860  right, tag
23861 #endif
23862 
23863  ierror = 0
23864  CALL mp_timeset(routinen, handle)
23865 
23866 #if defined(__parallel)
23867  CALL mpi_comm_rank(comm%handle, myrank, ierror)
23868  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
23869  CALL mpi_comm_size(comm%handle, nprocs, ierror)
23870  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
23871  IF (PRESENT(displ_in)) THEN
23872  displ = displ_in
23873  ELSE
23874  displ = 1
23875  END IF
23876  right = modulo(myrank + displ, nprocs)
23877  left = modulo(myrank - displ, nprocs)
23878  tag = 17
23879  msglen = SIZE(msg)
23880  CALL mpi_sendrecv_replace(msg, msglen, mpi_double_complex, right, tag, left, tag, &
23881  comm%handle, mpi_status_ignore, ierror)
23882  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
23883  CALL add_perf(perf_id=7, count=1, msg_size=msglen*(2*real_8_size))
23884 #else
23885  mark_used(msg)
23886  mark_used(comm)
23887  mark_used(displ_in)
23888 #endif
23889  CALL mp_timestop(handle)
23890 
23891  END SUBROUTINE mp_shift_zm
23892 
23893 ! **************************************************************************************************
23894 !> \brief Shift around the data in msg
23895 !> \param[in,out] msg Data to shift
23896 !> \param[in] comm message passing environment identifier
23897 !> \param[in] displ_in displacements (?)
23898 !> \par Example
23899 !> msg will be moved from rank to rank+displ_in (in a circular way)
23900 !> \par Limitations
23901 !> * displ_in will be 1 by default (others not tested)
23902 !> * the message array needs to be the same size on all processes
23903 ! **************************************************************************************************
23904  SUBROUTINE mp_shift_z (msg, comm, displ_in)
23905 
23906  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
23907  CLASS(mp_comm_type), INTENT(IN) :: comm
23908  INTEGER, INTENT(IN), OPTIONAL :: displ_in
23909 
23910  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_z'
23911 
23912  INTEGER :: handle, ierror
23913 #if defined(__parallel)
23914  INTEGER :: displ, left, &
23915  msglen, myrank, nprocs, &
23916  right, tag
23917 #endif
23918 
23919  ierror = 0
23920  CALL mp_timeset(routinen, handle)
23921 
23922 #if defined(__parallel)
23923  CALL mpi_comm_rank(comm%handle, myrank, ierror)
23924  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
23925  CALL mpi_comm_size(comm%handle, nprocs, ierror)
23926  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
23927  IF (PRESENT(displ_in)) THEN
23928  displ = displ_in
23929  ELSE
23930  displ = 1
23931  END IF
23932  right = modulo(myrank + displ, nprocs)
23933  left = modulo(myrank - displ, nprocs)
23934  tag = 19
23935  msglen = SIZE(msg)
23936  CALL mpi_sendrecv_replace(msg, msglen, mpi_double_complex, right, tag, left, &
23937  tag, comm%handle, mpi_status_ignore, ierror)
23938  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
23939  CALL add_perf(perf_id=7, count=1, msg_size=msglen*(2*real_8_size))
23940 #else
23941  mark_used(msg)
23942  mark_used(comm)
23943  mark_used(displ_in)
23944 #endif
23945  CALL mp_timestop(handle)
23946 
23947  END SUBROUTINE mp_shift_z
23948 
23949 ! **************************************************************************************************
23950 !> \brief All-to-all data exchange, rank-1 data of different sizes
23951 !> \param[in] sb Data to send
23952 !> \param[in] scount Data counts for data sent to other processes
23953 !> \param[in] sdispl Respective data offsets for data sent to process
23954 !> \param[in,out] rb Buffer into which to receive data
23955 !> \param[in] rcount Data counts for data received from other
23956 !> processes
23957 !> \param[in] rdispl Respective data offsets for data received from
23958 !> other processes
23959 !> \param[in] comm Message passing environment identifier
23960 !> \par MPI mapping
23961 !> mpi_alltoallv
23962 !> \par Array sizes
23963 !> The scount, rcount, and the sdispl and rdispl arrays have a
23964 !> size equal to the number of processes.
23965 !> \par Offsets
23966 !> Values in sdispl and rdispl start with 0.
23967 ! **************************************************************************************************
23968  SUBROUTINE mp_alltoall_z11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
23969 
23970  COMPLEX(kind=real_8), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
23971  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
23972  COMPLEX(kind=real_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
23973  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
23974  CLASS(mp_comm_type), INTENT(IN) :: comm
23975 
23976  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z11v'
23977 
23978  INTEGER :: handle
23979 #if defined(__parallel)
23980  INTEGER :: ierr, msglen
23981 #else
23982  INTEGER :: i
23983 #endif
23984 
23985  CALL mp_timeset(routinen, handle)
23986 
23987 #if defined(__parallel)
23988  CALL mpi_alltoallv(sb, scount, sdispl, mpi_double_complex, &
23989  rb, rcount, rdispl, mpi_double_complex, comm%handle, ierr)
23990  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
23991  msglen = sum(scount) + sum(rcount)
23992  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
23993 #else
23994  mark_used(comm)
23995  mark_used(scount)
23996  mark_used(sdispl)
23997  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
23998  DO i = 1, rcount(1)
23999  rb(rdispl(1) + i) = sb(sdispl(1) + i)
24000  END DO
24001 #endif
24002  CALL mp_timestop(handle)
24003 
24004  END SUBROUTINE mp_alltoall_z11v
24005 
24006 ! **************************************************************************************************
24007 !> \brief All-to-all data exchange, rank-2 data of different sizes
24008 !> \param sb ...
24009 !> \param scount ...
24010 !> \param sdispl ...
24011 !> \param rb ...
24012 !> \param rcount ...
24013 !> \param rdispl ...
24014 !> \param comm ...
24015 !> \par MPI mapping
24016 !> mpi_alltoallv
24017 !> \note see mp_alltoall_z11v
24018 ! **************************************************************************************************
24019  SUBROUTINE mp_alltoall_z22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
24020 
24021  COMPLEX(kind=real_8), DIMENSION(:, :), &
24022  INTENT(IN), CONTIGUOUS :: sb
24023  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
24024  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, &
24025  INTENT(INOUT) :: rb
24026  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
24027  CLASS(mp_comm_type), INTENT(IN) :: comm
24028 
24029  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z22v'
24030 
24031  INTEGER :: handle
24032 #if defined(__parallel)
24033  INTEGER :: ierr, msglen
24034 #endif
24035 
24036  CALL mp_timeset(routinen, handle)
24037 
24038 #if defined(__parallel)
24039  CALL mpi_alltoallv(sb, scount, sdispl, mpi_double_complex, &
24040  rb, rcount, rdispl, mpi_double_complex, comm%handle, ierr)
24041  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
24042  msglen = sum(scount) + sum(rcount)
24043  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*(2*real_8_size))
24044 #else
24045  mark_used(comm)
24046  mark_used(scount)
24047  mark_used(sdispl)
24048  mark_used(rcount)
24049  mark_used(rdispl)
24050  rb = sb
24051 #endif
24052  CALL mp_timestop(handle)
24053 
24054  END SUBROUTINE mp_alltoall_z22v
24055 
24056 ! **************************************************************************************************
24057 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
24058 !> \param[in] sb array with data to send
24059 !> \param[out] rb array into which data is received
24060 !> \param[in] count number of elements to send/receive (product of the
24061 !> extents of the first two dimensions)
24062 !> \param[in] comm Message passing environment identifier
24063 !> \par Index meaning
24064 !> \par The first two indices specify the data while the last index counts
24065 !> the processes
24066 !> \par Sizes of ranks
24067 !> All processes have the same data size.
24068 !> \par MPI mapping
24069 !> mpi_alltoall
24070 ! **************************************************************************************************
24071  SUBROUTINE mp_alltoall_z (sb, rb, count, comm)
24072 
24073  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
24074  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
24075  INTEGER, INTENT(IN) :: count
24076  CLASS(mp_comm_type), INTENT(IN) :: comm
24077 
24078  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z'
24079 
24080  INTEGER :: handle
24081 #if defined(__parallel)
24082  INTEGER :: ierr, msglen, np
24083 #endif
24084 
24085  CALL mp_timeset(routinen, handle)
24086 
24087 #if defined(__parallel)
24088  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24089  rb, count, mpi_double_complex, comm%handle, ierr)
24090  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24091  CALL mpi_comm_size(comm%handle, np, ierr)
24092  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24093  msglen = 2*count*np
24094  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24095 #else
24096  mark_used(count)
24097  mark_used(comm)
24098  rb = sb
24099 #endif
24100  CALL mp_timestop(handle)
24101 
24102  END SUBROUTINE mp_alltoall_z
24103 
24104 ! **************************************************************************************************
24105 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
24106 !> \param sb ...
24107 !> \param rb ...
24108 !> \param count ...
24109 !> \param commp ...
24110 !> \note see mp_alltoall_z
24111 ! **************************************************************************************************
24112  SUBROUTINE mp_alltoall_z22(sb, rb, count, comm)
24113 
24114  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
24115  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
24116  INTEGER, INTENT(IN) :: count
24117  CLASS(mp_comm_type), INTENT(IN) :: comm
24118 
24119  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z22'
24120 
24121  INTEGER :: handle
24122 #if defined(__parallel)
24123  INTEGER :: ierr, msglen, np
24124 #endif
24125 
24126  CALL mp_timeset(routinen, handle)
24127 
24128 #if defined(__parallel)
24129  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24130  rb, count, mpi_double_complex, comm%handle, ierr)
24131  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24132  CALL mpi_comm_size(comm%handle, np, ierr)
24133  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24134  msglen = 2*SIZE(sb)*np
24135  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24136 #else
24137  mark_used(count)
24138  mark_used(comm)
24139  rb = sb
24140 #endif
24141  CALL mp_timestop(handle)
24142 
24143  END SUBROUTINE mp_alltoall_z22
24144 
24145 ! **************************************************************************************************
24146 !> \brief All-to-all data exchange, rank-3 data with equal sizes
24147 !> \param sb ...
24148 !> \param rb ...
24149 !> \param count ...
24150 !> \param comm ...
24151 !> \note see mp_alltoall_z
24152 ! **************************************************************************************************
24153  SUBROUTINE mp_alltoall_z33(sb, rb, count, comm)
24154 
24155  COMPLEX(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
24156  COMPLEX(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
24157  INTEGER, INTENT(IN) :: count
24158  CLASS(mp_comm_type), INTENT(IN) :: comm
24159 
24160  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z33'
24161 
24162  INTEGER :: handle
24163 #if defined(__parallel)
24164  INTEGER :: ierr, msglen, np
24165 #endif
24166 
24167  CALL mp_timeset(routinen, handle)
24168 
24169 #if defined(__parallel)
24170  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24171  rb, count, mpi_double_complex, comm%handle, ierr)
24172  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24173  CALL mpi_comm_size(comm%handle, np, ierr)
24174  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24175  msglen = 2*count*np
24176  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24177 #else
24178  mark_used(count)
24179  mark_used(comm)
24180  rb = sb
24181 #endif
24182  CALL mp_timestop(handle)
24183 
24184  END SUBROUTINE mp_alltoall_z33
24185 
24186 ! **************************************************************************************************
24187 !> \brief All-to-all data exchange, rank 4 data, equal sizes
24188 !> \param sb ...
24189 !> \param rb ...
24190 !> \param count ...
24191 !> \param comm ...
24192 !> \note see mp_alltoall_z
24193 ! **************************************************************************************************
24194  SUBROUTINE mp_alltoall_z44(sb, rb, count, comm)
24195 
24196  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
24197  INTENT(IN) :: sb
24198  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
24199  INTENT(OUT) :: rb
24200  INTEGER, INTENT(IN) :: count
24201  CLASS(mp_comm_type), INTENT(IN) :: comm
24202 
24203  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z44'
24204 
24205  INTEGER :: handle
24206 #if defined(__parallel)
24207  INTEGER :: ierr, msglen, np
24208 #endif
24209 
24210  CALL mp_timeset(routinen, handle)
24211 
24212 #if defined(__parallel)
24213  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24214  rb, count, mpi_double_complex, comm%handle, ierr)
24215  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24216  CALL mpi_comm_size(comm%handle, np, ierr)
24217  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24218  msglen = 2*count*np
24219  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24220 #else
24221  mark_used(count)
24222  mark_used(comm)
24223  rb = sb
24224 #endif
24225  CALL mp_timestop(handle)
24226 
24227  END SUBROUTINE mp_alltoall_z44
24228 
24229 ! **************************************************************************************************
24230 !> \brief All-to-all data exchange, rank 5 data, equal sizes
24231 !> \param sb ...
24232 !> \param rb ...
24233 !> \param count ...
24234 !> \param comm ...
24235 !> \note see mp_alltoall_z
24236 ! **************************************************************************************************
24237  SUBROUTINE mp_alltoall_z55(sb, rb, count, comm)
24238 
24239  COMPLEX(kind=real_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
24240  INTENT(IN) :: sb
24241  COMPLEX(kind=real_8), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
24242  INTENT(OUT) :: rb
24243  INTEGER, INTENT(IN) :: count
24244  CLASS(mp_comm_type), INTENT(IN) :: comm
24245 
24246  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z55'
24247 
24248  INTEGER :: handle
24249 #if defined(__parallel)
24250  INTEGER :: ierr, msglen, np
24251 #endif
24252 
24253  CALL mp_timeset(routinen, handle)
24254 
24255 #if defined(__parallel)
24256  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24257  rb, count, mpi_double_complex, comm%handle, ierr)
24258  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24259  CALL mpi_comm_size(comm%handle, np, ierr)
24260  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24261  msglen = 2*count*np
24262  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24263 #else
24264  mark_used(count)
24265  mark_used(comm)
24266  rb = sb
24267 #endif
24268  CALL mp_timestop(handle)
24269 
24270  END SUBROUTINE mp_alltoall_z55
24271 
24272 ! **************************************************************************************************
24273 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
24274 !> \param sb ...
24275 !> \param rb ...
24276 !> \param count ...
24277 !> \param comm ...
24278 !> \note see mp_alltoall_z
24279 !> \note User must ensure size consistency.
24280 ! **************************************************************************************************
24281  SUBROUTINE mp_alltoall_z45(sb, rb, count, comm)
24282 
24283  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
24284  INTENT(IN) :: sb
24285  COMPLEX(kind=real_8), &
24286  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
24287  INTEGER, INTENT(IN) :: count
24288  CLASS(mp_comm_type), INTENT(IN) :: comm
24289 
24290  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z45'
24291 
24292  INTEGER :: handle
24293 #if defined(__parallel)
24294  INTEGER :: ierr, msglen, np
24295 #endif
24296 
24297  CALL mp_timeset(routinen, handle)
24298 
24299 #if defined(__parallel)
24300  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24301  rb, count, mpi_double_complex, comm%handle, ierr)
24302  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24303  CALL mpi_comm_size(comm%handle, np, ierr)
24304  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24305  msglen = 2*count*np
24306  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24307 #else
24308  mark_used(count)
24309  mark_used(comm)
24310  rb = reshape(sb, shape(rb))
24311 #endif
24312  CALL mp_timestop(handle)
24313 
24314  END SUBROUTINE mp_alltoall_z45
24315 
24316 ! **************************************************************************************************
24317 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
24318 !> \param sb ...
24319 !> \param rb ...
24320 !> \param count ...
24321 !> \param comm ...
24322 !> \note see mp_alltoall_z
24323 !> \note User must ensure size consistency.
24324 ! **************************************************************************************************
24325  SUBROUTINE mp_alltoall_z34(sb, rb, count, comm)
24326 
24327  COMPLEX(kind=real_8), DIMENSION(:, :, :), CONTIGUOUS, &
24328  INTENT(IN) :: sb
24329  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
24330  INTENT(OUT) :: rb
24331  INTEGER, INTENT(IN) :: count
24332  CLASS(mp_comm_type), INTENT(IN) :: comm
24333 
24334  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z34'
24335 
24336  INTEGER :: handle
24337 #if defined(__parallel)
24338  INTEGER :: ierr, msglen, np
24339 #endif
24340 
24341  CALL mp_timeset(routinen, handle)
24342 
24343 #if defined(__parallel)
24344  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24345  rb, count, mpi_double_complex, comm%handle, ierr)
24346  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24347  CALL mpi_comm_size(comm%handle, np, ierr)
24348  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24349  msglen = 2*count*np
24350  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24351 #else
24352  mark_used(count)
24353  mark_used(comm)
24354  rb = reshape(sb, shape(rb))
24355 #endif
24356  CALL mp_timestop(handle)
24357 
24358  END SUBROUTINE mp_alltoall_z34
24359 
24360 ! **************************************************************************************************
24361 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
24362 !> \param sb ...
24363 !> \param rb ...
24364 !> \param count ...
24365 !> \param comm ...
24366 !> \note see mp_alltoall_z
24367 !> \note User must ensure size consistency.
24368 ! **************************************************************************************************
24369  SUBROUTINE mp_alltoall_z54(sb, rb, count, comm)
24370 
24371  COMPLEX(kind=real_8), &
24372  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
24373  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), CONTIGUOUS, &
24374  INTENT(OUT) :: rb
24375  INTEGER, INTENT(IN) :: count
24376  CLASS(mp_comm_type), INTENT(IN) :: comm
24377 
24378  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_z54'
24379 
24380  INTEGER :: handle
24381 #if defined(__parallel)
24382  INTEGER :: ierr, msglen, np
24383 #endif
24384 
24385  CALL mp_timeset(routinen, handle)
24386 
24387 #if defined(__parallel)
24388  CALL mpi_alltoall(sb, count, mpi_double_complex, &
24389  rb, count, mpi_double_complex, comm%handle, ierr)
24390  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
24391  CALL mpi_comm_size(comm%handle, np, ierr)
24392  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
24393  msglen = 2*count*np
24394  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_8_size))
24395 #else
24396  mark_used(count)
24397  mark_used(comm)
24398  rb = reshape(sb, shape(rb))
24399 #endif
24400  CALL mp_timestop(handle)
24401 
24402  END SUBROUTINE mp_alltoall_z54
24403 
24404 ! **************************************************************************************************
24405 !> \brief Send one datum to another process
24406 !> \param[in] msg Scalar to send
24407 !> \param[in] dest Destination process
24408 !> \param[in] tag Transfer identifier
24409 !> \param[in] comm Message passing environment identifier
24410 !> \par MPI mapping
24411 !> mpi_send
24412 ! **************************************************************************************************
24413  SUBROUTINE mp_send_z (msg, dest, tag, comm)
24414  COMPLEX(kind=real_8), INTENT(IN) :: msg
24415  INTEGER, INTENT(IN) :: dest, tag
24416  CLASS(mp_comm_type), INTENT(IN) :: comm
24417 
24418  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_z'
24419 
24420  INTEGER :: handle
24421 #if defined(__parallel)
24422  INTEGER :: ierr, msglen
24423 #endif
24424 
24425  CALL mp_timeset(routinen, handle)
24426 
24427 #if defined(__parallel)
24428  msglen = 1
24429  CALL mpi_send(msg, msglen, mpi_double_complex, dest, tag, comm%handle, ierr)
24430  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
24431  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_8_size))
24432 #else
24433  mark_used(msg)
24434  mark_used(dest)
24435  mark_used(tag)
24436  mark_used(comm)
24437  ! only defined in parallel
24438  cpabort("not in parallel mode")
24439 #endif
24440  CALL mp_timestop(handle)
24441  END SUBROUTINE mp_send_z
24442 
24443 ! **************************************************************************************************
24444 !> \brief Send rank-1 data to another process
24445 !> \param[in] msg Rank-1 data to send
24446 !> \param dest ...
24447 !> \param tag ...
24448 !> \param comm ...
24449 !> \note see mp_send_z
24450 ! **************************************************************************************************
24451  SUBROUTINE mp_send_zv(msg, dest, tag, comm)
24452  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
24453  INTEGER, INTENT(IN) :: dest, tag
24454  CLASS(mp_comm_type), INTENT(IN) :: comm
24455 
24456  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_zv'
24457 
24458  INTEGER :: handle
24459 #if defined(__parallel)
24460  INTEGER :: ierr, msglen
24461 #endif
24462 
24463  CALL mp_timeset(routinen, handle)
24464 
24465 #if defined(__parallel)
24466  msglen = SIZE(msg)
24467  CALL mpi_send(msg, msglen, mpi_double_complex, dest, tag, comm%handle, ierr)
24468  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
24469  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_8_size))
24470 #else
24471  mark_used(msg)
24472  mark_used(dest)
24473  mark_used(tag)
24474  mark_used(comm)
24475  ! only defined in parallel
24476  cpabort("not in parallel mode")
24477 #endif
24478  CALL mp_timestop(handle)
24479  END SUBROUTINE mp_send_zv
24480 
24481 ! **************************************************************************************************
24482 !> \brief Send rank-2 data to another process
24483 !> \param[in] msg Rank-2 data to send
24484 !> \param dest ...
24485 !> \param tag ...
24486 !> \param comm ...
24487 !> \note see mp_send_z
24488 ! **************************************************************************************************
24489  SUBROUTINE mp_send_zm2(msg, dest, tag, comm)
24490  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
24491  INTEGER, INTENT(IN) :: dest, tag
24492  CLASS(mp_comm_type), INTENT(IN) :: comm
24493 
24494  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_zm2'
24495 
24496  INTEGER :: handle
24497 #if defined(__parallel)
24498  INTEGER :: ierr, msglen
24499 #endif
24500 
24501  CALL mp_timeset(routinen, handle)
24502 
24503 #if defined(__parallel)
24504  msglen = SIZE(msg)
24505  CALL mpi_send(msg, msglen, mpi_double_complex, dest, tag, comm%handle, ierr)
24506  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
24507  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_8_size))
24508 #else
24509  mark_used(msg)
24510  mark_used(dest)
24511  mark_used(tag)
24512  mark_used(comm)
24513  ! only defined in parallel
24514  cpabort("not in parallel mode")
24515 #endif
24516  CALL mp_timestop(handle)
24517  END SUBROUTINE mp_send_zm2
24518 
24519 ! **************************************************************************************************
24520 !> \brief Send rank-3 data to another process
24521 !> \param[in] msg Rank-3 data to send
24522 !> \param dest ...
24523 !> \param tag ...
24524 !> \param comm ...
24525 !> \note see mp_send_z
24526 ! **************************************************************************************************
24527  SUBROUTINE mp_send_zm3(msg, dest, tag, comm)
24528  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
24529  INTEGER, INTENT(IN) :: dest, tag
24530  CLASS(mp_comm_type), INTENT(IN) :: comm
24531 
24532  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
24533 
24534  INTEGER :: handle
24535 #if defined(__parallel)
24536  INTEGER :: ierr, msglen
24537 #endif
24538 
24539  CALL mp_timeset(routinen, handle)
24540 
24541 #if defined(__parallel)
24542  msglen = SIZE(msg)
24543  CALL mpi_send(msg, msglen, mpi_double_complex, dest, tag, comm%handle, ierr)
24544  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
24545  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_8_size))
24546 #else
24547  mark_used(msg)
24548  mark_used(dest)
24549  mark_used(tag)
24550  mark_used(comm)
24551  ! only defined in parallel
24552  cpabort("not in parallel mode")
24553 #endif
24554  CALL mp_timestop(handle)
24555  END SUBROUTINE mp_send_zm3
24556 
24557 ! **************************************************************************************************
24558 !> \brief Receive one datum from another process
24559 !> \param[in,out] msg Place received data into this variable
24560 !> \param[in,out] source Process to receive from
24561 !> \param[in,out] tag Transfer identifier
24562 !> \param[in] comm Message passing environment identifier
24563 !> \par MPI mapping
24564 !> mpi_send
24565 ! **************************************************************************************************
24566  SUBROUTINE mp_recv_z (msg, source, tag, comm)
24567  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
24568  INTEGER, INTENT(INOUT) :: source, tag
24569  CLASS(mp_comm_type), INTENT(IN) :: comm
24570 
24571  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_z'
24572 
24573  INTEGER :: handle
24574 #if defined(__parallel)
24575  INTEGER :: ierr, msglen
24576  mpi_status_type :: status
24577 #endif
24578 
24579  CALL mp_timeset(routinen, handle)
24580 
24581 #if defined(__parallel)
24582  msglen = 1
24583  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
24584  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
24585  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24586  ELSE
24587  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, status, ierr)
24588  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24589  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_8_size))
24590  source = status mpi_status_extract(mpi_source)
24591  tag = status mpi_status_extract(mpi_tag)
24592  END IF
24593 #else
24594  mark_used(msg)
24595  mark_used(source)
24596  mark_used(tag)
24597  mark_used(comm)
24598  ! only defined in parallel
24599  cpabort("not in parallel mode")
24600 #endif
24601  CALL mp_timestop(handle)
24602  END SUBROUTINE mp_recv_z
24603 
24604 ! **************************************************************************************************
24605 !> \brief Receive rank-1 data from another process
24606 !> \param[in,out] msg Place received data into this rank-1 array
24607 !> \param source ...
24608 !> \param tag ...
24609 !> \param comm ...
24610 !> \note see mp_recv_z
24611 ! **************************************************************************************************
24612  SUBROUTINE mp_recv_zv(msg, source, tag, comm)
24613  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
24614  INTEGER, INTENT(INOUT) :: source, tag
24615  CLASS(mp_comm_type), INTENT(IN) :: comm
24616 
24617  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_zv'
24618 
24619  INTEGER :: handle
24620 #if defined(__parallel)
24621  INTEGER :: ierr, msglen
24622  mpi_status_type :: status
24623 #endif
24624 
24625  CALL mp_timeset(routinen, handle)
24626 
24627 #if defined(__parallel)
24628  msglen = SIZE(msg)
24629  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
24630  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
24631  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24632  ELSE
24633  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, status, ierr)
24634  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24635  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_8_size))
24636  source = status mpi_status_extract(mpi_source)
24637  tag = status mpi_status_extract(mpi_tag)
24638  END IF
24639 #else
24640  mark_used(msg)
24641  mark_used(source)
24642  mark_used(tag)
24643  mark_used(comm)
24644  ! only defined in parallel
24645  cpabort("not in parallel mode")
24646 #endif
24647  CALL mp_timestop(handle)
24648  END SUBROUTINE mp_recv_zv
24649 
24650 ! **************************************************************************************************
24651 !> \brief Receive rank-2 data from another process
24652 !> \param[in,out] msg Place received data into this rank-2 array
24653 !> \param source ...
24654 !> \param tag ...
24655 !> \param comm ...
24656 !> \note see mp_recv_z
24657 ! **************************************************************************************************
24658  SUBROUTINE mp_recv_zm2(msg, source, tag, comm)
24659  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
24660  INTEGER, INTENT(INOUT) :: source, tag
24661  CLASS(mp_comm_type), INTENT(IN) :: comm
24662 
24663  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_zm2'
24664 
24665  INTEGER :: handle
24666 #if defined(__parallel)
24667  INTEGER :: ierr, msglen
24668  mpi_status_type :: status
24669 #endif
24670 
24671  CALL mp_timeset(routinen, handle)
24672 
24673 #if defined(__parallel)
24674  msglen = SIZE(msg)
24675  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
24676  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
24677  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24678  ELSE
24679  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, status, ierr)
24680  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24681  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_8_size))
24682  source = status mpi_status_extract(mpi_source)
24683  tag = status mpi_status_extract(mpi_tag)
24684  END IF
24685 #else
24686  mark_used(msg)
24687  mark_used(source)
24688  mark_used(tag)
24689  mark_used(comm)
24690  ! only defined in parallel
24691  cpabort("not in parallel mode")
24692 #endif
24693  CALL mp_timestop(handle)
24694  END SUBROUTINE mp_recv_zm2
24695 
24696 ! **************************************************************************************************
24697 !> \brief Receive rank-3 data from another process
24698 !> \param[in,out] msg Place received data into this rank-3 array
24699 !> \param source ...
24700 !> \param tag ...
24701 !> \param comm ...
24702 !> \note see mp_recv_z
24703 ! **************************************************************************************************
24704  SUBROUTINE mp_recv_zm3(msg, source, tag, comm)
24705  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
24706  INTEGER, INTENT(INOUT) :: source, tag
24707  CLASS(mp_comm_type), INTENT(IN) :: comm
24708 
24709  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_zm3'
24710 
24711  INTEGER :: handle
24712 #if defined(__parallel)
24713  INTEGER :: ierr, msglen
24714  mpi_status_type :: status
24715 #endif
24716 
24717  CALL mp_timeset(routinen, handle)
24718 
24719 #if defined(__parallel)
24720  msglen = SIZE(msg)
24721  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
24722  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
24723  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24724  ELSE
24725  CALL mpi_recv(msg, msglen, mpi_double_complex, source, tag, comm%handle, status, ierr)
24726  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
24727  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_8_size))
24728  source = status mpi_status_extract(mpi_source)
24729  tag = status mpi_status_extract(mpi_tag)
24730  END IF
24731 #else
24732  mark_used(msg)
24733  mark_used(source)
24734  mark_used(tag)
24735  mark_used(comm)
24736  ! only defined in parallel
24737  cpabort("not in parallel mode")
24738 #endif
24739  CALL mp_timestop(handle)
24740  END SUBROUTINE mp_recv_zm3
24741 
24742 ! **************************************************************************************************
24743 !> \brief Broadcasts a datum to all processes.
24744 !> \param[in] msg Datum to broadcast
24745 !> \param[in] source Processes which broadcasts
24746 !> \param[in] comm Message passing environment identifier
24747 !> \par MPI mapping
24748 !> mpi_bcast
24749 ! **************************************************************************************************
24750  SUBROUTINE mp_bcast_z (msg, source, comm)
24751  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
24752  INTEGER, INTENT(IN) :: source
24753  CLASS(mp_comm_type), INTENT(IN) :: comm
24754 
24755  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_z'
24756 
24757  INTEGER :: handle
24758 #if defined(__parallel)
24759  INTEGER :: ierr, msglen
24760 #endif
24761 
24762  CALL mp_timeset(routinen, handle)
24763 
24764 #if defined(__parallel)
24765  msglen = 1
24766  CALL mpi_bcast(msg, msglen, mpi_double_complex, source, comm%handle, ierr)
24767  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
24768  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
24769 #else
24770  mark_used(msg)
24771  mark_used(source)
24772  mark_used(comm)
24773 #endif
24774  CALL mp_timestop(handle)
24775  END SUBROUTINE mp_bcast_z
24776 
24777 ! **************************************************************************************************
24778 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
24779 !> \param[in] msg Datum to broadcast
24780 !> \param[in] comm Message passing environment identifier
24781 !> \par MPI mapping
24782 !> mpi_bcast
24783 ! **************************************************************************************************
24784  SUBROUTINE mp_bcast_z_src(msg, comm)
24785  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
24786  CLASS(mp_comm_type), INTENT(IN) :: comm
24787 
24788  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_z_src'
24789 
24790  INTEGER :: handle
24791 #if defined(__parallel)
24792  INTEGER :: ierr, msglen
24793 #endif
24794 
24795  CALL mp_timeset(routinen, handle)
24796 
24797 #if defined(__parallel)
24798  msglen = 1
24799  CALL mpi_bcast(msg, msglen, mpi_double_complex, comm%source, comm%handle, ierr)
24800  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
24801  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
24802 #else
24803  mark_used(msg)
24804  mark_used(comm)
24805 #endif
24806  CALL mp_timestop(handle)
24807  END SUBROUTINE mp_bcast_z_src
24808 
24809 ! **************************************************************************************************
24810 !> \brief Broadcasts a datum to all processes.
24811 !> \param[in] msg Datum to broadcast
24812 !> \param[in] source Processes which broadcasts
24813 !> \param[in] comm Message passing environment identifier
24814 !> \par MPI mapping
24815 !> mpi_bcast
24816 ! **************************************************************************************************
24817  SUBROUTINE mp_ibcast_z (msg, source, comm, request)
24818  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
24819  INTEGER, INTENT(IN) :: source
24820  CLASS(mp_comm_type), INTENT(IN) :: comm
24821  TYPE(mp_request_type), INTENT(OUT) :: request
24822 
24823  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_z'
24824 
24825  INTEGER :: handle
24826 #if defined(__parallel)
24827  INTEGER :: ierr, msglen
24828 #endif
24829 
24830  CALL mp_timeset(routinen, handle)
24831 
24832 #if defined(__parallel)
24833  msglen = 1
24834  CALL mpi_ibcast(msg, msglen, mpi_double_complex, source, comm%handle, request%handle, ierr)
24835  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
24836  CALL add_perf(perf_id=22, count=1, msg_size=msglen*(2*real_8_size))
24837 #else
24838  mark_used(msg)
24839  mark_used(source)
24840  mark_used(comm)
24841  request = mp_request_null
24842 #endif
24843  CALL mp_timestop(handle)
24844  END SUBROUTINE mp_ibcast_z
24845 
24846 ! **************************************************************************************************
24847 !> \brief Broadcasts rank-1 data to all processes
24848 !> \param[in] msg Data to broadcast
24849 !> \param source ...
24850 !> \param comm ...
24851 !> \note see mp_bcast_z1
24852 ! **************************************************************************************************
24853  SUBROUTINE mp_bcast_zv(msg, source, comm)
24854  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
24855  INTEGER, INTENT(IN) :: source
24856  CLASS(mp_comm_type), INTENT(IN) :: comm
24857 
24858  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_zv'
24859 
24860  INTEGER :: handle
24861 #if defined(__parallel)
24862  INTEGER :: ierr, msglen
24863 #endif
24864 
24865  CALL mp_timeset(routinen, handle)
24866 
24867 #if defined(__parallel)
24868  msglen = SIZE(msg)
24869  CALL mpi_bcast(msg, msglen, mpi_double_complex, source, comm%handle, ierr)
24870  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
24871  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
24872 #else
24873  mark_used(msg)
24874  mark_used(source)
24875  mark_used(comm)
24876 #endif
24877  CALL mp_timestop(handle)
24878  END SUBROUTINE mp_bcast_zv
24879 
24880 ! **************************************************************************************************
24881 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
24882 !> \param[in] msg Data to broadcast
24883 !> \param comm ...
24884 !> \note see mp_bcast_z1
24885 ! **************************************************************************************************
24886  SUBROUTINE mp_bcast_zv_src(msg, comm)
24887  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
24888  CLASS(mp_comm_type), INTENT(IN) :: comm
24889 
24890  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_zv_src'
24891 
24892  INTEGER :: handle
24893 #if defined(__parallel)
24894  INTEGER :: ierr, msglen
24895 #endif
24896 
24897  CALL mp_timeset(routinen, handle)
24898 
24899 #if defined(__parallel)
24900  msglen = SIZE(msg)
24901  CALL mpi_bcast(msg, msglen, mpi_double_complex, comm%source, comm%handle, ierr)
24902  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
24903  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
24904 #else
24905  mark_used(msg)
24906  mark_used(comm)
24907 #endif
24908  CALL mp_timestop(handle)
24909  END SUBROUTINE mp_bcast_zv_src
24910 
24911 ! **************************************************************************************************
24912 !> \brief Broadcasts rank-1 data to all processes
24913 !> \param[in] msg Data to broadcast
24914 !> \param source ...
24915 !> \param comm ...
24916 !> \note see mp_bcast_z1
24917 ! **************************************************************************************************
24918  SUBROUTINE mp_ibcast_zv(msg, source, comm, request)
24919  COMPLEX(kind=real_8), INTENT(INOUT) :: msg(:)
24920  INTEGER, INTENT(IN) :: source
24921  CLASS(mp_comm_type), INTENT(IN) :: comm
24922  TYPE(mp_request_type) :: request
24923 
24924  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_zv'
24925 
24926  INTEGER :: handle
24927 #if defined(__parallel)
24928  INTEGER :: ierr, msglen
24929 #endif
24930 
24931  CALL mp_timeset(routinen, handle)
24932 
24933 #if defined(__parallel)
24934 #if !defined(__GNUC__) || __GNUC__ >= 9
24935  cpassert(is_contiguous(msg))
24936 #endif
24937  msglen = SIZE(msg)
24938  CALL mpi_ibcast(msg, msglen, mpi_double_complex, source, comm%handle, request%handle, ierr)
24939  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
24940  CALL add_perf(perf_id=22, count=1, msg_size=msglen*(2*real_8_size))
24941 #else
24942  mark_used(msg)
24943  mark_used(source)
24944  mark_used(comm)
24945  request = mp_request_null
24946 #endif
24947  CALL mp_timestop(handle)
24948  END SUBROUTINE mp_ibcast_zv
24949 
24950 ! **************************************************************************************************
24951 !> \brief Broadcasts rank-2 data to all processes
24952 !> \param[in] msg Data to broadcast
24953 !> \param source ...
24954 !> \param comm ...
24955 !> \note see mp_bcast_z1
24956 ! **************************************************************************************************
24957  SUBROUTINE mp_bcast_zm(msg, source, comm)
24958  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
24959  INTEGER, INTENT(IN) :: source
24960  CLASS(mp_comm_type), INTENT(IN) :: comm
24961 
24962  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_zm'
24963 
24964  INTEGER :: handle
24965 #if defined(__parallel)
24966  INTEGER :: ierr, msglen
24967 #endif
24968 
24969  CALL mp_timeset(routinen, handle)
24970 
24971 #if defined(__parallel)
24972  msglen = SIZE(msg)
24973  CALL mpi_bcast(msg, msglen, mpi_double_complex, source, comm%handle, ierr)
24974  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
24975  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
24976 #else
24977  mark_used(msg)
24978  mark_used(source)
24979  mark_used(comm)
24980 #endif
24981  CALL mp_timestop(handle)
24982  END SUBROUTINE mp_bcast_zm
24983 
24984 ! **************************************************************************************************
24985 !> \brief Broadcasts rank-2 data to all processes
24986 !> \param[in] msg Data to broadcast
24987 !> \param source ...
24988 !> \param comm ...
24989 !> \note see mp_bcast_z1
24990 ! **************************************************************************************************
24991  SUBROUTINE mp_bcast_zm_src(msg, comm)
24992  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
24993  CLASS(mp_comm_type), INTENT(IN) :: comm
24994 
24995  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_zm_src'
24996 
24997  INTEGER :: handle
24998 #if defined(__parallel)
24999  INTEGER :: ierr, msglen
25000 #endif
25001 
25002  CALL mp_timeset(routinen, handle)
25003 
25004 #if defined(__parallel)
25005  msglen = SIZE(msg)
25006  CALL mpi_bcast(msg, msglen, mpi_double_complex, comm%source, comm%handle, ierr)
25007  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
25008  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
25009 #else
25010  mark_used(msg)
25011  mark_used(comm)
25012 #endif
25013  CALL mp_timestop(handle)
25014  END SUBROUTINE mp_bcast_zm_src
25015 
25016 ! **************************************************************************************************
25017 !> \brief Broadcasts rank-3 data to all processes
25018 !> \param[in] msg Data to broadcast
25019 !> \param source ...
25020 !> \param comm ...
25021 !> \note see mp_bcast_z1
25022 ! **************************************************************************************************
25023  SUBROUTINE mp_bcast_z3(msg, source, comm)
25024  COMPLEX(kind=real_8), CONTIGUOUS :: msg(:, :, :)
25025  INTEGER, INTENT(IN) :: source
25026  CLASS(mp_comm_type), INTENT(IN) :: comm
25027 
25028  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_z3'
25029 
25030  INTEGER :: handle
25031 #if defined(__parallel)
25032  INTEGER :: ierr, msglen
25033 #endif
25034 
25035  CALL mp_timeset(routinen, handle)
25036 
25037 #if defined(__parallel)
25038  msglen = SIZE(msg)
25039  CALL mpi_bcast(msg, msglen, mpi_double_complex, source, comm%handle, ierr)
25040  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
25041  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
25042 #else
25043  mark_used(msg)
25044  mark_used(source)
25045  mark_used(comm)
25046 #endif
25047  CALL mp_timestop(handle)
25048  END SUBROUTINE mp_bcast_z3
25049 
25050 ! **************************************************************************************************
25051 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
25052 !> \param[in] msg Data to broadcast
25053 !> \param source ...
25054 !> \param comm ...
25055 !> \note see mp_bcast_z1
25056 ! **************************************************************************************************
25057  SUBROUTINE mp_bcast_z3_src(msg, comm)
25058  COMPLEX(kind=real_8), CONTIGUOUS :: msg(:, :, :)
25059  CLASS(mp_comm_type), INTENT(IN) :: comm
25060 
25061  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_z3_src'
25062 
25063  INTEGER :: handle
25064 #if defined(__parallel)
25065  INTEGER :: ierr, msglen
25066 #endif
25067 
25068  CALL mp_timeset(routinen, handle)
25069 
25070 #if defined(__parallel)
25071  msglen = SIZE(msg)
25072  CALL mpi_bcast(msg, msglen, mpi_double_complex, comm%source, comm%handle, ierr)
25073  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
25074  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_8_size))
25075 #else
25076  mark_used(msg)
25077  mark_used(comm)
25078 #endif
25079  CALL mp_timestop(handle)
25080  END SUBROUTINE mp_bcast_z3_src
25081 
25082 ! **************************************************************************************************
25083 !> \brief Sums a datum from all processes with result left on all processes.
25084 !> \param[in,out] msg Datum to sum (input) and result (output)
25085 !> \param[in] comm Message passing environment identifier
25086 !> \par MPI mapping
25087 !> mpi_allreduce
25088 ! **************************************************************************************************
25089  SUBROUTINE mp_sum_z (msg, comm)
25090  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25091  CLASS(mp_comm_type), INTENT(IN) :: comm
25092 
25093  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_z'
25094 
25095  INTEGER :: handle
25096 #if defined(__parallel)
25097  INTEGER :: ierr, msglen
25098 #endif
25099 
25100  CALL mp_timeset(routinen, handle)
25101 
25102 #if defined(__parallel)
25103  msglen = 1
25104  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25105  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25106  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25107 #else
25108  mark_used(msg)
25109  mark_used(comm)
25110 #endif
25111  CALL mp_timestop(handle)
25112  END SUBROUTINE mp_sum_z
25113 
25114 ! **************************************************************************************************
25115 !> \brief Element-wise sum of a rank-1 array on all processes.
25116 !> \param[in,out] msg Vector to sum and result
25117 !> \param comm ...
25118 !> \note see mp_sum_z
25119 ! **************************************************************************************************
25120  SUBROUTINE mp_sum_zv(msg, comm)
25121  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
25122  CLASS(mp_comm_type), INTENT(IN) :: comm
25123 
25124  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_zv'
25125 
25126  INTEGER :: handle
25127 #if defined(__parallel)
25128  INTEGER :: ierr, msglen
25129 #endif
25130 
25131  CALL mp_timeset(routinen, handle)
25132 
25133 #if defined(__parallel)
25134  msglen = SIZE(msg)
25135  IF (msglen > 0) THEN
25136  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25137  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25138  END IF
25139  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25140 #else
25141  mark_used(msg)
25142  mark_used(comm)
25143 #endif
25144  CALL mp_timestop(handle)
25145  END SUBROUTINE mp_sum_zv
25146 
25147 ! **************************************************************************************************
25148 !> \brief Element-wise sum of a rank-1 array on all processes.
25149 !> \param[in,out] msg Vector to sum and result
25150 !> \param comm ...
25151 !> \note see mp_sum_z
25152 ! **************************************************************************************************
25153  SUBROUTINE mp_isum_zv(msg, comm, request)
25154  COMPLEX(kind=real_8), INTENT(INOUT) :: msg(:)
25155  CLASS(mp_comm_type), INTENT(IN) :: comm
25156  TYPE(mp_request_type), INTENT(OUT) :: request
25157 
25158  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_zv'
25159 
25160  INTEGER :: handle
25161 #if defined(__parallel)
25162  INTEGER :: ierr, msglen
25163 #endif
25164 
25165  CALL mp_timeset(routinen, handle)
25166 
25167 #if defined(__parallel)
25168 #if !defined(__GNUC__) || __GNUC__ >= 9
25169  cpassert(is_contiguous(msg))
25170 #endif
25171  msglen = SIZE(msg)
25172  IF (msglen > 0) THEN
25173  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_sum, comm%handle, request%handle, ierr)
25174  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
25175  ELSE
25176  request = mp_request_null
25177  END IF
25178  CALL add_perf(perf_id=23, count=1, msg_size=msglen*(2*real_8_size))
25179 #else
25180  mark_used(msg)
25181  mark_used(comm)
25182  request = mp_request_null
25183 #endif
25184  CALL mp_timestop(handle)
25185  END SUBROUTINE mp_isum_zv
25186 
25187 ! **************************************************************************************************
25188 !> \brief Element-wise sum of a rank-2 array on all processes.
25189 !> \param[in] msg Matrix to sum and result
25190 !> \param comm ...
25191 !> \note see mp_sum_z
25192 ! **************************************************************************************************
25193  SUBROUTINE mp_sum_zm(msg, comm)
25194  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
25195  CLASS(mp_comm_type), INTENT(IN) :: comm
25196 
25197  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_zm'
25198 
25199  INTEGER :: handle
25200 #if defined(__parallel)
25201  INTEGER, PARAMETER :: max_msg = 2**25
25202  INTEGER :: ierr, m1, msglen, step, msglensum
25203 #endif
25204 
25205  CALL mp_timeset(routinen, handle)
25206 
25207 #if defined(__parallel)
25208  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
25209  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
25210  msglensum = 0
25211  DO m1 = lbound(msg, 2), ubound(msg, 2), step
25212  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
25213  msglensum = msglensum + msglen
25214  IF (msglen > 0) THEN
25215  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25216  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25217  END IF
25218  END DO
25219  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*(2*real_8_size))
25220 #else
25221  mark_used(msg)
25222  mark_used(comm)
25223 #endif
25224  CALL mp_timestop(handle)
25225  END SUBROUTINE mp_sum_zm
25226 
25227 ! **************************************************************************************************
25228 !> \brief Element-wise sum of a rank-3 array on all processes.
25229 !> \param[in] msg Array to sum and result
25230 !> \param comm ...
25231 !> \note see mp_sum_z
25232 ! **************************************************************************************************
25233  SUBROUTINE mp_sum_zm3(msg, comm)
25234  COMPLEX(kind=real_8), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
25235  CLASS(mp_comm_type), INTENT(IN) :: comm
25236 
25237  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_zm3'
25238 
25239  INTEGER :: handle
25240 #if defined(__parallel)
25241  INTEGER :: ierr, msglen
25242 #endif
25243 
25244  CALL mp_timeset(routinen, handle)
25245 
25246 #if defined(__parallel)
25247  msglen = SIZE(msg)
25248  IF (msglen > 0) THEN
25249  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25250  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25251  END IF
25252  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25253 #else
25254  mark_used(msg)
25255  mark_used(comm)
25256 #endif
25257  CALL mp_timestop(handle)
25258  END SUBROUTINE mp_sum_zm3
25259 
25260 ! **************************************************************************************************
25261 !> \brief Element-wise sum of a rank-4 array on all processes.
25262 !> \param[in] msg Array to sum and result
25263 !> \param comm ...
25264 !> \note see mp_sum_z
25265 ! **************************************************************************************************
25266  SUBROUTINE mp_sum_zm4(msg, comm)
25267  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
25268  CLASS(mp_comm_type), INTENT(IN) :: comm
25269 
25270  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_zm4'
25271 
25272  INTEGER :: handle
25273 #if defined(__parallel)
25274  INTEGER :: ierr, msglen
25275 #endif
25276 
25277  CALL mp_timeset(routinen, handle)
25278 
25279 #if defined(__parallel)
25280  msglen = SIZE(msg)
25281  IF (msglen > 0) THEN
25282  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25283  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25284  END IF
25285  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25286 #else
25287  mark_used(msg)
25288  mark_used(comm)
25289 #endif
25290  CALL mp_timestop(handle)
25291  END SUBROUTINE mp_sum_zm4
25292 
25293 ! **************************************************************************************************
25294 !> \brief Element-wise sum of data from all processes with result left only on
25295 !> one.
25296 !> \param[in,out] msg Vector to sum (input) and (only on process root)
25297 !> result (output)
25298 !> \param root ...
25299 !> \param[in] comm Message passing environment identifier
25300 !> \par MPI mapping
25301 !> mpi_reduce
25302 ! **************************************************************************************************
25303  SUBROUTINE mp_sum_root_zv(msg, root, comm)
25304  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
25305  INTEGER, INTENT(IN) :: root
25306  CLASS(mp_comm_type), INTENT(IN) :: comm
25307 
25308  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_zv'
25309 
25310  INTEGER :: handle
25311 #if defined(__parallel)
25312  INTEGER :: ierr, m1, msglen, taskid
25313  COMPLEX(kind=real_8), ALLOCATABLE :: res(:)
25314 #endif
25315 
25316  CALL mp_timeset(routinen, handle)
25317 
25318 #if defined(__parallel)
25319  msglen = SIZE(msg)
25320  CALL mpi_comm_rank(comm%handle, taskid, ierr)
25321  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
25322  IF (msglen > 0) THEN
25323  m1 = SIZE(msg, 1)
25324  ALLOCATE (res(m1))
25325  CALL mpi_reduce(msg, res, msglen, mpi_double_complex, mpi_sum, &
25326  root, comm%handle, ierr)
25327  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
25328  IF (taskid == root) THEN
25329  msg = res
25330  END IF
25331  DEALLOCATE (res)
25332  END IF
25333  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25334 #else
25335  mark_used(msg)
25336  mark_used(root)
25337  mark_used(comm)
25338 #endif
25339  CALL mp_timestop(handle)
25340  END SUBROUTINE mp_sum_root_zv
25341 
25342 ! **************************************************************************************************
25343 !> \brief Element-wise sum of data from all processes with result left only on
25344 !> one.
25345 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
25346 !> result (output)
25347 !> \param root ...
25348 !> \param comm ...
25349 !> \note see mp_sum_root_zv
25350 ! **************************************************************************************************
25351  SUBROUTINE mp_sum_root_zm(msg, root, comm)
25352  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
25353  INTEGER, INTENT(IN) :: root
25354  CLASS(mp_comm_type), INTENT(IN) :: comm
25355 
25356  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
25357 
25358  INTEGER :: handle
25359 #if defined(__parallel)
25360  INTEGER :: ierr, m1, m2, msglen, taskid
25361  COMPLEX(kind=real_8), ALLOCATABLE :: res(:, :)
25362 #endif
25363 
25364  CALL mp_timeset(routinen, handle)
25365 
25366 #if defined(__parallel)
25367  msglen = SIZE(msg)
25368  CALL mpi_comm_rank(comm%handle, taskid, ierr)
25369  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
25370  IF (msglen > 0) THEN
25371  m1 = SIZE(msg, 1)
25372  m2 = SIZE(msg, 2)
25373  ALLOCATE (res(m1, m2))
25374  CALL mpi_reduce(msg, res, msglen, mpi_double_complex, mpi_sum, root, comm%handle, ierr)
25375  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
25376  IF (taskid == root) THEN
25377  msg = res
25378  END IF
25379  DEALLOCATE (res)
25380  END IF
25381  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25382 #else
25383  mark_used(root)
25384  mark_used(msg)
25385  mark_used(comm)
25386 #endif
25387  CALL mp_timestop(handle)
25388  END SUBROUTINE mp_sum_root_zm
25389 
25390 ! **************************************************************************************************
25391 !> \brief Partial sum of data from all processes with result on each process.
25392 !> \param[in] msg Matrix to sum (input)
25393 !> \param[out] res Matrix containing result (output)
25394 !> \param[in] comm Message passing environment identifier
25395 ! **************************************************************************************************
25396  SUBROUTINE mp_sum_partial_zm(msg, res, comm)
25397  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
25398  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: res(:, :)
25399  CLASS(mp_comm_type), INTENT(IN) :: comm
25400 
25401  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_zm'
25402 
25403  INTEGER :: handle
25404 #if defined(__parallel)
25405  INTEGER :: ierr, msglen, taskid
25406 #endif
25407 
25408  CALL mp_timeset(routinen, handle)
25409 
25410 #if defined(__parallel)
25411  msglen = SIZE(msg)
25412  CALL mpi_comm_rank(comm%handle, taskid, ierr)
25413  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
25414  IF (msglen > 0) THEN
25415  CALL mpi_scan(msg, res, msglen, mpi_double_complex, mpi_sum, comm%handle, ierr)
25416  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
25417  END IF
25418  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25419  ! perf_id is same as for other summation routines
25420 #else
25421  res = msg
25422  mark_used(comm)
25423 #endif
25424  CALL mp_timestop(handle)
25425  END SUBROUTINE mp_sum_partial_zm
25426 
25427 ! **************************************************************************************************
25428 !> \brief Finds the maximum of a datum with the result left on all processes.
25429 !> \param[in,out] msg Find maximum among these data (input) and
25430 !> maximum (output)
25431 !> \param[in] comm Message passing environment identifier
25432 !> \par MPI mapping
25433 !> mpi_allreduce
25434 ! **************************************************************************************************
25435  SUBROUTINE mp_max_z (msg, comm)
25436  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25437  CLASS(mp_comm_type), INTENT(IN) :: comm
25438 
25439  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_z'
25440 
25441  INTEGER :: handle
25442 #if defined(__parallel)
25443  INTEGER :: ierr, msglen
25444 #endif
25445 
25446  CALL mp_timeset(routinen, handle)
25447 
25448 #if defined(__parallel)
25449  msglen = 1
25450  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_max, comm%handle, ierr)
25451  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25452  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25453 #else
25454  mark_used(msg)
25455  mark_used(comm)
25456 #endif
25457  CALL mp_timestop(handle)
25458  END SUBROUTINE mp_max_z
25459 
25460 ! **************************************************************************************************
25461 !> \brief Finds the maximum of a datum with the result left on all processes.
25462 !> \param[in,out] msg Find maximum among these data (input) and
25463 !> maximum (output)
25464 !> \param[in] comm Message passing environment identifier
25465 !> \par MPI mapping
25466 !> mpi_allreduce
25467 ! **************************************************************************************************
25468  SUBROUTINE mp_max_root_z (msg, root, comm)
25469  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25470  INTEGER, INTENT(IN) :: root
25471  CLASS(mp_comm_type), INTENT(IN) :: comm
25472 
25473  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_z'
25474 
25475  INTEGER :: handle
25476 #if defined(__parallel)
25477  INTEGER :: ierr, msglen
25478  COMPLEX(kind=real_8) :: res
25479 #endif
25480 
25481  CALL mp_timeset(routinen, handle)
25482 
25483 #if defined(__parallel)
25484  msglen = 1
25485  CALL mpi_reduce(msg, res, msglen, mpi_double_complex, mpi_max, root, comm%handle, ierr)
25486  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
25487  IF (root == comm%mepos) msg = res
25488  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25489 #else
25490  mark_used(msg)
25491  mark_used(comm)
25492  mark_used(root)
25493 #endif
25494  CALL mp_timestop(handle)
25495  END SUBROUTINE mp_max_root_z
25496 
25497 ! **************************************************************************************************
25498 !> \brief Finds the element-wise maximum of a vector with the result left on
25499 !> all processes.
25500 !> \param[in,out] msg Find maximum among these data (input) and
25501 !> maximum (output)
25502 !> \param comm ...
25503 !> \note see mp_max_z
25504 ! **************************************************************************************************
25505  SUBROUTINE mp_max_zv(msg, comm)
25506  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:)
25507  CLASS(mp_comm_type), INTENT(IN) :: comm
25508 
25509  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_zv'
25510 
25511  INTEGER :: handle
25512 #if defined(__parallel)
25513  INTEGER :: ierr, msglen
25514 #endif
25515 
25516  CALL mp_timeset(routinen, handle)
25517 
25518 #if defined(__parallel)
25519  msglen = SIZE(msg)
25520  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_max, comm%handle, ierr)
25521  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25522  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25523 #else
25524  mark_used(msg)
25525  mark_used(comm)
25526 #endif
25527  CALL mp_timestop(handle)
25528  END SUBROUTINE mp_max_zv
25529 
25530 ! **************************************************************************************************
25531 !> \brief Finds the element-wise maximum of a vector with the result left on
25532 !> all processes.
25533 !> \param[in,out] msg Find maximum among these data (input) and
25534 !> maximum (output)
25535 !> \param comm ...
25536 !> \note see mp_max_z
25537 ! **************************************************************************************************
25538  SUBROUTINE mp_max_root_zm(msg, root, comm)
25539  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
25540  INTEGER :: root
25541  CLASS(mp_comm_type), INTENT(IN) :: comm
25542 
25543  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_zm'
25544 
25545  INTEGER :: handle
25546 #if defined(__parallel)
25547  INTEGER :: ierr, msglen
25548  COMPLEX(kind=real_8) :: res(size(msg, 1), size(msg, 2))
25549 #endif
25550 
25551  CALL mp_timeset(routinen, handle)
25552 
25553 #if defined(__parallel)
25554  msglen = SIZE(msg)
25555  CALL mpi_reduce(msg, res, msglen, mpi_double_complex, mpi_max, root, comm%handle, ierr)
25556  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25557  IF (root == comm%mepos) msg = res
25558  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25559 #else
25560  mark_used(msg)
25561  mark_used(comm)
25562  mark_used(root)
25563 #endif
25564  CALL mp_timestop(handle)
25565  END SUBROUTINE mp_max_root_zm
25566 
25567 ! **************************************************************************************************
25568 !> \brief Finds the minimum of a datum with the result left on all processes.
25569 !> \param[in,out] msg Find minimum among these data (input) and
25570 !> maximum (output)
25571 !> \param[in] comm Message passing environment identifier
25572 !> \par MPI mapping
25573 !> mpi_allreduce
25574 ! **************************************************************************************************
25575  SUBROUTINE mp_min_z (msg, comm)
25576  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25577  CLASS(mp_comm_type), INTENT(IN) :: comm
25578 
25579  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_z'
25580 
25581  INTEGER :: handle
25582 #if defined(__parallel)
25583  INTEGER :: ierr, msglen
25584 #endif
25585 
25586  CALL mp_timeset(routinen, handle)
25587 
25588 #if defined(__parallel)
25589  msglen = 1
25590  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_min, comm%handle, ierr)
25591  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25592  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25593 #else
25594  mark_used(msg)
25595  mark_used(comm)
25596 #endif
25597  CALL mp_timestop(handle)
25598  END SUBROUTINE mp_min_z
25599 
25600 ! **************************************************************************************************
25601 !> \brief Finds the element-wise minimum of vector with the result left on
25602 !> all processes.
25603 !> \param[in,out] msg Find minimum among these data (input) and
25604 !> maximum (output)
25605 !> \param comm ...
25606 !> \par MPI mapping
25607 !> mpi_allreduce
25608 !> \note see mp_min_z
25609 ! **************************************************************************************************
25610  SUBROUTINE mp_min_zv(msg, comm)
25611  COMPLEX(kind=real_8), INTENT(INOUT), CONTIGUOUS :: msg(:)
25612  CLASS(mp_comm_type), INTENT(IN) :: comm
25613 
25614  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_zv'
25615 
25616  INTEGER :: handle
25617 #if defined(__parallel)
25618  INTEGER :: ierr, msglen
25619 #endif
25620 
25621  CALL mp_timeset(routinen, handle)
25622 
25623 #if defined(__parallel)
25624  msglen = SIZE(msg)
25625  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_min, comm%handle, ierr)
25626  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25627  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25628 #else
25629  mark_used(msg)
25630  mark_used(comm)
25631 #endif
25632  CALL mp_timestop(handle)
25633  END SUBROUTINE mp_min_zv
25634 
25635 ! **************************************************************************************************
25636 !> \brief Multiplies a set of numbers scattered across a number of processes,
25637 !> then replicates the result.
25638 !> \param[in,out] msg a number to multiply (input) and result (output)
25639 !> \param[in] comm message passing environment identifier
25640 !> \par MPI mapping
25641 !> mpi_allreduce
25642 ! **************************************************************************************************
25643  SUBROUTINE mp_prod_z (msg, comm)
25644  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25645  CLASS(mp_comm_type), INTENT(IN) :: comm
25646 
25647  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_z'
25648 
25649  INTEGER :: handle
25650 #if defined(__parallel)
25651  INTEGER :: ierr, msglen
25652 #endif
25653 
25654  CALL mp_timeset(routinen, handle)
25655 
25656 #if defined(__parallel)
25657  msglen = 1
25658  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_double_complex, mpi_prod, comm%handle, ierr)
25659  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
25660  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_8_size))
25661 #else
25662  mark_used(msg)
25663  mark_used(comm)
25664 #endif
25665  CALL mp_timestop(handle)
25666  END SUBROUTINE mp_prod_z
25667 
25668 ! **************************************************************************************************
25669 !> \brief Scatters data from one processes to all others
25670 !> \param[in] msg_scatter Data to scatter (for root process)
25671 !> \param[out] msg Received data
25672 !> \param[in] root Process which scatters data
25673 !> \param[in] comm Message passing environment identifier
25674 !> \par MPI mapping
25675 !> mpi_scatter
25676 ! **************************************************************************************************
25677  SUBROUTINE mp_scatter_zv(msg_scatter, msg, root, comm)
25678  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
25679  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg(:)
25680  INTEGER, INTENT(IN) :: root
25681  CLASS(mp_comm_type), INTENT(IN) :: comm
25682 
25683  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_zv'
25684 
25685  INTEGER :: handle
25686 #if defined(__parallel)
25687  INTEGER :: ierr, msglen
25688 #endif
25689 
25690  CALL mp_timeset(routinen, handle)
25691 
25692 #if defined(__parallel)
25693  msglen = SIZE(msg)
25694  CALL mpi_scatter(msg_scatter, msglen, mpi_double_complex, msg, &
25695  msglen, mpi_double_complex, root, comm%handle, ierr)
25696  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
25697  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
25698 #else
25699  mark_used(root)
25700  mark_used(comm)
25701  msg = msg_scatter
25702 #endif
25703  CALL mp_timestop(handle)
25704  END SUBROUTINE mp_scatter_zv
25705 
25706 ! **************************************************************************************************
25707 !> \brief Scatters data from one processes to all others
25708 !> \param[in] msg_scatter Data to scatter (for root process)
25709 !> \param[in] root Process which scatters data
25710 !> \param[in] comm Message passing environment identifier
25711 !> \par MPI mapping
25712 !> mpi_scatter
25713 ! **************************************************************************************************
25714  SUBROUTINE mp_iscatter_z (msg_scatter, msg, root, comm, request)
25715  COMPLEX(kind=real_8), INTENT(IN) :: msg_scatter(:)
25716  COMPLEX(kind=real_8), INTENT(INOUT) :: msg
25717  INTEGER, INTENT(IN) :: root
25718  CLASS(mp_comm_type), INTENT(IN) :: comm
25719  TYPE(mp_request_type), INTENT(OUT) :: request
25720 
25721  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_z'
25722 
25723  INTEGER :: handle
25724 #if defined(__parallel)
25725  INTEGER :: ierr, msglen
25726 #endif
25727 
25728  CALL mp_timeset(routinen, handle)
25729 
25730 #if defined(__parallel)
25731 #if !defined(__GNUC__) || __GNUC__ >= 9
25732  cpassert(is_contiguous(msg_scatter))
25733 #endif
25734  msglen = 1
25735  CALL mpi_iscatter(msg_scatter, msglen, mpi_double_complex, msg, &
25736  msglen, mpi_double_complex, root, comm%handle, request%handle, ierr)
25737  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
25738  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_8_size))
25739 #else
25740  mark_used(root)
25741  mark_used(comm)
25742  msg = msg_scatter(1)
25743  request = mp_request_null
25744 #endif
25745  CALL mp_timestop(handle)
25746  END SUBROUTINE mp_iscatter_z
25747 
25748 ! **************************************************************************************************
25749 !> \brief Scatters data from one processes to all others
25750 !> \param[in] msg_scatter Data to scatter (for root process)
25751 !> \param[in] root Process which scatters data
25752 !> \param[in] comm Message passing environment identifier
25753 !> \par MPI mapping
25754 !> mpi_scatter
25755 ! **************************************************************************************************
25756  SUBROUTINE mp_iscatter_zv2(msg_scatter, msg, root, comm, request)
25757  COMPLEX(kind=real_8), INTENT(IN) :: msg_scatter(:, :)
25758  COMPLEX(kind=real_8), INTENT(INOUT) :: msg(:)
25759  INTEGER, INTENT(IN) :: root
25760  CLASS(mp_comm_type), INTENT(IN) :: comm
25761  TYPE(mp_request_type), INTENT(OUT) :: request
25762 
25763  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_zv2'
25764 
25765  INTEGER :: handle
25766 #if defined(__parallel)
25767  INTEGER :: ierr, msglen
25768 #endif
25769 
25770  CALL mp_timeset(routinen, handle)
25771 
25772 #if defined(__parallel)
25773 #if !defined(__GNUC__) || __GNUC__ >= 9
25774  cpassert(is_contiguous(msg_scatter))
25775 #endif
25776  msglen = SIZE(msg)
25777  CALL mpi_iscatter(msg_scatter, msglen, mpi_double_complex, msg, &
25778  msglen, mpi_double_complex, root, comm%handle, request%handle, ierr)
25779  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
25780  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_8_size))
25781 #else
25782  mark_used(root)
25783  mark_used(comm)
25784  msg(:) = msg_scatter(:, 1)
25785  request = mp_request_null
25786 #endif
25787  CALL mp_timestop(handle)
25788  END SUBROUTINE mp_iscatter_zv2
25789 
25790 ! **************************************************************************************************
25791 !> \brief Scatters data from one processes to all others
25792 !> \param[in] msg_scatter Data to scatter (for root process)
25793 !> \param[in] root Process which scatters data
25794 !> \param[in] comm Message passing environment identifier
25795 !> \par MPI mapping
25796 !> mpi_scatter
25797 ! **************************************************************************************************
25798  SUBROUTINE mp_iscatterv_zv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
25799  COMPLEX(kind=real_8), INTENT(IN) :: msg_scatter(:)
25800  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
25801  COMPLEX(kind=real_8), INTENT(INOUT) :: msg(:)
25802  INTEGER, INTENT(IN) :: recvcount, root
25803  CLASS(mp_comm_type), INTENT(IN) :: comm
25804  TYPE(mp_request_type), INTENT(OUT) :: request
25805 
25806  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_zv'
25807 
25808  INTEGER :: handle
25809 #if defined(__parallel)
25810  INTEGER :: ierr
25811 #endif
25812 
25813  CALL mp_timeset(routinen, handle)
25814 
25815 #if defined(__parallel)
25816 #if !defined(__GNUC__) || __GNUC__ >= 9
25817  cpassert(is_contiguous(msg_scatter))
25818  cpassert(is_contiguous(msg))
25819  cpassert(is_contiguous(sendcounts))
25820  cpassert(is_contiguous(displs))
25821 #endif
25822  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_double_complex, msg, &
25823  recvcount, mpi_double_complex, root, comm%handle, request%handle, ierr)
25824  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
25825  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_8_size))
25826 #else
25827  mark_used(sendcounts)
25828  mark_used(displs)
25829  mark_used(recvcount)
25830  mark_used(root)
25831  mark_used(comm)
25832  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
25833  request = mp_request_null
25834 #endif
25835  CALL mp_timestop(handle)
25836  END SUBROUTINE mp_iscatterv_zv
25837 
25838 ! **************************************************************************************************
25839 !> \brief Gathers a datum from all processes to one
25840 !> \param[in] msg Datum to send to root
25841 !> \param[out] msg_gather Received data (on root)
25842 !> \param[in] root Process which gathers the data
25843 !> \param[in] comm Message passing environment identifier
25844 !> \par MPI mapping
25845 !> mpi_gather
25846 ! **************************************************************************************************
25847  SUBROUTINE mp_gather_z (msg, msg_gather, root, comm)
25848  COMPLEX(kind=real_8), INTENT(IN) :: msg
25849  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
25850  INTEGER, INTENT(IN) :: root
25851  CLASS(mp_comm_type), INTENT(IN) :: comm
25852 
25853  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_z'
25854 
25855  INTEGER :: handle
25856 #if defined(__parallel)
25857  INTEGER :: ierr, msglen
25858 #endif
25859 
25860  CALL mp_timeset(routinen, handle)
25861 
25862 #if defined(__parallel)
25863  msglen = 1
25864  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
25865  msglen, mpi_double_complex, root, comm%handle, ierr)
25866  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
25867  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
25868 #else
25869  mark_used(root)
25870  mark_used(comm)
25871  msg_gather(1) = msg
25872 #endif
25873  CALL mp_timestop(handle)
25874  END SUBROUTINE mp_gather_z
25875 
25876 ! **************************************************************************************************
25877 !> \brief Gathers a datum from all processes to one, uses the source process of comm
25878 !> \param[in] msg Datum to send to root
25879 !> \param[out] msg_gather Received data (on root)
25880 !> \param[in] comm Message passing environment identifier
25881 !> \par MPI mapping
25882 !> mpi_gather
25883 ! **************************************************************************************************
25884  SUBROUTINE mp_gather_z_src(msg, msg_gather, comm)
25885  COMPLEX(kind=real_8), INTENT(IN) :: msg
25886  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
25887  CLASS(mp_comm_type), INTENT(IN) :: comm
25888 
25889  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_z_src'
25890 
25891  INTEGER :: handle
25892 #if defined(__parallel)
25893  INTEGER :: ierr, msglen
25894 #endif
25895 
25896  CALL mp_timeset(routinen, handle)
25897 
25898 #if defined(__parallel)
25899  msglen = 1
25900  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
25901  msglen, mpi_double_complex, comm%source, comm%handle, ierr)
25902  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
25903  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
25904 #else
25905  mark_used(comm)
25906  msg_gather(1) = msg
25907 #endif
25908  CALL mp_timestop(handle)
25909  END SUBROUTINE mp_gather_z_src
25910 
25911 ! **************************************************************************************************
25912 !> \brief Gathers data from all processes to one
25913 !> \param[in] msg Datum to send to root
25914 !> \param msg_gather ...
25915 !> \param root ...
25916 !> \param comm ...
25917 !> \par Data length
25918 !> All data (msg) is equal-sized
25919 !> \par MPI mapping
25920 !> mpi_gather
25921 !> \note see mp_gather_z
25922 ! **************************************************************************************************
25923  SUBROUTINE mp_gather_zv(msg, msg_gather, root, comm)
25924  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
25925  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
25926  INTEGER, INTENT(IN) :: root
25927  CLASS(mp_comm_type), INTENT(IN) :: comm
25928 
25929  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_zv'
25930 
25931  INTEGER :: handle
25932 #if defined(__parallel)
25933  INTEGER :: ierr, msglen
25934 #endif
25935 
25936  CALL mp_timeset(routinen, handle)
25937 
25938 #if defined(__parallel)
25939  msglen = SIZE(msg)
25940  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
25941  msglen, mpi_double_complex, root, comm%handle, ierr)
25942  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
25943  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
25944 #else
25945  mark_used(root)
25946  mark_used(comm)
25947  msg_gather = msg
25948 #endif
25949  CALL mp_timestop(handle)
25950  END SUBROUTINE mp_gather_zv
25951 
25952 ! **************************************************************************************************
25953 !> \brief Gathers data from all processes to one. Gathers from comm%source
25954 !> \param[in] msg Datum to send to root
25955 !> \param msg_gather ...
25956 !> \param comm ...
25957 !> \par Data length
25958 !> All data (msg) is equal-sized
25959 !> \par MPI mapping
25960 !> mpi_gather
25961 !> \note see mp_gather_z
25962 ! **************************************************************************************************
25963  SUBROUTINE mp_gather_zv_src(msg, msg_gather, comm)
25964  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
25965  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
25966  CLASS(mp_comm_type), INTENT(IN) :: comm
25967 
25968  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_zv_src'
25969 
25970  INTEGER :: handle
25971 #if defined(__parallel)
25972  INTEGER :: ierr, msglen
25973 #endif
25974 
25975  CALL mp_timeset(routinen, handle)
25976 
25977 #if defined(__parallel)
25978  msglen = SIZE(msg)
25979  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
25980  msglen, mpi_double_complex, comm%source, comm%handle, ierr)
25981  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
25982  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
25983 #else
25984  mark_used(comm)
25985  msg_gather = msg
25986 #endif
25987  CALL mp_timestop(handle)
25988  END SUBROUTINE mp_gather_zv_src
25989 
25990 ! **************************************************************************************************
25991 !> \brief Gathers data from all processes to one
25992 !> \param[in] msg Datum to send to root
25993 !> \param msg_gather ...
25994 !> \param root ...
25995 !> \param comm ...
25996 !> \par Data length
25997 !> All data (msg) is equal-sized
25998 !> \par MPI mapping
25999 !> mpi_gather
26000 !> \note see mp_gather_z
26001 ! **************************************************************************************************
26002  SUBROUTINE mp_gather_zm(msg, msg_gather, root, comm)
26003  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
26004  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
26005  INTEGER, INTENT(IN) :: root
26006  CLASS(mp_comm_type), INTENT(IN) :: comm
26007 
26008  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_zm'
26009 
26010  INTEGER :: handle
26011 #if defined(__parallel)
26012  INTEGER :: ierr, msglen
26013 #endif
26014 
26015  CALL mp_timeset(routinen, handle)
26016 
26017 #if defined(__parallel)
26018  msglen = SIZE(msg)
26019  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
26020  msglen, mpi_double_complex, root, comm%handle, ierr)
26021  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
26022  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
26023 #else
26024  mark_used(root)
26025  mark_used(comm)
26026  msg_gather = msg
26027 #endif
26028  CALL mp_timestop(handle)
26029  END SUBROUTINE mp_gather_zm
26030 
26031 ! **************************************************************************************************
26032 !> \brief Gathers data from all processes to one. Gathers from comm%source
26033 !> \param[in] msg Datum to send to root
26034 !> \param msg_gather ...
26035 !> \param comm ...
26036 !> \par Data length
26037 !> All data (msg) is equal-sized
26038 !> \par MPI mapping
26039 !> mpi_gather
26040 !> \note see mp_gather_z
26041 ! **************************************************************************************************
26042  SUBROUTINE mp_gather_zm_src(msg, msg_gather, comm)
26043  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:, :)
26044  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
26045  CLASS(mp_comm_type), INTENT(IN) :: comm
26046 
26047  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_zm_src'
26048 
26049  INTEGER :: handle
26050 #if defined(__parallel)
26051  INTEGER :: ierr, msglen
26052 #endif
26053 
26054  CALL mp_timeset(routinen, handle)
26055 
26056 #if defined(__parallel)
26057  msglen = SIZE(msg)
26058  CALL mpi_gather(msg, msglen, mpi_double_complex, msg_gather, &
26059  msglen, mpi_double_complex, comm%source, comm%handle, ierr)
26060  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
26061  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_8_size))
26062 #else
26063  mark_used(comm)
26064  msg_gather = msg
26065 #endif
26066  CALL mp_timestop(handle)
26067  END SUBROUTINE mp_gather_zm_src
26068 
26069 ! **************************************************************************************************
26070 !> \brief Gathers data from all processes to one.
26071 !> \param[in] sendbuf Data to send to root
26072 !> \param[out] recvbuf Received data (on root)
26073 !> \param[in] recvcounts Sizes of data received from processes
26074 !> \param[in] displs Offsets of data received from processes
26075 !> \param[in] root Process which gathers the data
26076 !> \param[in] comm Message passing environment identifier
26077 !> \par Data length
26078 !> Data can have different lengths
26079 !> \par Offsets
26080 !> Offsets start at 0
26081 !> \par MPI mapping
26082 !> mpi_gather
26083 ! **************************************************************************************************
26084  SUBROUTINE mp_gatherv_zv(sendbuf, recvbuf, recvcounts, displs, root, comm)
26085 
26086  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
26087  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
26088  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
26089  INTEGER, INTENT(IN) :: root
26090  CLASS(mp_comm_type), INTENT(IN) :: comm
26091 
26092  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_zv'
26093 
26094  INTEGER :: handle
26095 #if defined(__parallel)
26096  INTEGER :: ierr, sendcount
26097 #endif
26098 
26099  CALL mp_timeset(routinen, handle)
26100 
26101 #if defined(__parallel)
26102  sendcount = SIZE(sendbuf)
26103  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_complex, &
26104  recvbuf, recvcounts, displs, mpi_double_complex, &
26105  root, comm%handle, ierr)
26106  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
26107  CALL add_perf(perf_id=4, &
26108  count=1, &
26109  msg_size=sendcount*(2*real_8_size))
26110 #else
26111  mark_used(recvcounts)
26112  mark_used(root)
26113  mark_used(comm)
26114  recvbuf(1 + displs(1):) = sendbuf
26115 #endif
26116  CALL mp_timestop(handle)
26117  END SUBROUTINE mp_gatherv_zv
26118 
26119 ! **************************************************************************************************
26120 !> \brief Gathers data from all processes to one. Gathers from comm%source
26121 !> \param[in] sendbuf Data to send to root
26122 !> \param[out] recvbuf Received data (on root)
26123 !> \param[in] recvcounts Sizes of data received from processes
26124 !> \param[in] displs Offsets of data received from processes
26125 !> \param[in] comm Message passing environment identifier
26126 !> \par Data length
26127 !> Data can have different lengths
26128 !> \par Offsets
26129 !> Offsets start at 0
26130 !> \par MPI mapping
26131 !> mpi_gather
26132 ! **************************************************************************************************
26133  SUBROUTINE mp_gatherv_zv_src(sendbuf, recvbuf, recvcounts, displs, comm)
26134 
26135  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
26136  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
26137  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
26138  CLASS(mp_comm_type), INTENT(IN) :: comm
26139 
26140  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_zv_src'
26141 
26142  INTEGER :: handle
26143 #if defined(__parallel)
26144  INTEGER :: ierr, sendcount
26145 #endif
26146 
26147  CALL mp_timeset(routinen, handle)
26148 
26149 #if defined(__parallel)
26150  sendcount = SIZE(sendbuf)
26151  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_complex, &
26152  recvbuf, recvcounts, displs, mpi_double_complex, &
26153  comm%source, comm%handle, ierr)
26154  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
26155  CALL add_perf(perf_id=4, &
26156  count=1, &
26157  msg_size=sendcount*(2*real_8_size))
26158 #else
26159  mark_used(recvcounts)
26160  mark_used(comm)
26161  recvbuf(1 + displs(1):) = sendbuf
26162 #endif
26163  CALL mp_timestop(handle)
26164  END SUBROUTINE mp_gatherv_zv_src
26165 
26166 ! **************************************************************************************************
26167 !> \brief Gathers data from all processes to one.
26168 !> \param[in] sendbuf Data to send to root
26169 !> \param[out] recvbuf Received data (on root)
26170 !> \param[in] recvcounts Sizes of data received from processes
26171 !> \param[in] displs Offsets of data received from processes
26172 !> \param[in] root Process which gathers the data
26173 !> \param[in] comm Message passing environment identifier
26174 !> \par Data length
26175 !> Data can have different lengths
26176 !> \par Offsets
26177 !> Offsets start at 0
26178 !> \par MPI mapping
26179 !> mpi_gather
26180 ! **************************************************************************************************
26181  SUBROUTINE mp_gatherv_zm2(sendbuf, recvbuf, recvcounts, displs, root, comm)
26182 
26183  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
26184  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
26185  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
26186  INTEGER, INTENT(IN) :: root
26187  CLASS(mp_comm_type), INTENT(IN) :: comm
26188 
26189  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_zm2'
26190 
26191  INTEGER :: handle
26192 #if defined(__parallel)
26193  INTEGER :: ierr, sendcount
26194 #endif
26195 
26196  CALL mp_timeset(routinen, handle)
26197 
26198 #if defined(__parallel)
26199  sendcount = SIZE(sendbuf)
26200  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_complex, &
26201  recvbuf, recvcounts, displs, mpi_double_complex, &
26202  root, comm%handle, ierr)
26203  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
26204  CALL add_perf(perf_id=4, &
26205  count=1, &
26206  msg_size=sendcount*(2*real_8_size))
26207 #else
26208  mark_used(recvcounts)
26209  mark_used(root)
26210  mark_used(comm)
26211  recvbuf(:, 1 + displs(1):) = sendbuf
26212 #endif
26213  CALL mp_timestop(handle)
26214  END SUBROUTINE mp_gatherv_zm2
26215 
26216 ! **************************************************************************************************
26217 !> \brief Gathers data from all processes to one.
26218 !> \param[in] sendbuf Data to send to root
26219 !> \param[out] recvbuf Received data (on root)
26220 !> \param[in] recvcounts Sizes of data received from processes
26221 !> \param[in] displs Offsets of data received from processes
26222 !> \param[in] comm Message passing environment identifier
26223 !> \par Data length
26224 !> Data can have different lengths
26225 !> \par Offsets
26226 !> Offsets start at 0
26227 !> \par MPI mapping
26228 !> mpi_gather
26229 ! **************************************************************************************************
26230  SUBROUTINE mp_gatherv_zm2_src(sendbuf, recvbuf, recvcounts, displs, comm)
26231 
26232  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
26233  COMPLEX(kind=real_8), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
26234  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
26235  CLASS(mp_comm_type), INTENT(IN) :: comm
26236 
26237  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_zm2_src'
26238 
26239  INTEGER :: handle
26240 #if defined(__parallel)
26241  INTEGER :: ierr, sendcount
26242 #endif
26243 
26244  CALL mp_timeset(routinen, handle)
26245 
26246 #if defined(__parallel)
26247  sendcount = SIZE(sendbuf)
26248  CALL mpi_gatherv(sendbuf, sendcount, mpi_double_complex, &
26249  recvbuf, recvcounts, displs, mpi_double_complex, &
26250  comm%source, comm%handle, ierr)
26251  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
26252  CALL add_perf(perf_id=4, &
26253  count=1, &
26254  msg_size=sendcount*(2*real_8_size))
26255 #else
26256  mark_used(recvcounts)
26257  mark_used(comm)
26258  recvbuf(:, 1 + displs(1):) = sendbuf
26259 #endif
26260  CALL mp_timestop(handle)
26261  END SUBROUTINE mp_gatherv_zm2_src
26262 
26263 ! **************************************************************************************************
26264 !> \brief Gathers data from all processes to one.
26265 !> \param[in] sendbuf Data to send to root
26266 !> \param[out] recvbuf Received data (on root)
26267 !> \param[in] recvcounts Sizes of data received from processes
26268 !> \param[in] displs Offsets of data received from processes
26269 !> \param[in] root Process which gathers the data
26270 !> \param[in] comm Message passing environment identifier
26271 !> \par Data length
26272 !> Data can have different lengths
26273 !> \par Offsets
26274 !> Offsets start at 0
26275 !> \par MPI mapping
26276 !> mpi_gather
26277 ! **************************************************************************************************
26278  SUBROUTINE mp_igatherv_zv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
26279  COMPLEX(kind=real_8), DIMENSION(:), INTENT(IN) :: sendbuf
26280  COMPLEX(kind=real_8), DIMENSION(:), INTENT(OUT) :: recvbuf
26281  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
26282  INTEGER, INTENT(IN) :: sendcount, root
26283  CLASS(mp_comm_type), INTENT(IN) :: comm
26284  TYPE(mp_request_type), INTENT(OUT) :: request
26285 
26286  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_zv'
26287 
26288  INTEGER :: handle
26289 #if defined(__parallel)
26290  INTEGER :: ierr
26291 #endif
26292 
26293  CALL mp_timeset(routinen, handle)
26294 
26295 #if defined(__parallel)
26296 #if !defined(__GNUC__) || __GNUC__ >= 9
26297  cpassert(is_contiguous(sendbuf))
26298  cpassert(is_contiguous(recvbuf))
26299  cpassert(is_contiguous(recvcounts))
26300  cpassert(is_contiguous(displs))
26301 #endif
26302  CALL mpi_igatherv(sendbuf, sendcount, mpi_double_complex, &
26303  recvbuf, recvcounts, displs, mpi_double_complex, &
26304  root, comm%handle, request%handle, ierr)
26305  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
26306  CALL add_perf(perf_id=24, &
26307  count=1, &
26308  msg_size=sendcount*(2*real_8_size))
26309 #else
26310  mark_used(sendcount)
26311  mark_used(recvcounts)
26312  mark_used(root)
26313  mark_used(comm)
26314  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
26315  request = mp_request_null
26316 #endif
26317  CALL mp_timestop(handle)
26318  END SUBROUTINE mp_igatherv_zv
26319 
26320 ! **************************************************************************************************
26321 !> \brief Gathers a datum from all processes and all processes receive the
26322 !> same data
26323 !> \param[in] msgout Datum to send
26324 !> \param[out] msgin Received data
26325 !> \param[in] comm Message passing environment identifier
26326 !> \par Data size
26327 !> All processes send equal-sized data
26328 !> \par MPI mapping
26329 !> mpi_allgather
26330 ! **************************************************************************************************
26331  SUBROUTINE mp_allgather_z (msgout, msgin, comm)
26332  COMPLEX(kind=real_8), INTENT(IN) :: msgout
26333  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:)
26334  CLASS(mp_comm_type), INTENT(IN) :: comm
26335 
26336  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z'
26337 
26338  INTEGER :: handle
26339 #if defined(__parallel)
26340  INTEGER :: ierr, rcount, scount
26341 #endif
26342 
26343  CALL mp_timeset(routinen, handle)
26344 
26345 #if defined(__parallel)
26346  scount = 1
26347  rcount = 1
26348  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26349  msgin, rcount, mpi_double_complex, &
26350  comm%handle, ierr)
26351  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26352 #else
26353  mark_used(comm)
26354  msgin = msgout
26355 #endif
26356  CALL mp_timestop(handle)
26357  END SUBROUTINE mp_allgather_z
26358 
26359 ! **************************************************************************************************
26360 !> \brief Gathers a datum from all processes and all processes receive the
26361 !> same data
26362 !> \param[in] msgout Datum to send
26363 !> \param[out] msgin Received data
26364 !> \param[in] comm Message passing environment identifier
26365 !> \par Data size
26366 !> All processes send equal-sized data
26367 !> \par MPI mapping
26368 !> mpi_allgather
26369 ! **************************************************************************************************
26370  SUBROUTINE mp_allgather_z2(msgout, msgin, comm)
26371  COMPLEX(kind=real_8), INTENT(IN) :: msgout
26372  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
26373  CLASS(mp_comm_type), INTENT(IN) :: comm
26374 
26375  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z2'
26376 
26377  INTEGER :: handle
26378 #if defined(__parallel)
26379  INTEGER :: ierr, rcount, scount
26380 #endif
26381 
26382  CALL mp_timeset(routinen, handle)
26383 
26384 #if defined(__parallel)
26385  scount = 1
26386  rcount = 1
26387  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26388  msgin, rcount, mpi_double_complex, &
26389  comm%handle, ierr)
26390  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26391 #else
26392  mark_used(comm)
26393  msgin = msgout
26394 #endif
26395  CALL mp_timestop(handle)
26396  END SUBROUTINE mp_allgather_z2
26397 
26398 ! **************************************************************************************************
26399 !> \brief Gathers a datum from all processes and all processes receive the
26400 !> same data
26401 !> \param[in] msgout Datum to send
26402 !> \param[out] msgin Received data
26403 !> \param[in] comm Message passing environment identifier
26404 !> \par Data size
26405 !> All processes send equal-sized data
26406 !> \par MPI mapping
26407 !> mpi_allgather
26408 ! **************************************************************************************************
26409  SUBROUTINE mp_iallgather_z (msgout, msgin, comm, request)
26410  COMPLEX(kind=real_8), INTENT(IN) :: msgout
26411  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:)
26412  CLASS(mp_comm_type), INTENT(IN) :: comm
26413  TYPE(mp_request_type), INTENT(OUT) :: request
26414 
26415  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z'
26416 
26417  INTEGER :: handle
26418 #if defined(__parallel)
26419  INTEGER :: ierr, rcount, scount
26420 #endif
26421 
26422  CALL mp_timeset(routinen, handle)
26423 
26424 #if defined(__parallel)
26425 #if !defined(__GNUC__) || __GNUC__ >= 9
26426  cpassert(is_contiguous(msgin))
26427 #endif
26428  scount = 1
26429  rcount = 1
26430  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26431  msgin, rcount, mpi_double_complex, &
26432  comm%handle, request%handle, ierr)
26433  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26434 #else
26435  mark_used(comm)
26436  msgin = msgout
26437  request = mp_request_null
26438 #endif
26439  CALL mp_timestop(handle)
26440  END SUBROUTINE mp_iallgather_z
26441 
26442 ! **************************************************************************************************
26443 !> \brief Gathers vector data from all processes and all processes receive the
26444 !> same data
26445 !> \param[in] msgout Rank-1 data to send
26446 !> \param[out] msgin Received data
26447 !> \param[in] comm Message passing environment identifier
26448 !> \par Data size
26449 !> All processes send equal-sized data
26450 !> \par Ranks
26451 !> The last rank counts the processes
26452 !> \par MPI mapping
26453 !> mpi_allgather
26454 ! **************************************************************************************************
26455  SUBROUTINE mp_allgather_z12(msgout, msgin, comm)
26456  COMPLEX(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:)
26457  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
26458  CLASS(mp_comm_type), INTENT(IN) :: comm
26459 
26460  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z12'
26461 
26462  INTEGER :: handle
26463 #if defined(__parallel)
26464  INTEGER :: ierr, rcount, scount
26465 #endif
26466 
26467  CALL mp_timeset(routinen, handle)
26468 
26469 #if defined(__parallel)
26470  scount = SIZE(msgout(:))
26471  rcount = scount
26472  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26473  msgin, rcount, mpi_double_complex, &
26474  comm%handle, ierr)
26475  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26476 #else
26477  mark_used(comm)
26478  msgin(:, 1) = msgout(:)
26479 #endif
26480  CALL mp_timestop(handle)
26481  END SUBROUTINE mp_allgather_z12
26482 
26483 ! **************************************************************************************************
26484 !> \brief Gathers matrix data from all processes and all processes receive the
26485 !> same data
26486 !> \param[in] msgout Rank-2 data to send
26487 !> \param msgin ...
26488 !> \param comm ...
26489 !> \note see mp_allgather_z12
26490 ! **************************************************************************************************
26491  SUBROUTINE mp_allgather_z23(msgout, msgin, comm)
26492  COMPLEX(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
26493  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
26494  CLASS(mp_comm_type), INTENT(IN) :: comm
26495 
26496  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z23'
26497 
26498  INTEGER :: handle
26499 #if defined(__parallel)
26500  INTEGER :: ierr, rcount, scount
26501 #endif
26502 
26503  CALL mp_timeset(routinen, handle)
26504 
26505 #if defined(__parallel)
26506  scount = SIZE(msgout(:, :))
26507  rcount = scount
26508  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26509  msgin, rcount, mpi_double_complex, &
26510  comm%handle, ierr)
26511  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26512 #else
26513  mark_used(comm)
26514  msgin(:, :, 1) = msgout(:, :)
26515 #endif
26516  CALL mp_timestop(handle)
26517  END SUBROUTINE mp_allgather_z23
26518 
26519 ! **************************************************************************************************
26520 !> \brief Gathers rank-3 data from all processes and all processes receive the
26521 !> same data
26522 !> \param[in] msgout Rank-3 data to send
26523 !> \param msgin ...
26524 !> \param comm ...
26525 !> \note see mp_allgather_z12
26526 ! **************************************************************************************************
26527  SUBROUTINE mp_allgather_z34(msgout, msgin, comm)
26528  COMPLEX(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
26529  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
26530  CLASS(mp_comm_type), INTENT(IN) :: comm
26531 
26532  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z34'
26533 
26534  INTEGER :: handle
26535 #if defined(__parallel)
26536  INTEGER :: ierr, rcount, scount
26537 #endif
26538 
26539  CALL mp_timeset(routinen, handle)
26540 
26541 #if defined(__parallel)
26542  scount = SIZE(msgout(:, :, :))
26543  rcount = scount
26544  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26545  msgin, rcount, mpi_double_complex, &
26546  comm%handle, ierr)
26547  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26548 #else
26549  mark_used(comm)
26550  msgin(:, :, :, 1) = msgout(:, :, :)
26551 #endif
26552  CALL mp_timestop(handle)
26553  END SUBROUTINE mp_allgather_z34
26554 
26555 ! **************************************************************************************************
26556 !> \brief Gathers rank-2 data from all processes and all processes receive the
26557 !> same data
26558 !> \param[in] msgout Rank-2 data to send
26559 !> \param msgin ...
26560 !> \param comm ...
26561 !> \note see mp_allgather_z12
26562 ! **************************************************************************************************
26563  SUBROUTINE mp_allgather_z22(msgout, msgin, comm)
26564  COMPLEX(kind=real_8), INTENT(IN), CONTIGUOUS :: msgout(:, :)
26565  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
26566  CLASS(mp_comm_type), INTENT(IN) :: comm
26567 
26568  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_z22'
26569 
26570  INTEGER :: handle
26571 #if defined(__parallel)
26572  INTEGER :: ierr, rcount, scount
26573 #endif
26574 
26575  CALL mp_timeset(routinen, handle)
26576 
26577 #if defined(__parallel)
26578  scount = SIZE(msgout(:, :))
26579  rcount = scount
26580  CALL mpi_allgather(msgout, scount, mpi_double_complex, &
26581  msgin, rcount, mpi_double_complex, &
26582  comm%handle, ierr)
26583  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
26584 #else
26585  mark_used(comm)
26586  msgin(:, :) = msgout(:, :)
26587 #endif
26588  CALL mp_timestop(handle)
26589  END SUBROUTINE mp_allgather_z22
26590 
26591 ! **************************************************************************************************
26592 !> \brief Gathers rank-1 data from all processes and all processes receive the
26593 !> same data
26594 !> \param[in] msgout Rank-1 data to send
26595 !> \param msgin ...
26596 !> \param comm ...
26597 !> \param request ...
26598 !> \note see mp_allgather_z11
26599 ! **************************************************************************************************
26600  SUBROUTINE mp_iallgather_z11(msgout, msgin, comm, request)
26601  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:)
26602  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:)
26603  CLASS(mp_comm_type), INTENT(IN) :: comm
26604  TYPE(mp_request_type), INTENT(OUT) :: request
26605 
26606  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z11'
26607 
26608  INTEGER :: handle
26609 #if defined(__parallel)
26610  INTEGER :: ierr, rcount, scount
26611 #endif
26612 
26613  CALL mp_timeset(routinen, handle)
26614 
26615 #if defined(__parallel)
26616 #if !defined(__GNUC__) || __GNUC__ >= 9
26617  cpassert(is_contiguous(msgout))
26618  cpassert(is_contiguous(msgin))
26619 #endif
26620  scount = SIZE(msgout(:))
26621  rcount = scount
26622  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26623  msgin, rcount, mpi_double_complex, &
26624  comm%handle, request%handle, ierr)
26625  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
26626 #else
26627  mark_used(comm)
26628  msgin = msgout
26629  request = mp_request_null
26630 #endif
26631  CALL mp_timestop(handle)
26632  END SUBROUTINE mp_iallgather_z11
26633 
26634 ! **************************************************************************************************
26635 !> \brief Gathers rank-2 data from all processes and all processes receive the
26636 !> same data
26637 !> \param[in] msgout Rank-2 data to send
26638 !> \param msgin ...
26639 !> \param comm ...
26640 !> \param request ...
26641 !> \note see mp_allgather_z12
26642 ! **************************************************************************************************
26643  SUBROUTINE mp_iallgather_z13(msgout, msgin, comm, request)
26644  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:)
26645  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:, :, :)
26646  CLASS(mp_comm_type), INTENT(IN) :: comm
26647  TYPE(mp_request_type), INTENT(OUT) :: request
26648 
26649  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z13'
26650 
26651  INTEGER :: handle
26652 #if defined(__parallel)
26653  INTEGER :: ierr, rcount, scount
26654 #endif
26655 
26656  CALL mp_timeset(routinen, handle)
26657 
26658 #if defined(__parallel)
26659 #if !defined(__GNUC__) || __GNUC__ >= 9
26660  cpassert(is_contiguous(msgout))
26661  cpassert(is_contiguous(msgin))
26662 #endif
26663 
26664  scount = SIZE(msgout(:))
26665  rcount = scount
26666  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26667  msgin, rcount, mpi_double_complex, &
26668  comm%handle, request%handle, ierr)
26669  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
26670 #else
26671  mark_used(comm)
26672  msgin(:, 1, 1) = msgout(:)
26673  request = mp_request_null
26674 #endif
26675  CALL mp_timestop(handle)
26676  END SUBROUTINE mp_iallgather_z13
26677 
26678 ! **************************************************************************************************
26679 !> \brief Gathers rank-2 data from all processes and all processes receive the
26680 !> same data
26681 !> \param[in] msgout Rank-2 data to send
26682 !> \param msgin ...
26683 !> \param comm ...
26684 !> \param request ...
26685 !> \note see mp_allgather_z12
26686 ! **************************************************************************************************
26687  SUBROUTINE mp_iallgather_z22(msgout, msgin, comm, request)
26688  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:, :)
26689  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:, :)
26690  CLASS(mp_comm_type), INTENT(IN) :: comm
26691  TYPE(mp_request_type), INTENT(OUT) :: request
26692 
26693  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z22'
26694 
26695  INTEGER :: handle
26696 #if defined(__parallel)
26697  INTEGER :: ierr, rcount, scount
26698 #endif
26699 
26700  CALL mp_timeset(routinen, handle)
26701 
26702 #if defined(__parallel)
26703 #if !defined(__GNUC__) || __GNUC__ >= 9
26704  cpassert(is_contiguous(msgout))
26705  cpassert(is_contiguous(msgin))
26706 #endif
26707 
26708  scount = SIZE(msgout(:, :))
26709  rcount = scount
26710  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26711  msgin, rcount, mpi_double_complex, &
26712  comm%handle, request%handle, ierr)
26713  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
26714 #else
26715  mark_used(comm)
26716  msgin(:, :) = msgout(:, :)
26717  request = mp_request_null
26718 #endif
26719  CALL mp_timestop(handle)
26720  END SUBROUTINE mp_iallgather_z22
26721 
26722 ! **************************************************************************************************
26723 !> \brief Gathers rank-2 data from all processes and all processes receive the
26724 !> same data
26725 !> \param[in] msgout Rank-2 data to send
26726 !> \param msgin ...
26727 !> \param comm ...
26728 !> \param request ...
26729 !> \note see mp_allgather_z12
26730 ! **************************************************************************************************
26731  SUBROUTINE mp_iallgather_z24(msgout, msgin, comm, request)
26732  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:, :)
26733  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:, :, :, :)
26734  CLASS(mp_comm_type), INTENT(IN) :: comm
26735  TYPE(mp_request_type), INTENT(OUT) :: request
26736 
26737  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z24'
26738 
26739  INTEGER :: handle
26740 #if defined(__parallel)
26741  INTEGER :: ierr, rcount, scount
26742 #endif
26743 
26744  CALL mp_timeset(routinen, handle)
26745 
26746 #if defined(__parallel)
26747 #if !defined(__GNUC__) || __GNUC__ >= 9
26748  cpassert(is_contiguous(msgout))
26749  cpassert(is_contiguous(msgin))
26750 #endif
26751 
26752  scount = SIZE(msgout(:, :))
26753  rcount = scount
26754  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26755  msgin, rcount, mpi_double_complex, &
26756  comm%handle, request%handle, ierr)
26757  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
26758 #else
26759  mark_used(comm)
26760  msgin(:, :, 1, 1) = msgout(:, :)
26761  request = mp_request_null
26762 #endif
26763  CALL mp_timestop(handle)
26764  END SUBROUTINE mp_iallgather_z24
26765 
26766 ! **************************************************************************************************
26767 !> \brief Gathers rank-3 data from all processes and all processes receive the
26768 !> same data
26769 !> \param[in] msgout Rank-3 data to send
26770 !> \param msgin ...
26771 !> \param comm ...
26772 !> \param request ...
26773 !> \note see mp_allgather_z12
26774 ! **************************************************************************************************
26775  SUBROUTINE mp_iallgather_z33(msgout, msgin, comm, request)
26776  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:, :, :)
26777  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:, :, :)
26778  CLASS(mp_comm_type), INTENT(IN) :: comm
26779  TYPE(mp_request_type), INTENT(OUT) :: request
26780 
26781  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_z33'
26782 
26783  INTEGER :: handle
26784 #if defined(__parallel)
26785  INTEGER :: ierr, rcount, scount
26786 #endif
26787 
26788  CALL mp_timeset(routinen, handle)
26789 
26790 #if defined(__parallel)
26791 #if !defined(__GNUC__) || __GNUC__ >= 9
26792  cpassert(is_contiguous(msgout))
26793  cpassert(is_contiguous(msgin))
26794 #endif
26795 
26796  scount = SIZE(msgout(:, :, :))
26797  rcount = scount
26798  CALL mpi_iallgather(msgout, scount, mpi_double_complex, &
26799  msgin, rcount, mpi_double_complex, &
26800  comm%handle, request%handle, ierr)
26801  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
26802 #else
26803  mark_used(comm)
26804  msgin(:, :, :) = msgout(:, :, :)
26805  request = mp_request_null
26806 #endif
26807  CALL mp_timestop(handle)
26808  END SUBROUTINE mp_iallgather_z33
26809 
26810 ! **************************************************************************************************
26811 !> \brief Gathers vector data from all processes and all processes receive the
26812 !> same data
26813 !> \param[in] msgout Rank-1 data to send
26814 !> \param[out] msgin Received data
26815 !> \param[in] rcount Size of sent data for every process
26816 !> \param[in] rdispl Offset of sent data for every process
26817 !> \param[in] comm Message passing environment identifier
26818 !> \par Data size
26819 !> Processes can send different-sized data
26820 !> \par Ranks
26821 !> The last rank counts the processes
26822 !> \par Offsets
26823 !> Offsets are from 0
26824 !> \par MPI mapping
26825 !> mpi_allgather
26826 ! **************************************************************************************************
26827  SUBROUTINE mp_allgatherv_zv(msgout, msgin, rcount, rdispl, comm)
26828  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
26829  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
26830  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
26831  CLASS(mp_comm_type), INTENT(IN) :: comm
26832 
26833  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_zv'
26834 
26835  INTEGER :: handle
26836 #if defined(__parallel)
26837  INTEGER :: ierr, scount
26838 #endif
26839 
26840  CALL mp_timeset(routinen, handle)
26841 
26842 #if defined(__parallel)
26843  scount = SIZE(msgout)
26844  CALL mpi_allgatherv(msgout, scount, mpi_double_complex, msgin, rcount, &
26845  rdispl, mpi_double_complex, comm%handle, ierr)
26846  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
26847 #else
26848  mark_used(rcount)
26849  mark_used(rdispl)
26850  mark_used(comm)
26851  msgin = msgout
26852 #endif
26853  CALL mp_timestop(handle)
26854  END SUBROUTINE mp_allgatherv_zv
26855 
26856 ! **************************************************************************************************
26857 !> \brief Gathers vector data from all processes and all processes receive the
26858 !> same data
26859 !> \param[in] msgout Rank-1 data to send
26860 !> \param[out] msgin Received data
26861 !> \param[in] rcount Size of sent data for every process
26862 !> \param[in] rdispl Offset of sent data for every process
26863 !> \param[in] comm Message passing environment identifier
26864 !> \par Data size
26865 !> Processes can send different-sized data
26866 !> \par Ranks
26867 !> The last rank counts the processes
26868 !> \par Offsets
26869 !> Offsets are from 0
26870 !> \par MPI mapping
26871 !> mpi_allgather
26872 ! **************************************************************************************************
26873  SUBROUTINE mp_allgatherv_zm2(msgout, msgin, rcount, rdispl, comm)
26874  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
26875  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
26876  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
26877  CLASS(mp_comm_type), INTENT(IN) :: comm
26878 
26879  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_zv'
26880 
26881  INTEGER :: handle
26882 #if defined(__parallel)
26883  INTEGER :: ierr, scount
26884 #endif
26885 
26886  CALL mp_timeset(routinen, handle)
26887 
26888 #if defined(__parallel)
26889  scount = SIZE(msgout)
26890  CALL mpi_allgatherv(msgout, scount, mpi_double_complex, msgin, rcount, &
26891  rdispl, mpi_double_complex, comm%handle, ierr)
26892  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
26893 #else
26894  mark_used(rcount)
26895  mark_used(rdispl)
26896  mark_used(comm)
26897  msgin = msgout
26898 #endif
26899  CALL mp_timestop(handle)
26900  END SUBROUTINE mp_allgatherv_zm2
26901 
26902 ! **************************************************************************************************
26903 !> \brief Gathers vector data from all processes and all processes receive the
26904 !> same data
26905 !> \param[in] msgout Rank-1 data to send
26906 !> \param[out] msgin Received data
26907 !> \param[in] rcount Size of sent data for every process
26908 !> \param[in] rdispl Offset of sent data for every process
26909 !> \param[in] comm Message passing environment identifier
26910 !> \par Data size
26911 !> Processes can send different-sized data
26912 !> \par Ranks
26913 !> The last rank counts the processes
26914 !> \par Offsets
26915 !> Offsets are from 0
26916 !> \par MPI mapping
26917 !> mpi_allgather
26918 ! **************************************************************************************************
26919  SUBROUTINE mp_iallgatherv_zv(msgout, msgin, rcount, rdispl, comm, request)
26920  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:)
26921  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:)
26922  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
26923  CLASS(mp_comm_type), INTENT(IN) :: comm
26924  TYPE(mp_request_type), INTENT(OUT) :: request
26925 
26926  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_zv'
26927 
26928  INTEGER :: handle
26929 #if defined(__parallel)
26930  INTEGER :: ierr, scount, rsize
26931 #endif
26932 
26933  CALL mp_timeset(routinen, handle)
26934 
26935 #if defined(__parallel)
26936 #if !defined(__GNUC__) || __GNUC__ >= 9
26937  cpassert(is_contiguous(msgout))
26938  cpassert(is_contiguous(msgin))
26939  cpassert(is_contiguous(rcount))
26940  cpassert(is_contiguous(rdispl))
26941 #endif
26942 
26943  scount = SIZE(msgout)
26944  rsize = SIZE(rcount)
26945  CALL mp_iallgatherv_zv_internal(msgout, scount, msgin, rsize, rcount, &
26946  rdispl, comm, request, ierr)
26947  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
26948 #else
26949  mark_used(rcount)
26950  mark_used(rdispl)
26951  mark_used(comm)
26952  msgin = msgout
26953  request = mp_request_null
26954 #endif
26955  CALL mp_timestop(handle)
26956  END SUBROUTINE mp_iallgatherv_zv
26957 
26958 ! **************************************************************************************************
26959 !> \brief Gathers vector data from all processes and all processes receive the
26960 !> same data
26961 !> \param[in] msgout Rank-1 data to send
26962 !> \param[out] msgin Received data
26963 !> \param[in] rcount Size of sent data for every process
26964 !> \param[in] rdispl Offset of sent data for every process
26965 !> \param[in] comm Message passing environment identifier
26966 !> \par Data size
26967 !> Processes can send different-sized data
26968 !> \par Ranks
26969 !> The last rank counts the processes
26970 !> \par Offsets
26971 !> Offsets are from 0
26972 !> \par MPI mapping
26973 !> mpi_allgather
26974 ! **************************************************************************************************
26975  SUBROUTINE mp_iallgatherv_zv2(msgout, msgin, rcount, rdispl, comm, request)
26976  COMPLEX(kind=real_8), INTENT(IN) :: msgout(:)
26977  COMPLEX(kind=real_8), INTENT(OUT) :: msgin(:)
26978  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
26979  CLASS(mp_comm_type), INTENT(IN) :: comm
26980  TYPE(mp_request_type), INTENT(OUT) :: request
26981 
26982  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_zv2'
26983 
26984  INTEGER :: handle
26985 #if defined(__parallel)
26986  INTEGER :: ierr, scount, rsize
26987 #endif
26988 
26989  CALL mp_timeset(routinen, handle)
26990 
26991 #if defined(__parallel)
26992 #if !defined(__GNUC__) || __GNUC__ >= 9
26993  cpassert(is_contiguous(msgout))
26994  cpassert(is_contiguous(msgin))
26995  cpassert(is_contiguous(rcount))
26996  cpassert(is_contiguous(rdispl))
26997 #endif
26998 
26999  scount = SIZE(msgout)
27000  rsize = SIZE(rcount)
27001  CALL mp_iallgatherv_zv_internal(msgout, scount, msgin, rsize, rcount, &
27002  rdispl, comm, request, ierr)
27003  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
27004 #else
27005  mark_used(rcount)
27006  mark_used(rdispl)
27007  mark_used(comm)
27008  msgin = msgout
27009  request = mp_request_null
27010 #endif
27011  CALL mp_timestop(handle)
27012  END SUBROUTINE mp_iallgatherv_zv2
27013 
27014 ! **************************************************************************************************
27015 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
27016 !> the issue is with the rank of rcount and rdispl
27017 !> \param count ...
27018 !> \param array_of_requests ...
27019 !> \param array_of_statuses ...
27020 !> \param ierr ...
27021 !> \author Alfio Lazzaro
27022 ! **************************************************************************************************
27023 #if defined(__parallel)
27024  SUBROUTINE mp_iallgatherv_zv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
27025  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:)
27026  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
27027  INTEGER, INTENT(IN) :: rsize
27028  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
27029  CLASS(mp_comm_type), INTENT(IN) :: comm
27030  TYPE(mp_request_type), INTENT(OUT) :: request
27031  INTEGER, INTENT(INOUT) :: ierr
27032 
27033  CALL mpi_iallgatherv(msgout, scount, mpi_double_complex, msgin, rcount, &
27034  rdispl, mpi_double_complex, comm%handle, request%handle, ierr)
27035 
27036  END SUBROUTINE mp_iallgatherv_zv_internal
27037 #endif
27038 
27039 ! **************************************************************************************************
27040 !> \brief Sums a vector and partitions the result among processes
27041 !> \param[in] msgout Data to sum
27042 !> \param[out] msgin Received portion of summed data
27043 !> \param[in] rcount Partition sizes of the summed data for
27044 !> every process
27045 !> \param[in] comm Message passing environment identifier
27046 ! **************************************************************************************************
27047  SUBROUTINE mp_sum_scatter_zv(msgout, msgin, rcount, comm)
27048  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
27049  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgin(:)
27050  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
27051  CLASS(mp_comm_type), INTENT(IN) :: comm
27052 
27053  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_zv'
27054 
27055  INTEGER :: handle
27056 #if defined(__parallel)
27057  INTEGER :: ierr
27058 #endif
27059 
27060  CALL mp_timeset(routinen, handle)
27061 
27062 #if defined(__parallel)
27063  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_double_complex, mpi_sum, &
27064  comm%handle, ierr)
27065  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
27066 
27067  CALL add_perf(perf_id=3, count=1, &
27068  msg_size=rcount(1)*2*(2*real_8_size))
27069 #else
27070  mark_used(rcount)
27071  mark_used(comm)
27072  msgin = msgout(:, 1)
27073 #endif
27074  CALL mp_timestop(handle)
27075  END SUBROUTINE mp_sum_scatter_zv
27076 
27077 ! **************************************************************************************************
27078 !> \brief Sends and receives vector data
27079 !> \param[in] msgin Data to send
27080 !> \param[in] dest Process to send data to
27081 !> \param[out] msgout Received data
27082 !> \param[in] source Process from which to receive
27083 !> \param[in] comm Message passing environment identifier
27084 !> \param[in] tag Send and recv tag (default: 0)
27085 ! **************************************************************************************************
27086  SUBROUTINE mp_sendrecv_z (msgin, dest, msgout, source, comm, tag)
27087  COMPLEX(kind=real_8), INTENT(IN) :: msgin
27088  INTEGER, INTENT(IN) :: dest
27089  COMPLEX(kind=real_8), INTENT(OUT) :: msgout
27090  INTEGER, INTENT(IN) :: source
27091  CLASS(mp_comm_type), INTENT(IN) :: comm
27092  INTEGER, INTENT(IN), OPTIONAL :: tag
27093 
27094  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_z'
27095 
27096  INTEGER :: handle
27097 #if defined(__parallel)
27098  INTEGER :: ierr, msglen_in, msglen_out, &
27099  recv_tag, send_tag
27100 #endif
27101 
27102  CALL mp_timeset(routinen, handle)
27103 
27104 #if defined(__parallel)
27105  msglen_in = 1
27106  msglen_out = 1
27107  send_tag = 0 ! cannot think of something better here, this might be dangerous
27108  recv_tag = 0 ! cannot think of something better here, this might be dangerous
27109  IF (PRESENT(tag)) THEN
27110  send_tag = tag
27111  recv_tag = tag
27112  END IF
27113  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_complex, dest, send_tag, msgout, &
27114  msglen_out, mpi_double_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
27115  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
27116  CALL add_perf(perf_id=7, count=1, &
27117  msg_size=(msglen_in + msglen_out)*(2*real_8_size)/2)
27118 #else
27119  mark_used(dest)
27120  mark_used(source)
27121  mark_used(comm)
27122  mark_used(tag)
27123  msgout = msgin
27124 #endif
27125  CALL mp_timestop(handle)
27126  END SUBROUTINE mp_sendrecv_z
27127 
27128 ! **************************************************************************************************
27129 !> \brief Sends and receives vector data
27130 !> \param[in] msgin Data to send
27131 !> \param[in] dest Process to send data to
27132 !> \param[out] msgout Received data
27133 !> \param[in] source Process from which to receive
27134 !> \param[in] comm Message passing environment identifier
27135 !> \param[in] tag Send and recv tag (default: 0)
27136 ! **************************************************************************************************
27137  SUBROUTINE mp_sendrecv_zv(msgin, dest, msgout, source, comm, tag)
27138  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:)
27139  INTEGER, INTENT(IN) :: dest
27140  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:)
27141  INTEGER, INTENT(IN) :: source
27142  CLASS(mp_comm_type), INTENT(IN) :: comm
27143  INTEGER, INTENT(IN), OPTIONAL :: tag
27144 
27145  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_zv'
27146 
27147  INTEGER :: handle
27148 #if defined(__parallel)
27149  INTEGER :: ierr, msglen_in, msglen_out, &
27150  recv_tag, send_tag
27151 #endif
27152 
27153  CALL mp_timeset(routinen, handle)
27154 
27155 #if defined(__parallel)
27156  msglen_in = SIZE(msgin)
27157  msglen_out = SIZE(msgout)
27158  send_tag = 0 ! cannot think of something better here, this might be dangerous
27159  recv_tag = 0 ! cannot think of something better here, this might be dangerous
27160  IF (PRESENT(tag)) THEN
27161  send_tag = tag
27162  recv_tag = tag
27163  END IF
27164  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_complex, dest, send_tag, msgout, &
27165  msglen_out, mpi_double_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
27166  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
27167  CALL add_perf(perf_id=7, count=1, &
27168  msg_size=(msglen_in + msglen_out)*(2*real_8_size)/2)
27169 #else
27170  mark_used(dest)
27171  mark_used(source)
27172  mark_used(comm)
27173  mark_used(tag)
27174  msgout = msgin
27175 #endif
27176  CALL mp_timestop(handle)
27177  END SUBROUTINE mp_sendrecv_zv
27178 
27179 ! **************************************************************************************************
27180 !> \brief Sends and receives matrix data
27181 !> \param msgin ...
27182 !> \param dest ...
27183 !> \param msgout ...
27184 !> \param source ...
27185 !> \param comm ...
27186 !> \param tag ...
27187 !> \note see mp_sendrecv_zv
27188 ! **************************************************************************************************
27189  SUBROUTINE mp_sendrecv_zm2(msgin, dest, msgout, source, comm, tag)
27190  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
27191  INTEGER, INTENT(IN) :: dest
27192  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
27193  INTEGER, INTENT(IN) :: source
27194  CLASS(mp_comm_type), INTENT(IN) :: comm
27195  INTEGER, INTENT(IN), OPTIONAL :: tag
27196 
27197  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_zm2'
27198 
27199  INTEGER :: handle
27200 #if defined(__parallel)
27201  INTEGER :: ierr, msglen_in, msglen_out, &
27202  recv_tag, send_tag
27203 #endif
27204 
27205  CALL mp_timeset(routinen, handle)
27206 
27207 #if defined(__parallel)
27208  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
27209  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
27210  send_tag = 0 ! cannot think of something better here, this might be dangerous
27211  recv_tag = 0 ! cannot think of something better here, this might be dangerous
27212  IF (PRESENT(tag)) THEN
27213  send_tag = tag
27214  recv_tag = tag
27215  END IF
27216  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_complex, dest, send_tag, msgout, &
27217  msglen_out, mpi_double_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
27218  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
27219  CALL add_perf(perf_id=7, count=1, &
27220  msg_size=(msglen_in + msglen_out)*(2*real_8_size)/2)
27221 #else
27222  mark_used(dest)
27223  mark_used(source)
27224  mark_used(comm)
27225  mark_used(tag)
27226  msgout = msgin
27227 #endif
27228  CALL mp_timestop(handle)
27229  END SUBROUTINE mp_sendrecv_zm2
27230 
27231 ! **************************************************************************************************
27232 !> \brief Sends and receives rank-3 data
27233 !> \param msgin ...
27234 !> \param dest ...
27235 !> \param msgout ...
27236 !> \param source ...
27237 !> \param comm ...
27238 !> \note see mp_sendrecv_zv
27239 ! **************************************************************************************************
27240  SUBROUTINE mp_sendrecv_zm3(msgin, dest, msgout, source, comm, tag)
27241  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
27242  INTEGER, INTENT(IN) :: dest
27243  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
27244  INTEGER, INTENT(IN) :: source
27245  CLASS(mp_comm_type), INTENT(IN) :: comm
27246  INTEGER, INTENT(IN), OPTIONAL :: tag
27247 
27248  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_zm3'
27249 
27250  INTEGER :: handle
27251 #if defined(__parallel)
27252  INTEGER :: ierr, msglen_in, msglen_out, &
27253  recv_tag, send_tag
27254 #endif
27255 
27256  CALL mp_timeset(routinen, handle)
27257 
27258 #if defined(__parallel)
27259  msglen_in = SIZE(msgin)
27260  msglen_out = SIZE(msgout)
27261  send_tag = 0 ! cannot think of something better here, this might be dangerous
27262  recv_tag = 0 ! cannot think of something better here, this might be dangerous
27263  IF (PRESENT(tag)) THEN
27264  send_tag = tag
27265  recv_tag = tag
27266  END IF
27267  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_complex, dest, send_tag, msgout, &
27268  msglen_out, mpi_double_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
27269  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
27270  CALL add_perf(perf_id=7, count=1, &
27271  msg_size=(msglen_in + msglen_out)*(2*real_8_size)/2)
27272 #else
27273  mark_used(dest)
27274  mark_used(source)
27275  mark_used(comm)
27276  mark_used(tag)
27277  msgout = msgin
27278 #endif
27279  CALL mp_timestop(handle)
27280  END SUBROUTINE mp_sendrecv_zm3
27281 
27282 ! **************************************************************************************************
27283 !> \brief Sends and receives rank-4 data
27284 !> \param msgin ...
27285 !> \param dest ...
27286 !> \param msgout ...
27287 !> \param source ...
27288 !> \param comm ...
27289 !> \note see mp_sendrecv_zv
27290 ! **************************************************************************************************
27291  SUBROUTINE mp_sendrecv_zm4(msgin, dest, msgout, source, comm, tag)
27292  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
27293  INTEGER, INTENT(IN) :: dest
27294  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
27295  INTEGER, INTENT(IN) :: source
27296  CLASS(mp_comm_type), INTENT(IN) :: comm
27297  INTEGER, INTENT(IN), OPTIONAL :: tag
27298 
27299  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_zm4'
27300 
27301  INTEGER :: handle
27302 #if defined(__parallel)
27303  INTEGER :: ierr, msglen_in, msglen_out, &
27304  recv_tag, send_tag
27305 #endif
27306 
27307  CALL mp_timeset(routinen, handle)
27308 
27309 #if defined(__parallel)
27310  msglen_in = SIZE(msgin)
27311  msglen_out = SIZE(msgout)
27312  send_tag = 0 ! cannot think of something better here, this might be dangerous
27313  recv_tag = 0 ! cannot think of something better here, this might be dangerous
27314  IF (PRESENT(tag)) THEN
27315  send_tag = tag
27316  recv_tag = tag
27317  END IF
27318  CALL mpi_sendrecv(msgin, msglen_in, mpi_double_complex, dest, send_tag, msgout, &
27319  msglen_out, mpi_double_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
27320  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
27321  CALL add_perf(perf_id=7, count=1, &
27322  msg_size=(msglen_in + msglen_out)*(2*real_8_size)/2)
27323 #else
27324  mark_used(dest)
27325  mark_used(source)
27326  mark_used(comm)
27327  mark_used(tag)
27328  msgout = msgin
27329 #endif
27330  CALL mp_timestop(handle)
27331  END SUBROUTINE mp_sendrecv_zm4
27332 
27333 ! **************************************************************************************************
27334 !> \brief Non-blocking send and receive of a scalar
27335 !> \param[in] msgin Scalar data to send
27336 !> \param[in] dest Which process to send to
27337 !> \param[out] msgout Receive data into this pointer
27338 !> \param[in] source Process to receive from
27339 !> \param[in] comm Message passing environment identifier
27340 !> \param[out] send_request Request handle for the send
27341 !> \param[out] recv_request Request handle for the receive
27342 !> \param[in] tag (optional) tag to differentiate requests
27343 !> \par Implementation
27344 !> Calls mpi_isend and mpi_irecv.
27345 !> \par History
27346 !> 02.2005 created [Alfio Lazzaro]
27347 ! **************************************************************************************************
27348  SUBROUTINE mp_isendrecv_z (msgin, dest, msgout, source, comm, send_request, &
27349  recv_request, tag)
27350  COMPLEX(kind=real_8), INTENT(IN) :: msgin
27351  INTEGER, INTENT(IN) :: dest
27352  COMPLEX(kind=real_8), INTENT(INOUT) :: msgout
27353  INTEGER, INTENT(IN) :: source
27354  CLASS(mp_comm_type), INTENT(IN) :: comm
27355  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
27356  INTEGER, INTENT(in), OPTIONAL :: tag
27357 
27358  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_z'
27359 
27360  INTEGER :: handle
27361 #if defined(__parallel)
27362  INTEGER :: ierr, my_tag
27363 #endif
27364 
27365  CALL mp_timeset(routinen, handle)
27366 
27367 #if defined(__parallel)
27368  my_tag = 0
27369  IF (PRESENT(tag)) my_tag = tag
27370 
27371  CALL mpi_irecv(msgout, 1, mpi_double_complex, source, my_tag, &
27372  comm%handle, recv_request%handle, ierr)
27373  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
27374 
27375  CALL mpi_isend(msgin, 1, mpi_double_complex, dest, my_tag, &
27376  comm%handle, send_request%handle, ierr)
27377  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27378 
27379  CALL add_perf(perf_id=8, count=1, msg_size=2*(2*real_8_size))
27380 #else
27381  mark_used(dest)
27382  mark_used(source)
27383  mark_used(comm)
27384  mark_used(tag)
27385  send_request = mp_request_null
27386  recv_request = mp_request_null
27387  msgout = msgin
27388 #endif
27389  CALL mp_timestop(handle)
27390  END SUBROUTINE mp_isendrecv_z
27391 
27392 ! **************************************************************************************************
27393 !> \brief Non-blocking send and receive of a vector
27394 !> \param[in] msgin Vector data to send
27395 !> \param[in] dest Which process to send to
27396 !> \param[out] msgout Receive data into this pointer
27397 !> \param[in] source Process to receive from
27398 !> \param[in] comm Message passing environment identifier
27399 !> \param[out] send_request Request handle for the send
27400 !> \param[out] recv_request Request handle for the receive
27401 !> \param[in] tag (optional) tag to differentiate requests
27402 !> \par Implementation
27403 !> Calls mpi_isend and mpi_irecv.
27404 !> \par History
27405 !> 11.2004 created [Joost VandeVondele]
27406 !> \note
27407 !> arrays can be pointers or assumed shape, but they must be contiguous!
27408 ! **************************************************************************************************
27409  SUBROUTINE mp_isendrecv_zv(msgin, dest, msgout, source, comm, send_request, &
27410  recv_request, tag)
27411  COMPLEX(kind=real_8), DIMENSION(:), INTENT(IN) :: msgin
27412  INTEGER, INTENT(IN) :: dest
27413  COMPLEX(kind=real_8), DIMENSION(:), INTENT(INOUT) :: msgout
27414  INTEGER, INTENT(IN) :: source
27415  CLASS(mp_comm_type), INTENT(IN) :: comm
27416  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
27417  INTEGER, INTENT(in), OPTIONAL :: tag
27418 
27419  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_zv'
27420 
27421  INTEGER :: handle
27422 #if defined(__parallel)
27423  INTEGER :: ierr, msglen, my_tag
27424  COMPLEX(kind=real_8) :: foo
27425 #endif
27426 
27427  CALL mp_timeset(routinen, handle)
27428 
27429 #if defined(__parallel)
27430 #if !defined(__GNUC__) || __GNUC__ >= 9
27431  cpassert(is_contiguous(msgout))
27432  cpassert(is_contiguous(msgin))
27433 #endif
27434 
27435  my_tag = 0
27436  IF (PRESENT(tag)) my_tag = tag
27437 
27438  msglen = SIZE(msgout, 1)
27439  IF (msglen > 0) THEN
27440  CALL mpi_irecv(msgout(1), msglen, mpi_double_complex, source, my_tag, &
27441  comm%handle, recv_request%handle, ierr)
27442  ELSE
27443  CALL mpi_irecv(foo, msglen, mpi_double_complex, source, my_tag, &
27444  comm%handle, recv_request%handle, ierr)
27445  END IF
27446  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
27447 
27448  msglen = SIZE(msgin, 1)
27449  IF (msglen > 0) THEN
27450  CALL mpi_isend(msgin(1), msglen, mpi_double_complex, dest, my_tag, &
27451  comm%handle, send_request%handle, ierr)
27452  ELSE
27453  CALL mpi_isend(foo, msglen, mpi_double_complex, dest, my_tag, &
27454  comm%handle, send_request%handle, ierr)
27455  END IF
27456  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27457 
27458  msglen = (msglen + SIZE(msgout, 1) + 1)/2
27459  CALL add_perf(perf_id=8, count=1, msg_size=msglen*(2*real_8_size))
27460 #else
27461  mark_used(dest)
27462  mark_used(source)
27463  mark_used(comm)
27464  mark_used(tag)
27465  send_request = mp_request_null
27466  recv_request = mp_request_null
27467  msgout = msgin
27468 #endif
27469  CALL mp_timestop(handle)
27470  END SUBROUTINE mp_isendrecv_zv
27471 
27472 ! **************************************************************************************************
27473 !> \brief Non-blocking send of vector data
27474 !> \param msgin ...
27475 !> \param dest ...
27476 !> \param comm ...
27477 !> \param request ...
27478 !> \param tag ...
27479 !> \par History
27480 !> 08.2003 created [f&j]
27481 !> \note see mp_isendrecv_zv
27482 !> \note
27483 !> arrays can be pointers or assumed shape, but they must be contiguous!
27484 ! **************************************************************************************************
27485  SUBROUTINE mp_isend_zv(msgin, dest, comm, request, tag)
27486  COMPLEX(kind=real_8), DIMENSION(:), INTENT(IN) :: msgin
27487  INTEGER, INTENT(IN) :: dest
27488  CLASS(mp_comm_type), INTENT(IN) :: comm
27489  TYPE(mp_request_type), INTENT(out) :: request
27490  INTEGER, INTENT(in), OPTIONAL :: tag
27491 
27492  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_zv'
27493 
27494  INTEGER :: handle, ierr
27495 #if defined(__parallel)
27496  INTEGER :: msglen, my_tag
27497  COMPLEX(kind=real_8) :: foo(1)
27498 #endif
27499 
27500  CALL mp_timeset(routinen, handle)
27501 
27502 #if defined(__parallel)
27503 #if !defined(__GNUC__) || __GNUC__ >= 9
27504  cpassert(is_contiguous(msgin))
27505 #endif
27506  my_tag = 0
27507  IF (PRESENT(tag)) my_tag = tag
27508 
27509  msglen = SIZE(msgin)
27510  IF (msglen > 0) THEN
27511  CALL mpi_isend(msgin(1), msglen, mpi_double_complex, dest, my_tag, &
27512  comm%handle, request%handle, ierr)
27513  ELSE
27514  CALL mpi_isend(foo, msglen, mpi_double_complex, dest, my_tag, &
27515  comm%handle, request%handle, ierr)
27516  END IF
27517  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27518 
27519  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_8_size))
27520 #else
27521  mark_used(msgin)
27522  mark_used(dest)
27523  mark_used(comm)
27524  mark_used(request)
27525  mark_used(tag)
27526  ierr = 1
27527  request = mp_request_null
27528  CALL mp_stop(ierr, "mp_isend called in non parallel case")
27529 #endif
27530  CALL mp_timestop(handle)
27531  END SUBROUTINE mp_isend_zv
27532 
27533 ! **************************************************************************************************
27534 !> \brief Non-blocking send of matrix data
27535 !> \param msgin ...
27536 !> \param dest ...
27537 !> \param comm ...
27538 !> \param request ...
27539 !> \param tag ...
27540 !> \par History
27541 !> 2009-11-25 [UB] Made type-generic for templates
27542 !> \author fawzi
27543 !> \note see mp_isendrecv_zv
27544 !> \note see mp_isend_zv
27545 !> \note
27546 !> arrays can be pointers or assumed shape, but they must be contiguous!
27547 ! **************************************************************************************************
27548  SUBROUTINE mp_isend_zm2(msgin, dest, comm, request, tag)
27549  COMPLEX(kind=real_8), DIMENSION(:, :), INTENT(IN) :: msgin
27550  INTEGER, INTENT(IN) :: dest
27551  CLASS(mp_comm_type), INTENT(IN) :: comm
27552  TYPE(mp_request_type), INTENT(out) :: request
27553  INTEGER, INTENT(in), OPTIONAL :: tag
27554 
27555  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_zm2'
27556 
27557  INTEGER :: handle, ierr
27558 #if defined(__parallel)
27559  INTEGER :: msglen, my_tag
27560  COMPLEX(kind=real_8) :: foo(1)
27561 #endif
27562 
27563  CALL mp_timeset(routinen, handle)
27564 
27565 #if defined(__parallel)
27566 #if !defined(__GNUC__) || __GNUC__ >= 9
27567  cpassert(is_contiguous(msgin))
27568 #endif
27569 
27570  my_tag = 0
27571  IF (PRESENT(tag)) my_tag = tag
27572 
27573  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
27574  IF (msglen > 0) THEN
27575  CALL mpi_isend(msgin(1, 1), msglen, mpi_double_complex, dest, my_tag, &
27576  comm%handle, request%handle, ierr)
27577  ELSE
27578  CALL mpi_isend(foo, msglen, mpi_double_complex, dest, my_tag, &
27579  comm%handle, request%handle, ierr)
27580  END IF
27581  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27582 
27583  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_8_size))
27584 #else
27585  mark_used(msgin)
27586  mark_used(dest)
27587  mark_used(comm)
27588  mark_used(request)
27589  mark_used(tag)
27590  ierr = 1
27591  request = mp_request_null
27592  CALL mp_stop(ierr, "mp_isend called in non parallel case")
27593 #endif
27594  CALL mp_timestop(handle)
27595  END SUBROUTINE mp_isend_zm2
27596 
27597 ! **************************************************************************************************
27598 !> \brief Non-blocking send of rank-3 data
27599 !> \param msgin ...
27600 !> \param dest ...
27601 !> \param comm ...
27602 !> \param request ...
27603 !> \param tag ...
27604 !> \par History
27605 !> 9.2008 added _rm3 subroutine [Iain Bethune]
27606 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
27607 !> 2009-11-25 [UB] Made type-generic for templates
27608 !> \author fawzi
27609 !> \note see mp_isendrecv_zv
27610 !> \note see mp_isend_zv
27611 !> \note
27612 !> arrays can be pointers or assumed shape, but they must be contiguous!
27613 ! **************************************************************************************************
27614  SUBROUTINE mp_isend_zm3(msgin, dest, comm, request, tag)
27615  COMPLEX(kind=real_8), DIMENSION(:, :, :), INTENT(IN) :: msgin
27616  INTEGER, INTENT(IN) :: dest
27617  CLASS(mp_comm_type), INTENT(IN) :: comm
27618  TYPE(mp_request_type), INTENT(out) :: request
27619  INTEGER, INTENT(in), OPTIONAL :: tag
27620 
27621  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_zm3'
27622 
27623  INTEGER :: handle, ierr
27624 #if defined(__parallel)
27625  INTEGER :: msglen, my_tag
27626  COMPLEX(kind=real_8) :: foo(1)
27627 #endif
27628 
27629  CALL mp_timeset(routinen, handle)
27630 
27631 #if defined(__parallel)
27632 #if !defined(__GNUC__) || __GNUC__ >= 9
27633  cpassert(is_contiguous(msgin))
27634 #endif
27635 
27636  my_tag = 0
27637  IF (PRESENT(tag)) my_tag = tag
27638 
27639  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
27640  IF (msglen > 0) THEN
27641  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_double_complex, dest, my_tag, &
27642  comm%handle, request%handle, ierr)
27643  ELSE
27644  CALL mpi_isend(foo, msglen, mpi_double_complex, dest, my_tag, &
27645  comm%handle, request%handle, ierr)
27646  END IF
27647  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27648 
27649  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_8_size))
27650 #else
27651  mark_used(msgin)
27652  mark_used(dest)
27653  mark_used(comm)
27654  mark_used(request)
27655  mark_used(tag)
27656  ierr = 1
27657  request = mp_request_null
27658  CALL mp_stop(ierr, "mp_isend called in non parallel case")
27659 #endif
27660  CALL mp_timestop(handle)
27661  END SUBROUTINE mp_isend_zm3
27662 
27663 ! **************************************************************************************************
27664 !> \brief Non-blocking send of rank-4 data
27665 !> \param msgin the input message
27666 !> \param dest the destination processor
27667 !> \param comm the communicator object
27668 !> \param request the communication request id
27669 !> \param tag the message tag
27670 !> \par History
27671 !> 2.2016 added _zm4 subroutine [Nico Holmberg]
27672 !> \author fawzi
27673 !> \note see mp_isend_zv
27674 !> \note
27675 !> arrays can be pointers or assumed shape, but they must be contiguous!
27676 ! **************************************************************************************************
27677  SUBROUTINE mp_isend_zm4(msgin, dest, comm, request, tag)
27678  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
27679  INTEGER, INTENT(IN) :: dest
27680  CLASS(mp_comm_type), INTENT(IN) :: comm
27681  TYPE(mp_request_type), INTENT(out) :: request
27682  INTEGER, INTENT(in), OPTIONAL :: tag
27683 
27684  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_zm4'
27685 
27686  INTEGER :: handle, ierr
27687 #if defined(__parallel)
27688  INTEGER :: msglen, my_tag
27689  COMPLEX(kind=real_8) :: foo(1)
27690 #endif
27691 
27692  CALL mp_timeset(routinen, handle)
27693 
27694 #if defined(__parallel)
27695 #if !defined(__GNUC__) || __GNUC__ >= 9
27696  cpassert(is_contiguous(msgin))
27697 #endif
27698 
27699  my_tag = 0
27700  IF (PRESENT(tag)) my_tag = tag
27701 
27702  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
27703  IF (msglen > 0) THEN
27704  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_double_complex, dest, my_tag, &
27705  comm%handle, request%handle, ierr)
27706  ELSE
27707  CALL mpi_isend(foo, msglen, mpi_double_complex, dest, my_tag, &
27708  comm%handle, request%handle, ierr)
27709  END IF
27710  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
27711 
27712  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_8_size))
27713 #else
27714  mark_used(msgin)
27715  mark_used(dest)
27716  mark_used(comm)
27717  mark_used(request)
27718  mark_used(tag)
27719  ierr = 1
27720  request = mp_request_null
27721  CALL mp_stop(ierr, "mp_isend called in non parallel case")
27722 #endif
27723  CALL mp_timestop(handle)
27724  END SUBROUTINE mp_isend_zm4
27725 
27726 ! **************************************************************************************************
27727 !> \brief Non-blocking receive of vector data
27728 !> \param msgout ...
27729 !> \param source ...
27730 !> \param comm ...
27731 !> \param request ...
27732 !> \param tag ...
27733 !> \par History
27734 !> 08.2003 created [f&j]
27735 !> 2009-11-25 [UB] Made type-generic for templates
27736 !> \note see mp_isendrecv_zv
27737 !> \note
27738 !> arrays can be pointers or assumed shape, but they must be contiguous!
27739 ! **************************************************************************************************
27740  SUBROUTINE mp_irecv_zv(msgout, source, comm, request, tag)
27741  COMPLEX(kind=real_8), DIMENSION(:), INTENT(INOUT) :: msgout
27742  INTEGER, INTENT(IN) :: source
27743  CLASS(mp_comm_type), INTENT(IN) :: comm
27744  TYPE(mp_request_type), INTENT(out) :: request
27745  INTEGER, INTENT(in), OPTIONAL :: tag
27746 
27747  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_zv'
27748 
27749  INTEGER :: handle
27750 #if defined(__parallel)
27751  INTEGER :: ierr, msglen, my_tag
27752  COMPLEX(kind=real_8) :: foo(1)
27753 #endif
27754 
27755  CALL mp_timeset(routinen, handle)
27756 
27757 #if defined(__parallel)
27758 #if !defined(__GNUC__) || __GNUC__ >= 9
27759  cpassert(is_contiguous(msgout))
27760 #endif
27761 
27762  my_tag = 0
27763  IF (PRESENT(tag)) my_tag = tag
27764 
27765  msglen = SIZE(msgout)
27766  IF (msglen > 0) THEN
27767  CALL mpi_irecv(msgout(1), msglen, mpi_double_complex, source, my_tag, &
27768  comm%handle, request%handle, ierr)
27769  ELSE
27770  CALL mpi_irecv(foo, msglen, mpi_double_complex, source, my_tag, &
27771  comm%handle, request%handle, ierr)
27772  END IF
27773  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
27774 
27775  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_8_size))
27776 #else
27777  cpabort("mp_irecv called in non parallel case")
27778  mark_used(msgout)
27779  mark_used(source)
27780  mark_used(comm)
27781  mark_used(tag)
27782  request = mp_request_null
27783 #endif
27784  CALL mp_timestop(handle)
27785  END SUBROUTINE mp_irecv_zv
27786 
27787 ! **************************************************************************************************
27788 !> \brief Non-blocking receive of matrix data
27789 !> \param msgout ...
27790 !> \param source ...
27791 !> \param comm ...
27792 !> \param request ...
27793 !> \param tag ...
27794 !> \par History
27795 !> 2009-11-25 [UB] Made type-generic for templates
27796 !> \author fawzi
27797 !> \note see mp_isendrecv_zv
27798 !> \note see mp_irecv_zv
27799 !> \note
27800 !> arrays can be pointers or assumed shape, but they must be contiguous!
27801 ! **************************************************************************************************
27802  SUBROUTINE mp_irecv_zm2(msgout, source, comm, request, tag)
27803  COMPLEX(kind=real_8), DIMENSION(:, :), INTENT(INOUT) :: msgout
27804  INTEGER, INTENT(IN) :: source
27805  CLASS(mp_comm_type), INTENT(IN) :: comm
27806  TYPE(mp_request_type), INTENT(out) :: request
27807  INTEGER, INTENT(in), OPTIONAL :: tag
27808 
27809  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_zm2'
27810 
27811  INTEGER :: handle
27812 #if defined(__parallel)
27813  INTEGER :: ierr, msglen, my_tag
27814  COMPLEX(kind=real_8) :: foo(1)
27815 #endif
27816 
27817  CALL mp_timeset(routinen, handle)
27818 
27819 #if defined(__parallel)
27820 #if !defined(__GNUC__) || __GNUC__ >= 9
27821  cpassert(is_contiguous(msgout))
27822 #endif
27823 
27824  my_tag = 0
27825  IF (PRESENT(tag)) my_tag = tag
27826 
27827  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
27828  IF (msglen > 0) THEN
27829  CALL mpi_irecv(msgout(1, 1), msglen, mpi_double_complex, source, my_tag, &
27830  comm%handle, request%handle, ierr)
27831  ELSE
27832  CALL mpi_irecv(foo, msglen, mpi_double_complex, source, my_tag, &
27833  comm%handle, request%handle, ierr)
27834  END IF
27835  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
27836 
27837  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_8_size))
27838 #else
27839  mark_used(msgout)
27840  mark_used(source)
27841  mark_used(comm)
27842  mark_used(tag)
27843  request = mp_request_null
27844  cpabort("mp_irecv called in non parallel case")
27845 #endif
27846  CALL mp_timestop(handle)
27847  END SUBROUTINE mp_irecv_zm2
27848 
27849 ! **************************************************************************************************
27850 !> \brief Non-blocking send of rank-3 data
27851 !> \param msgout ...
27852 !> \param source ...
27853 !> \param comm ...
27854 !> \param request ...
27855 !> \param tag ...
27856 !> \par History
27857 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
27858 !> 2009-11-25 [UB] Made type-generic for templates
27859 !> \author fawzi
27860 !> \note see mp_isendrecv_zv
27861 !> \note see mp_irecv_zv
27862 !> \note
27863 !> arrays can be pointers or assumed shape, but they must be contiguous!
27864 ! **************************************************************************************************
27865  SUBROUTINE mp_irecv_zm3(msgout, source, comm, request, tag)
27866  COMPLEX(kind=real_8), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
27867  INTEGER, INTENT(IN) :: source
27868  CLASS(mp_comm_type), INTENT(IN) :: comm
27869  TYPE(mp_request_type), INTENT(out) :: request
27870  INTEGER, INTENT(in), OPTIONAL :: tag
27871 
27872  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_zm3'
27873 
27874  INTEGER :: handle
27875 #if defined(__parallel)
27876  INTEGER :: ierr, msglen, my_tag
27877  COMPLEX(kind=real_8) :: foo(1)
27878 #endif
27879 
27880  CALL mp_timeset(routinen, handle)
27881 
27882 #if defined(__parallel)
27883 #if !defined(__GNUC__) || __GNUC__ >= 9
27884  cpassert(is_contiguous(msgout))
27885 #endif
27886 
27887  my_tag = 0
27888  IF (PRESENT(tag)) my_tag = tag
27889 
27890  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
27891  IF (msglen > 0) THEN
27892  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_double_complex, source, my_tag, &
27893  comm%handle, request%handle, ierr)
27894  ELSE
27895  CALL mpi_irecv(foo, msglen, mpi_double_complex, source, my_tag, &
27896  comm%handle, request%handle, ierr)
27897  END IF
27898  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
27899 
27900  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_8_size))
27901 #else
27902  mark_used(msgout)
27903  mark_used(source)
27904  mark_used(comm)
27905  mark_used(tag)
27906  request = mp_request_null
27907  cpabort("mp_irecv called in non parallel case")
27908 #endif
27909  CALL mp_timestop(handle)
27910  END SUBROUTINE mp_irecv_zm3
27911 
27912 ! **************************************************************************************************
27913 !> \brief Non-blocking receive of rank-4 data
27914 !> \param msgout the output message
27915 !> \param source the source processor
27916 !> \param comm the communicator object
27917 !> \param request the communication request id
27918 !> \param tag the message tag
27919 !> \par History
27920 !> 2.2016 added _zm4 subroutine [Nico Holmberg]
27921 !> \author fawzi
27922 !> \note see mp_irecv_zv
27923 !> \note
27924 !> arrays can be pointers or assumed shape, but they must be contiguous!
27925 ! **************************************************************************************************
27926  SUBROUTINE mp_irecv_zm4(msgout, source, comm, request, tag)
27927  COMPLEX(kind=real_8), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
27928  INTEGER, INTENT(IN) :: source
27929  CLASS(mp_comm_type), INTENT(IN) :: comm
27930  TYPE(mp_request_type), INTENT(out) :: request
27931  INTEGER, INTENT(in), OPTIONAL :: tag
27932 
27933  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_zm4'
27934 
27935  INTEGER :: handle
27936 #if defined(__parallel)
27937  INTEGER :: ierr, msglen, my_tag
27938  COMPLEX(kind=real_8) :: foo(1)
27939 #endif
27940 
27941  CALL mp_timeset(routinen, handle)
27942 
27943 #if defined(__parallel)
27944 #if !defined(__GNUC__) || __GNUC__ >= 9
27945  cpassert(is_contiguous(msgout))
27946 #endif
27947 
27948  my_tag = 0
27949  IF (PRESENT(tag)) my_tag = tag
27950 
27951  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
27952  IF (msglen > 0) THEN
27953  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_double_complex, source, my_tag, &
27954  comm%handle, request%handle, ierr)
27955  ELSE
27956  CALL mpi_irecv(foo, msglen, mpi_double_complex, source, my_tag, &
27957  comm%handle, request%handle, ierr)
27958  END IF
27959  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
27960 
27961  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_8_size))
27962 #else
27963  mark_used(msgout)
27964  mark_used(source)
27965  mark_used(comm)
27966  mark_used(tag)
27967  request = mp_request_null
27968  cpabort("mp_irecv called in non parallel case")
27969 #endif
27970  CALL mp_timestop(handle)
27971  END SUBROUTINE mp_irecv_zm4
27972 
27973 ! **************************************************************************************************
27974 !> \brief Window initialization function for vector data
27975 !> \param base ...
27976 !> \param comm ...
27977 !> \param win ...
27978 !> \par History
27979 !> 02.2015 created [Alfio Lazzaro]
27980 !> \note
27981 !> arrays can be pointers or assumed shape, but they must be contiguous!
27982 ! **************************************************************************************************
27983  SUBROUTINE mp_win_create_zv(base, comm, win)
27984  COMPLEX(kind=real_8), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
27985  TYPE(mp_comm_type), INTENT(IN) :: comm
27986  CLASS(mp_win_type), INTENT(INOUT) :: win
27987 
27988  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_zv'
27989 
27990  INTEGER :: handle
27991 #if defined(__parallel)
27992  INTEGER :: ierr
27993  INTEGER(kind=mpi_address_kind) :: len
27994  COMPLEX(kind=real_8) :: foo(1)
27995 #endif
27996 
27997  CALL mp_timeset(routinen, handle)
27998 
27999 #if defined(__parallel)
28000 
28001  len = SIZE(base)*(2*real_8_size)
28002  IF (len > 0) THEN
28003  CALL mpi_win_create(base(1), len, (2*real_8_size), mpi_info_null, comm%handle, win%handle, ierr)
28004  ELSE
28005  CALL mpi_win_create(foo, len, (2*real_8_size), mpi_info_null, comm%handle, win%handle, ierr)
28006  END IF
28007  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
28008 
28009  CALL add_perf(perf_id=20, count=1)
28010 #else
28011  mark_used(base)
28012  mark_used(comm)
28013  win%handle = mp_win_null_handle
28014 #endif
28015  CALL mp_timestop(handle)
28016  END SUBROUTINE mp_win_create_zv
28017 
28018 ! **************************************************************************************************
28019 !> \brief Single-sided get function for vector data
28020 !> \param base ...
28021 !> \param comm ...
28022 !> \param win ...
28023 !> \par History
28024 !> 02.2015 created [Alfio Lazzaro]
28025 !> \note
28026 !> arrays can be pointers or assumed shape, but they must be contiguous!
28027 ! **************************************************************************************************
28028  SUBROUTINE mp_rget_zv(base, source, win, win_data, myproc, disp, request, &
28029  origin_datatype, target_datatype)
28030  COMPLEX(kind=real_8), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
28031  INTEGER, INTENT(IN) :: source
28032  CLASS(mp_win_type), INTENT(IN) :: win
28033  COMPLEX(kind=real_8), DIMENSION(:), INTENT(IN) :: win_data
28034  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
28035  TYPE(mp_request_type), INTENT(OUT) :: request
28036  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
28037 
28038  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_zv'
28039 
28040  INTEGER :: handle
28041 #if defined(__parallel)
28042  INTEGER :: ierr, len, &
28043  origin_len, target_len
28044  LOGICAL :: do_local_copy
28045  INTEGER(kind=mpi_address_kind) :: disp_aint
28046  mpi_data_type :: handle_origin_datatype, handle_target_datatype
28047 #endif
28048 
28049  CALL mp_timeset(routinen, handle)
28050 
28051 #if defined(__parallel)
28052  len = SIZE(base)
28053  disp_aint = 0
28054  IF (PRESENT(disp)) THEN
28055  disp_aint = int(disp, kind=mpi_address_kind)
28056  END IF
28057  handle_origin_datatype = mpi_double_complex
28058  origin_len = len
28059  IF (PRESENT(origin_datatype)) THEN
28060  handle_origin_datatype = origin_datatype%type_handle
28061  origin_len = 1
28062  END IF
28063  handle_target_datatype = mpi_double_complex
28064  target_len = len
28065  IF (PRESENT(target_datatype)) THEN
28066  handle_target_datatype = target_datatype%type_handle
28067  target_len = 1
28068  END IF
28069  IF (len > 0) THEN
28070  do_local_copy = .false.
28071  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
28072  IF (myproc .EQ. source) do_local_copy = .true.
28073  END IF
28074  IF (do_local_copy) THEN
28075  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
28076  base(:) = win_data(disp_aint + 1:disp_aint + len)
28077  !$OMP END PARALLEL WORKSHARE
28078  request = mp_request_null
28079  ierr = 0
28080  ELSE
28081  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
28082  target_len, handle_target_datatype, win%handle, request%handle, ierr)
28083  END IF
28084  ELSE
28085  request = mp_request_null
28086  ierr = 0
28087  END IF
28088  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
28089 
28090  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*(2*real_8_size))
28091 #else
28092  mark_used(source)
28093  mark_used(win)
28094  mark_used(myproc)
28095  mark_used(origin_datatype)
28096  mark_used(target_datatype)
28097 
28098  request = mp_request_null
28099  !
28100  IF (PRESENT(disp)) THEN
28101  base(:) = win_data(disp + 1:disp + SIZE(base))
28102  ELSE
28103  base(:) = win_data(:SIZE(base))
28104  END IF
28105 
28106 #endif
28107  CALL mp_timestop(handle)
28108  END SUBROUTINE mp_rget_zv
28109 
28110 ! **************************************************************************************************
28111 !> \brief ...
28112 !> \param count ...
28113 !> \param lengths ...
28114 !> \param displs ...
28115 !> \return ...
28116 ! ***************************************************************************
28117  FUNCTION mp_type_indexed_make_z (count, lengths, displs) &
28118  result(type_descriptor)
28119  INTEGER, INTENT(IN) :: count
28120  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
28121  TYPE(mp_type_descriptor_type) :: type_descriptor
28122 
28123  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_z'
28124 
28125  INTEGER :: handle
28126 #if defined(__parallel)
28127  INTEGER :: ierr
28128 #endif
28129 
28130  CALL mp_timeset(routinen, handle)
28131 
28132 #if defined(__parallel)
28133  CALL mpi_type_indexed(count, lengths, displs, mpi_double_complex, &
28134  type_descriptor%type_handle, ierr)
28135  IF (ierr /= 0) &
28136  cpabort("MPI_Type_Indexed @ "//routinen)
28137  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
28138  IF (ierr /= 0) &
28139  cpabort("MPI_Type_commit @ "//routinen)
28140 #else
28141  type_descriptor%type_handle = 7
28142 #endif
28143  type_descriptor%length = count
28144  NULLIFY (type_descriptor%subtype)
28145  type_descriptor%vector_descriptor(1:2) = 1
28146  type_descriptor%has_indexing = .true.
28147  type_descriptor%index_descriptor%index => lengths
28148  type_descriptor%index_descriptor%chunks => displs
28149 
28150  CALL mp_timestop(handle)
28151 
28152  END FUNCTION mp_type_indexed_make_z
28153 
28154 ! **************************************************************************************************
28155 !> \brief Allocates special parallel memory
28156 !> \param[in] DATA pointer to integer array to allocate
28157 !> \param[in] len number of integers to allocate
28158 !> \param[out] stat (optional) allocation status result
28159 !> \author UB
28160 ! **************************************************************************************************
28161  SUBROUTINE mp_allocate_z (DATA, len, stat)
28162  COMPLEX(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
28163  INTEGER, INTENT(IN) :: len
28164  INTEGER, INTENT(OUT), OPTIONAL :: stat
28165 
28166  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_z'
28167 
28168  INTEGER :: handle, ierr
28169 
28170  CALL mp_timeset(routinen, handle)
28171 
28172 #if defined(__parallel)
28173  NULLIFY (data)
28174  CALL mp_alloc_mem(DATA, len, stat=ierr)
28175  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
28176  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
28177  CALL add_perf(perf_id=15, count=1)
28178 #else
28179  ALLOCATE (DATA(len), stat=ierr)
28180  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
28181  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
28182 #endif
28183  IF (PRESENT(stat)) stat = ierr
28184  CALL mp_timestop(handle)
28185  END SUBROUTINE mp_allocate_z
28186 
28187 ! **************************************************************************************************
28188 !> \brief Deallocates special parallel memory
28189 !> \param[in] DATA pointer to special memory to deallocate
28190 !> \param stat ...
28191 !> \author UB
28192 ! **************************************************************************************************
28193  SUBROUTINE mp_deallocate_z (DATA, stat)
28194  COMPLEX(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
28195  INTEGER, INTENT(OUT), OPTIONAL :: stat
28196 
28197  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_z'
28198 
28199  INTEGER :: handle
28200 #if defined(__parallel)
28201  INTEGER :: ierr
28202 #endif
28203 
28204  CALL mp_timeset(routinen, handle)
28205 
28206 #if defined(__parallel)
28207  CALL mp_free_mem(DATA, ierr)
28208  IF (PRESENT(stat)) THEN
28209  stat = ierr
28210  ELSE
28211  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
28212  END IF
28213  NULLIFY (data)
28214  CALL add_perf(perf_id=15, count=1)
28215 #else
28216  DEALLOCATE (data)
28217  IF (PRESENT(stat)) stat = 0
28218 #endif
28219  CALL mp_timestop(handle)
28220  END SUBROUTINE mp_deallocate_z
28221 
28222 ! **************************************************************************************************
28223 !> \brief (parallel) Blocking individual file write using explicit offsets
28224 !> (serial) Unformatted stream write
28225 !> \param[in] fh file handle (file storage unit)
28226 !> \param[in] offset file offset (position)
28227 !> \param[in] msg data to be written to the file
28228 !> \param msglen ...
28229 !> \par MPI-I/O mapping mpi_file_write_at
28230 !> \par STREAM-I/O mapping WRITE
28231 !> \param[in](optional) msglen number of the elements of data
28232 ! **************************************************************************************************
28233  SUBROUTINE mp_file_write_at_zv(fh, offset, msg, msglen)
28234  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
28235  CLASS(mp_file_type), INTENT(IN) :: fh
28236  INTEGER, INTENT(IN), OPTIONAL :: msglen
28237  INTEGER(kind=file_offset), INTENT(IN) :: offset
28238 
28239  INTEGER :: msg_len
28240 #if defined(__parallel)
28241  INTEGER :: ierr
28242 #endif
28243 
28244  msg_len = SIZE(msg)
28245  IF (PRESENT(msglen)) msg_len = msglen
28246 #if defined(__parallel)
28247  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_double_complex, mpi_status_ignore, ierr)
28248  IF (ierr .NE. 0) &
28249  cpabort("mpi_file_write_at_zv @ mp_file_write_at_zv")
28250 #else
28251  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
28252 #endif
28253  END SUBROUTINE mp_file_write_at_zv
28254 
28255 ! **************************************************************************************************
28256 !> \brief ...
28257 !> \param fh ...
28258 !> \param offset ...
28259 !> \param msg ...
28260 ! **************************************************************************************************
28261  SUBROUTINE mp_file_write_at_z (fh, offset, msg)
28262  COMPLEX(kind=real_8), INTENT(IN) :: msg
28263  CLASS(mp_file_type), INTENT(IN) :: fh
28264  INTEGER(kind=file_offset), INTENT(IN) :: offset
28265 
28266 #if defined(__parallel)
28267  INTEGER :: ierr
28268 
28269  ierr = 0
28270  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_double_complex, mpi_status_ignore, ierr)
28271  IF (ierr .NE. 0) &
28272  cpabort("mpi_file_write_at_z @ mp_file_write_at_z")
28273 #else
28274  WRITE (unit=fh%handle, pos=offset + 1) msg
28275 #endif
28276  END SUBROUTINE mp_file_write_at_z
28277 
28278 ! **************************************************************************************************
28279 !> \brief (parallel) Blocking collective file write using explicit offsets
28280 !> (serial) Unformatted stream write
28281 !> \param fh ...
28282 !> \param offset ...
28283 !> \param msg ...
28284 !> \param msglen ...
28285 !> \par MPI-I/O mapping mpi_file_write_at_all
28286 !> \par STREAM-I/O mapping WRITE
28287 ! **************************************************************************************************
28288  SUBROUTINE mp_file_write_at_all_zv(fh, offset, msg, msglen)
28289  COMPLEX(kind=real_8), CONTIGUOUS, INTENT(IN) :: msg(:)
28290  CLASS(mp_file_type), INTENT(IN) :: fh
28291  INTEGER, INTENT(IN), OPTIONAL :: msglen
28292  INTEGER(kind=file_offset), INTENT(IN) :: offset
28293 
28294  INTEGER :: msg_len
28295 #if defined(__parallel)
28296  INTEGER :: ierr
28297 #endif
28298 
28299  msg_len = SIZE(msg)
28300  IF (PRESENT(msglen)) msg_len = msglen
28301 #if defined(__parallel)
28302  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_double_complex, mpi_status_ignore, ierr)
28303  IF (ierr .NE. 0) &
28304  cpabort("mpi_file_write_at_all_zv @ mp_file_write_at_all_zv")
28305 #else
28306  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
28307 #endif
28308  END SUBROUTINE mp_file_write_at_all_zv
28309 
28310 ! **************************************************************************************************
28311 !> \brief ...
28312 !> \param fh ...
28313 !> \param offset ...
28314 !> \param msg ...
28315 ! **************************************************************************************************
28316  SUBROUTINE mp_file_write_at_all_z (fh, offset, msg)
28317  COMPLEX(kind=real_8), INTENT(IN) :: msg
28318  CLASS(mp_file_type), INTENT(IN) :: fh
28319  INTEGER(kind=file_offset), INTENT(IN) :: offset
28320 
28321 #if defined(__parallel)
28322  INTEGER :: ierr
28323 
28324  ierr = 0
28325  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_double_complex, mpi_status_ignore, ierr)
28326  IF (ierr .NE. 0) &
28327  cpabort("mpi_file_write_at_all_z @ mp_file_write_at_all_z")
28328 #else
28329  WRITE (unit=fh%handle, pos=offset + 1) msg
28330 #endif
28331  END SUBROUTINE mp_file_write_at_all_z
28332 
28333 ! **************************************************************************************************
28334 !> \brief (parallel) Blocking individual file read using explicit offsets
28335 !> (serial) Unformatted stream read
28336 !> \param[in] fh file handle (file storage unit)
28337 !> \param[in] offset file offset (position)
28338 !> \param[out] msg data to be read from the file
28339 !> \param msglen ...
28340 !> \par MPI-I/O mapping mpi_file_read_at
28341 !> \par STREAM-I/O mapping READ
28342 !> \param[in](optional) msglen number of elements of data
28343 ! **************************************************************************************************
28344  SUBROUTINE mp_file_read_at_zv(fh, offset, msg, msglen)
28345  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msg(:)
28346  CLASS(mp_file_type), INTENT(IN) :: fh
28347  INTEGER, INTENT(IN), OPTIONAL :: msglen
28348  INTEGER(kind=file_offset), INTENT(IN) :: offset
28349 
28350  INTEGER :: msg_len
28351 #if defined(__parallel)
28352  INTEGER :: ierr
28353 #endif
28354 
28355  msg_len = SIZE(msg)
28356  IF (PRESENT(msglen)) msg_len = msglen
28357 #if defined(__parallel)
28358  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_double_complex, mpi_status_ignore, ierr)
28359  IF (ierr .NE. 0) &
28360  cpabort("mpi_file_read_at_zv @ mp_file_read_at_zv")
28361 #else
28362  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
28363 #endif
28364  END SUBROUTINE mp_file_read_at_zv
28365 
28366 ! **************************************************************************************************
28367 !> \brief ...
28368 !> \param fh ...
28369 !> \param offset ...
28370 !> \param msg ...
28371 ! **************************************************************************************************
28372  SUBROUTINE mp_file_read_at_z (fh, offset, msg)
28373  COMPLEX(kind=real_8), INTENT(OUT) :: msg
28374  CLASS(mp_file_type), INTENT(IN) :: fh
28375  INTEGER(kind=file_offset), INTENT(IN) :: offset
28376 
28377 #if defined(__parallel)
28378  INTEGER :: ierr
28379 
28380  ierr = 0
28381  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_double_complex, mpi_status_ignore, ierr)
28382  IF (ierr .NE. 0) &
28383  cpabort("mpi_file_read_at_z @ mp_file_read_at_z")
28384 #else
28385  READ (unit=fh%handle, pos=offset + 1) msg
28386 #endif
28387  END SUBROUTINE mp_file_read_at_z
28388 
28389 ! **************************************************************************************************
28390 !> \brief (parallel) Blocking collective file read using explicit offsets
28391 !> (serial) Unformatted stream read
28392 !> \param fh ...
28393 !> \param offset ...
28394 !> \param msg ...
28395 !> \param msglen ...
28396 !> \par MPI-I/O mapping mpi_file_read_at_all
28397 !> \par STREAM-I/O mapping READ
28398 ! **************************************************************************************************
28399  SUBROUTINE mp_file_read_at_all_zv(fh, offset, msg, msglen)
28400  COMPLEX(kind=real_8), INTENT(OUT), CONTIGUOUS :: msg(:)
28401  CLASS(mp_file_type), INTENT(IN) :: fh
28402  INTEGER, INTENT(IN), OPTIONAL :: msglen
28403  INTEGER(kind=file_offset), INTENT(IN) :: offset
28404 
28405  INTEGER :: msg_len
28406 #if defined(__parallel)
28407  INTEGER :: ierr
28408 #endif
28409 
28410  msg_len = SIZE(msg)
28411  IF (PRESENT(msglen)) msg_len = msglen
28412 #if defined(__parallel)
28413  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_double_complex, mpi_status_ignore, ierr)
28414  IF (ierr .NE. 0) &
28415  cpabort("mpi_file_read_at_all_zv @ mp_file_read_at_all_zv")
28416 #else
28417  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
28418 #endif
28419  END SUBROUTINE mp_file_read_at_all_zv
28420 
28421 ! **************************************************************************************************
28422 !> \brief ...
28423 !> \param fh ...
28424 !> \param offset ...
28425 !> \param msg ...
28426 ! **************************************************************************************************
28427  SUBROUTINE mp_file_read_at_all_z (fh, offset, msg)
28428  COMPLEX(kind=real_8), INTENT(OUT) :: msg
28429  CLASS(mp_file_type), INTENT(IN) :: fh
28430  INTEGER(kind=file_offset), INTENT(IN) :: offset
28431 
28432 #if defined(__parallel)
28433  INTEGER :: ierr
28434 
28435  ierr = 0
28436  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_double_complex, mpi_status_ignore, ierr)
28437  IF (ierr .NE. 0) &
28438  cpabort("mpi_file_read_at_all_z @ mp_file_read_at_all_z")
28439 #else
28440  READ (unit=fh%handle, pos=offset + 1) msg
28441 #endif
28442  END SUBROUTINE mp_file_read_at_all_z
28443 
28444 ! **************************************************************************************************
28445 !> \brief ...
28446 !> \param ptr ...
28447 !> \param vector_descriptor ...
28448 !> \param index_descriptor ...
28449 !> \return ...
28450 ! **************************************************************************************************
28451  FUNCTION mp_type_make_z (ptr, &
28452  vector_descriptor, index_descriptor) &
28453  result(type_descriptor)
28454  COMPLEX(kind=real_8), DIMENSION(:), TARGET, asynchronous :: ptr
28455  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
28456  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
28457  TYPE(mp_type_descriptor_type) :: type_descriptor
28458 
28459  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_z'
28460 
28461 #if defined(__parallel)
28462  INTEGER :: ierr
28463 #endif
28464 
28465  NULLIFY (type_descriptor%subtype)
28466  type_descriptor%length = SIZE(ptr)
28467 #if defined(__parallel)
28468  type_descriptor%type_handle = mpi_double_complex
28469  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
28470  IF (ierr /= 0) &
28471  cpabort("MPI_Get_address @ "//routinen)
28472 #else
28473  type_descriptor%type_handle = 7
28474 #endif
28475  type_descriptor%vector_descriptor(1:2) = 1
28476  type_descriptor%has_indexing = .false.
28477  type_descriptor%data_z => ptr
28478  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
28479  cpabort(routinen//": Vectors and indices NYI")
28480  END IF
28481  END FUNCTION mp_type_make_z
28482 
28483 ! **************************************************************************************************
28484 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
28485 !> as the Fortran version returns an integer, which we take to be a C_PTR
28486 !> \param DATA data array to allocate
28487 !> \param[in] len length (in data elements) of data array allocation
28488 !> \param[out] stat (optional) allocation status result
28489 ! **************************************************************************************************
28490  SUBROUTINE mp_alloc_mem_z (DATA, len, stat)
28491  COMPLEX(kind=real_8), CONTIGUOUS, DIMENSION(:), POINTER :: data
28492  INTEGER, INTENT(IN) :: len
28493  INTEGER, INTENT(OUT), OPTIONAL :: stat
28494 
28495 #if defined(__parallel)
28496  INTEGER :: size, ierr, length, &
28497  mp_res
28498  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
28499  TYPE(c_ptr) :: mp_baseptr
28500  mpi_info_type :: mp_info
28501 
28502  length = max(len, 1)
28503  CALL mpi_type_size(mpi_double_complex, size, ierr)
28504  mp_size = int(length, kind=mpi_address_kind)*size
28505  IF (mp_size .GT. mp_max_memory_size) THEN
28506  cpabort("MPI cannot allocate more than 2 GiByte")
28507  END IF
28508  mp_info = mpi_info_null
28509  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
28510  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
28511  IF (PRESENT(stat)) stat = mp_res
28512 #else
28513  INTEGER :: length, mystat
28514  length = max(len, 1)
28515  IF (PRESENT(stat)) THEN
28516  ALLOCATE (DATA(length), stat=mystat)
28517  stat = mystat ! show to convention checker that stat is used
28518  ELSE
28519  ALLOCATE (DATA(length))
28520  END IF
28521 #endif
28522  END SUBROUTINE mp_alloc_mem_z
28523 
28524 ! **************************************************************************************************
28525 !> \brief Deallocates am array, ... this is hackish
28526 !> as the Fortran version takes an integer, which we hope to get by reference
28527 !> \param DATA data array to allocate
28528 !> \param[out] stat (optional) allocation status result
28529 ! **************************************************************************************************
28530  SUBROUTINE mp_free_mem_z (DATA, stat)
28531  COMPLEX(kind=real_8), DIMENSION(:), &
28532  POINTER, asynchronous :: data
28533  INTEGER, INTENT(OUT), OPTIONAL :: stat
28534 
28535 #if defined(__parallel)
28536  INTEGER :: mp_res
28537  CALL mpi_free_mem(DATA, mp_res)
28538  IF (PRESENT(stat)) stat = mp_res
28539 #else
28540  DEALLOCATE (data)
28541  IF (PRESENT(stat)) stat = 0
28542 #endif
28543  END SUBROUTINE mp_free_mem_z
28544 ! **************************************************************************************************
28545 !> \brief Shift around the data in msg
28546 !> \param[in,out] msg Rank-2 data to shift
28547 !> \param[in] comm message passing environment identifier
28548 !> \param[in] displ_in displacements (?)
28549 !> \par Example
28550 !> msg will be moved from rank to rank+displ_in (in a circular way)
28551 !> \par Limitations
28552 !> * displ_in will be 1 by default (others not tested)
28553 !> * the message array needs to be the same size on all processes
28554 ! **************************************************************************************************
28555  SUBROUTINE mp_shift_cm(msg, comm, displ_in)
28556 
28557  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
28558  CLASS(mp_comm_type), INTENT(IN) :: comm
28559  INTEGER, INTENT(IN), OPTIONAL :: displ_in
28560 
28561  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_cm'
28562 
28563  INTEGER :: handle, ierror
28564 #if defined(__parallel)
28565  INTEGER :: displ, left, &
28566  msglen, myrank, nprocs, &
28567  right, tag
28568 #endif
28569 
28570  ierror = 0
28571  CALL mp_timeset(routinen, handle)
28572 
28573 #if defined(__parallel)
28574  CALL mpi_comm_rank(comm%handle, myrank, ierror)
28575  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
28576  CALL mpi_comm_size(comm%handle, nprocs, ierror)
28577  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
28578  IF (PRESENT(displ_in)) THEN
28579  displ = displ_in
28580  ELSE
28581  displ = 1
28582  END IF
28583  right = modulo(myrank + displ, nprocs)
28584  left = modulo(myrank - displ, nprocs)
28585  tag = 17
28586  msglen = SIZE(msg)
28587  CALL mpi_sendrecv_replace(msg, msglen, mpi_complex, right, tag, left, tag, &
28588  comm%handle, mpi_status_ignore, ierror)
28589  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
28590  CALL add_perf(perf_id=7, count=1, msg_size=msglen*(2*real_4_size))
28591 #else
28592  mark_used(msg)
28593  mark_used(comm)
28594  mark_used(displ_in)
28595 #endif
28596  CALL mp_timestop(handle)
28597 
28598  END SUBROUTINE mp_shift_cm
28599 
28600 ! **************************************************************************************************
28601 !> \brief Shift around the data in msg
28602 !> \param[in,out] msg Data to shift
28603 !> \param[in] comm message passing environment identifier
28604 !> \param[in] displ_in displacements (?)
28605 !> \par Example
28606 !> msg will be moved from rank to rank+displ_in (in a circular way)
28607 !> \par Limitations
28608 !> * displ_in will be 1 by default (others not tested)
28609 !> * the message array needs to be the same size on all processes
28610 ! **************************************************************************************************
28611  SUBROUTINE mp_shift_c (msg, comm, displ_in)
28612 
28613  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
28614  CLASS(mp_comm_type), INTENT(IN) :: comm
28615  INTEGER, INTENT(IN), OPTIONAL :: displ_in
28616 
28617  CHARACTER(len=*), PARAMETER :: routinen = 'mp_shift_c'
28618 
28619  INTEGER :: handle, ierror
28620 #if defined(__parallel)
28621  INTEGER :: displ, left, &
28622  msglen, myrank, nprocs, &
28623  right, tag
28624 #endif
28625 
28626  ierror = 0
28627  CALL mp_timeset(routinen, handle)
28628 
28629 #if defined(__parallel)
28630  CALL mpi_comm_rank(comm%handle, myrank, ierror)
28631  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_rank @ "//routinen)
28632  CALL mpi_comm_size(comm%handle, nprocs, ierror)
28633  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_comm_size @ "//routinen)
28634  IF (PRESENT(displ_in)) THEN
28635  displ = displ_in
28636  ELSE
28637  displ = 1
28638  END IF
28639  right = modulo(myrank + displ, nprocs)
28640  left = modulo(myrank - displ, nprocs)
28641  tag = 19
28642  msglen = SIZE(msg)
28643  CALL mpi_sendrecv_replace(msg, msglen, mpi_complex, right, tag, left, &
28644  tag, comm%handle, mpi_status_ignore, ierror)
28645  IF (ierror /= 0) CALL mp_stop(ierror, "mpi_sendrecv_replace @ "//routinen)
28646  CALL add_perf(perf_id=7, count=1, msg_size=msglen*(2*real_4_size))
28647 #else
28648  mark_used(msg)
28649  mark_used(comm)
28650  mark_used(displ_in)
28651 #endif
28652  CALL mp_timestop(handle)
28653 
28654  END SUBROUTINE mp_shift_c
28655 
28656 ! **************************************************************************************************
28657 !> \brief All-to-all data exchange, rank-1 data of different sizes
28658 !> \param[in] sb Data to send
28659 !> \param[in] scount Data counts for data sent to other processes
28660 !> \param[in] sdispl Respective data offsets for data sent to process
28661 !> \param[in,out] rb Buffer into which to receive data
28662 !> \param[in] rcount Data counts for data received from other
28663 !> processes
28664 !> \param[in] rdispl Respective data offsets for data received from
28665 !> other processes
28666 !> \param[in] comm Message passing environment identifier
28667 !> \par MPI mapping
28668 !> mpi_alltoallv
28669 !> \par Array sizes
28670 !> The scount, rcount, and the sdispl and rdispl arrays have a
28671 !> size equal to the number of processes.
28672 !> \par Offsets
28673 !> Values in sdispl and rdispl start with 0.
28674 ! **************************************************************************************************
28675  SUBROUTINE mp_alltoall_c11v(sb, scount, sdispl, rb, rcount, rdispl, comm)
28676 
28677  COMPLEX(kind=real_4), DIMENSION(:), INTENT(IN), CONTIGUOUS :: sb
28678  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
28679  COMPLEX(kind=real_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: rb
28680  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
28681  CLASS(mp_comm_type), INTENT(IN) :: comm
28682 
28683  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c11v'
28684 
28685  INTEGER :: handle
28686 #if defined(__parallel)
28687  INTEGER :: ierr, msglen
28688 #else
28689  INTEGER :: i
28690 #endif
28691 
28692  CALL mp_timeset(routinen, handle)
28693 
28694 #if defined(__parallel)
28695  CALL mpi_alltoallv(sb, scount, sdispl, mpi_complex, &
28696  rb, rcount, rdispl, mpi_complex, comm%handle, ierr)
28697  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
28698  msglen = sum(scount) + sum(rcount)
28699  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28700 #else
28701  mark_used(comm)
28702  mark_used(scount)
28703  mark_used(sdispl)
28704  !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(rcount,rdispl,sdispl,rb,sb)
28705  DO i = 1, rcount(1)
28706  rb(rdispl(1) + i) = sb(sdispl(1) + i)
28707  END DO
28708 #endif
28709  CALL mp_timestop(handle)
28710 
28711  END SUBROUTINE mp_alltoall_c11v
28712 
28713 ! **************************************************************************************************
28714 !> \brief All-to-all data exchange, rank-2 data of different sizes
28715 !> \param sb ...
28716 !> \param scount ...
28717 !> \param sdispl ...
28718 !> \param rb ...
28719 !> \param rcount ...
28720 !> \param rdispl ...
28721 !> \param comm ...
28722 !> \par MPI mapping
28723 !> mpi_alltoallv
28724 !> \note see mp_alltoall_c11v
28725 ! **************************************************************************************************
28726  SUBROUTINE mp_alltoall_c22v(sb, scount, sdispl, rb, rcount, rdispl, comm)
28727 
28728  COMPLEX(kind=real_4), DIMENSION(:, :), &
28729  INTENT(IN), CONTIGUOUS :: sb
28730  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: scount, sdispl
28731  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, &
28732  INTENT(INOUT) :: rb
28733  INTEGER, DIMENSION(:), INTENT(IN), CONTIGUOUS :: rcount, rdispl
28734  CLASS(mp_comm_type), INTENT(IN) :: comm
28735 
28736  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c22v'
28737 
28738  INTEGER :: handle
28739 #if defined(__parallel)
28740  INTEGER :: ierr, msglen
28741 #endif
28742 
28743  CALL mp_timeset(routinen, handle)
28744 
28745 #if defined(__parallel)
28746  CALL mpi_alltoallv(sb, scount, sdispl, mpi_complex, &
28747  rb, rcount, rdispl, mpi_complex, comm%handle, ierr)
28748  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoallv @ "//routinen)
28749  msglen = sum(scount) + sum(rcount)
28750  CALL add_perf(perf_id=6, count=1, msg_size=msglen*2*(2*real_4_size))
28751 #else
28752  mark_used(comm)
28753  mark_used(scount)
28754  mark_used(sdispl)
28755  mark_used(rcount)
28756  mark_used(rdispl)
28757  rb = sb
28758 #endif
28759  CALL mp_timestop(handle)
28760 
28761  END SUBROUTINE mp_alltoall_c22v
28762 
28763 ! **************************************************************************************************
28764 !> \brief All-to-all data exchange, rank 1 arrays, equal sizes
28765 !> \param[in] sb array with data to send
28766 !> \param[out] rb array into which data is received
28767 !> \param[in] count number of elements to send/receive (product of the
28768 !> extents of the first two dimensions)
28769 !> \param[in] comm Message passing environment identifier
28770 !> \par Index meaning
28771 !> \par The first two indices specify the data while the last index counts
28772 !> the processes
28773 !> \par Sizes of ranks
28774 !> All processes have the same data size.
28775 !> \par MPI mapping
28776 !> mpi_alltoall
28777 ! **************************************************************************************************
28778  SUBROUTINE mp_alltoall_c (sb, rb, count, comm)
28779 
28780  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sb
28781  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: rb
28782  INTEGER, INTENT(IN) :: count
28783  CLASS(mp_comm_type), INTENT(IN) :: comm
28784 
28785  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c'
28786 
28787  INTEGER :: handle
28788 #if defined(__parallel)
28789  INTEGER :: ierr, msglen, np
28790 #endif
28791 
28792  CALL mp_timeset(routinen, handle)
28793 
28794 #if defined(__parallel)
28795  CALL mpi_alltoall(sb, count, mpi_complex, &
28796  rb, count, mpi_complex, comm%handle, ierr)
28797  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
28798  CALL mpi_comm_size(comm%handle, np, ierr)
28799  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
28800  msglen = 2*count*np
28801  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28802 #else
28803  mark_used(count)
28804  mark_used(comm)
28805  rb = sb
28806 #endif
28807  CALL mp_timestop(handle)
28808 
28809  END SUBROUTINE mp_alltoall_c
28810 
28811 ! **************************************************************************************************
28812 !> \brief All-to-all data exchange, rank-2 arrays, equal sizes
28813 !> \param sb ...
28814 !> \param rb ...
28815 !> \param count ...
28816 !> \param commp ...
28817 !> \note see mp_alltoall_c
28818 ! **************************************************************************************************
28819  SUBROUTINE mp_alltoall_c22(sb, rb, count, comm)
28820 
28821  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sb
28822  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: rb
28823  INTEGER, INTENT(IN) :: count
28824  CLASS(mp_comm_type), INTENT(IN) :: comm
28825 
28826  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c22'
28827 
28828  INTEGER :: handle
28829 #if defined(__parallel)
28830  INTEGER :: ierr, msglen, np
28831 #endif
28832 
28833  CALL mp_timeset(routinen, handle)
28834 
28835 #if defined(__parallel)
28836  CALL mpi_alltoall(sb, count, mpi_complex, &
28837  rb, count, mpi_complex, comm%handle, ierr)
28838  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
28839  CALL mpi_comm_size(comm%handle, np, ierr)
28840  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
28841  msglen = 2*SIZE(sb)*np
28842  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28843 #else
28844  mark_used(count)
28845  mark_used(comm)
28846  rb = sb
28847 #endif
28848  CALL mp_timestop(handle)
28849 
28850  END SUBROUTINE mp_alltoall_c22
28851 
28852 ! **************************************************************************************************
28853 !> \brief All-to-all data exchange, rank-3 data with equal sizes
28854 !> \param sb ...
28855 !> \param rb ...
28856 !> \param count ...
28857 !> \param comm ...
28858 !> \note see mp_alltoall_c
28859 ! **************************************************************************************************
28860  SUBROUTINE mp_alltoall_c33(sb, rb, count, comm)
28861 
28862  COMPLEX(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(IN) :: sb
28863  COMPLEX(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, INTENT(OUT) :: rb
28864  INTEGER, INTENT(IN) :: count
28865  CLASS(mp_comm_type), INTENT(IN) :: comm
28866 
28867  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c33'
28868 
28869  INTEGER :: handle
28870 #if defined(__parallel)
28871  INTEGER :: ierr, msglen, np
28872 #endif
28873 
28874  CALL mp_timeset(routinen, handle)
28875 
28876 #if defined(__parallel)
28877  CALL mpi_alltoall(sb, count, mpi_complex, &
28878  rb, count, mpi_complex, comm%handle, ierr)
28879  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
28880  CALL mpi_comm_size(comm%handle, np, ierr)
28881  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
28882  msglen = 2*count*np
28883  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28884 #else
28885  mark_used(count)
28886  mark_used(comm)
28887  rb = sb
28888 #endif
28889  CALL mp_timestop(handle)
28890 
28891  END SUBROUTINE mp_alltoall_c33
28892 
28893 ! **************************************************************************************************
28894 !> \brief All-to-all data exchange, rank 4 data, equal sizes
28895 !> \param sb ...
28896 !> \param rb ...
28897 !> \param count ...
28898 !> \param comm ...
28899 !> \note see mp_alltoall_c
28900 ! **************************************************************************************************
28901  SUBROUTINE mp_alltoall_c44(sb, rb, count, comm)
28902 
28903  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
28904  INTENT(IN) :: sb
28905  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
28906  INTENT(OUT) :: rb
28907  INTEGER, INTENT(IN) :: count
28908  CLASS(mp_comm_type), INTENT(IN) :: comm
28909 
28910  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c44'
28911 
28912  INTEGER :: handle
28913 #if defined(__parallel)
28914  INTEGER :: ierr, msglen, np
28915 #endif
28916 
28917  CALL mp_timeset(routinen, handle)
28918 
28919 #if defined(__parallel)
28920  CALL mpi_alltoall(sb, count, mpi_complex, &
28921  rb, count, mpi_complex, comm%handle, ierr)
28922  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
28923  CALL mpi_comm_size(comm%handle, np, ierr)
28924  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
28925  msglen = 2*count*np
28926  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28927 #else
28928  mark_used(count)
28929  mark_used(comm)
28930  rb = sb
28931 #endif
28932  CALL mp_timestop(handle)
28933 
28934  END SUBROUTINE mp_alltoall_c44
28935 
28936 ! **************************************************************************************************
28937 !> \brief All-to-all data exchange, rank 5 data, equal sizes
28938 !> \param sb ...
28939 !> \param rb ...
28940 !> \param count ...
28941 !> \param comm ...
28942 !> \note see mp_alltoall_c
28943 ! **************************************************************************************************
28944  SUBROUTINE mp_alltoall_c55(sb, rb, count, comm)
28945 
28946  COMPLEX(kind=real_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
28947  INTENT(IN) :: sb
28948  COMPLEX(kind=real_4), DIMENSION(:, :, :, :, :), CONTIGUOUS, &
28949  INTENT(OUT) :: rb
28950  INTEGER, INTENT(IN) :: count
28951  CLASS(mp_comm_type), INTENT(IN) :: comm
28952 
28953  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c55'
28954 
28955  INTEGER :: handle
28956 #if defined(__parallel)
28957  INTEGER :: ierr, msglen, np
28958 #endif
28959 
28960  CALL mp_timeset(routinen, handle)
28961 
28962 #if defined(__parallel)
28963  CALL mpi_alltoall(sb, count, mpi_complex, &
28964  rb, count, mpi_complex, comm%handle, ierr)
28965  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
28966  CALL mpi_comm_size(comm%handle, np, ierr)
28967  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
28968  msglen = 2*count*np
28969  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
28970 #else
28971  mark_used(count)
28972  mark_used(comm)
28973  rb = sb
28974 #endif
28975  CALL mp_timestop(handle)
28976 
28977  END SUBROUTINE mp_alltoall_c55
28978 
28979 ! **************************************************************************************************
28980 !> \brief All-to-all data exchange, rank-4 data to rank-5 data
28981 !> \param sb ...
28982 !> \param rb ...
28983 !> \param count ...
28984 !> \param comm ...
28985 !> \note see mp_alltoall_c
28986 !> \note User must ensure size consistency.
28987 ! **************************************************************************************************
28988  SUBROUTINE mp_alltoall_c45(sb, rb, count, comm)
28989 
28990  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
28991  INTENT(IN) :: sb
28992  COMPLEX(kind=real_4), &
28993  DIMENSION(:, :, :, :, :), INTENT(OUT), CONTIGUOUS :: rb
28994  INTEGER, INTENT(IN) :: count
28995  CLASS(mp_comm_type), INTENT(IN) :: comm
28996 
28997  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c45'
28998 
28999  INTEGER :: handle
29000 #if defined(__parallel)
29001  INTEGER :: ierr, msglen, np
29002 #endif
29003 
29004  CALL mp_timeset(routinen, handle)
29005 
29006 #if defined(__parallel)
29007  CALL mpi_alltoall(sb, count, mpi_complex, &
29008  rb, count, mpi_complex, comm%handle, ierr)
29009  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
29010  CALL mpi_comm_size(comm%handle, np, ierr)
29011  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
29012  msglen = 2*count*np
29013  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
29014 #else
29015  mark_used(count)
29016  mark_used(comm)
29017  rb = reshape(sb, shape(rb))
29018 #endif
29019  CALL mp_timestop(handle)
29020 
29021  END SUBROUTINE mp_alltoall_c45
29022 
29023 ! **************************************************************************************************
29024 !> \brief All-to-all data exchange, rank-3 data to rank-4 data
29025 !> \param sb ...
29026 !> \param rb ...
29027 !> \param count ...
29028 !> \param comm ...
29029 !> \note see mp_alltoall_c
29030 !> \note User must ensure size consistency.
29031 ! **************************************************************************************************
29032  SUBROUTINE mp_alltoall_c34(sb, rb, count, comm)
29033 
29034  COMPLEX(kind=real_4), DIMENSION(:, :, :), CONTIGUOUS, &
29035  INTENT(IN) :: sb
29036  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
29037  INTENT(OUT) :: rb
29038  INTEGER, INTENT(IN) :: count
29039  CLASS(mp_comm_type), INTENT(IN) :: comm
29040 
29041  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c34'
29042 
29043  INTEGER :: handle
29044 #if defined(__parallel)
29045  INTEGER :: ierr, msglen, np
29046 #endif
29047 
29048  CALL mp_timeset(routinen, handle)
29049 
29050 #if defined(__parallel)
29051  CALL mpi_alltoall(sb, count, mpi_complex, &
29052  rb, count, mpi_complex, comm%handle, ierr)
29053  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
29054  CALL mpi_comm_size(comm%handle, np, ierr)
29055  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
29056  msglen = 2*count*np
29057  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
29058 #else
29059  mark_used(count)
29060  mark_used(comm)
29061  rb = reshape(sb, shape(rb))
29062 #endif
29063  CALL mp_timestop(handle)
29064 
29065  END SUBROUTINE mp_alltoall_c34
29066 
29067 ! **************************************************************************************************
29068 !> \brief All-to-all data exchange, rank-5 data to rank-4 data
29069 !> \param sb ...
29070 !> \param rb ...
29071 !> \param count ...
29072 !> \param comm ...
29073 !> \note see mp_alltoall_c
29074 !> \note User must ensure size consistency.
29075 ! **************************************************************************************************
29076  SUBROUTINE mp_alltoall_c54(sb, rb, count, comm)
29077 
29078  COMPLEX(kind=real_4), &
29079  DIMENSION(:, :, :, :, :), CONTIGUOUS, INTENT(IN) :: sb
29080  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), CONTIGUOUS, &
29081  INTENT(OUT) :: rb
29082  INTEGER, INTENT(IN) :: count
29083  CLASS(mp_comm_type), INTENT(IN) :: comm
29084 
29085  CHARACTER(len=*), PARAMETER :: routinen = 'mp_alltoall_c54'
29086 
29087  INTEGER :: handle
29088 #if defined(__parallel)
29089  INTEGER :: ierr, msglen, np
29090 #endif
29091 
29092  CALL mp_timeset(routinen, handle)
29093 
29094 #if defined(__parallel)
29095  CALL mpi_alltoall(sb, count, mpi_complex, &
29096  rb, count, mpi_complex, comm%handle, ierr)
29097  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_alltoall @ "//routinen)
29098  CALL mpi_comm_size(comm%handle, np, ierr)
29099  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_size @ "//routinen)
29100  msglen = 2*count*np
29101  CALL add_perf(perf_id=6, count=1, msg_size=msglen*(2*real_4_size))
29102 #else
29103  mark_used(count)
29104  mark_used(comm)
29105  rb = reshape(sb, shape(rb))
29106 #endif
29107  CALL mp_timestop(handle)
29108 
29109  END SUBROUTINE mp_alltoall_c54
29110 
29111 ! **************************************************************************************************
29112 !> \brief Send one datum to another process
29113 !> \param[in] msg Scalar to send
29114 !> \param[in] dest Destination process
29115 !> \param[in] tag Transfer identifier
29116 !> \param[in] comm Message passing environment identifier
29117 !> \par MPI mapping
29118 !> mpi_send
29119 ! **************************************************************************************************
29120  SUBROUTINE mp_send_c (msg, dest, tag, comm)
29121  COMPLEX(kind=real_4), INTENT(IN) :: msg
29122  INTEGER, INTENT(IN) :: dest, tag
29123  CLASS(mp_comm_type), INTENT(IN) :: comm
29124 
29125  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_c'
29126 
29127  INTEGER :: handle
29128 #if defined(__parallel)
29129  INTEGER :: ierr, msglen
29130 #endif
29131 
29132  CALL mp_timeset(routinen, handle)
29133 
29134 #if defined(__parallel)
29135  msglen = 1
29136  CALL mpi_send(msg, msglen, mpi_complex, dest, tag, comm%handle, ierr)
29137  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
29138  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_4_size))
29139 #else
29140  mark_used(msg)
29141  mark_used(dest)
29142  mark_used(tag)
29143  mark_used(comm)
29144  ! only defined in parallel
29145  cpabort("not in parallel mode")
29146 #endif
29147  CALL mp_timestop(handle)
29148  END SUBROUTINE mp_send_c
29149 
29150 ! **************************************************************************************************
29151 !> \brief Send rank-1 data to another process
29152 !> \param[in] msg Rank-1 data to send
29153 !> \param dest ...
29154 !> \param tag ...
29155 !> \param comm ...
29156 !> \note see mp_send_c
29157 ! **************************************************************************************************
29158  SUBROUTINE mp_send_cv(msg, dest, tag, comm)
29159  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
29160  INTEGER, INTENT(IN) :: dest, tag
29161  CLASS(mp_comm_type), INTENT(IN) :: comm
29162 
29163  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_cv'
29164 
29165  INTEGER :: handle
29166 #if defined(__parallel)
29167  INTEGER :: ierr, msglen
29168 #endif
29169 
29170  CALL mp_timeset(routinen, handle)
29171 
29172 #if defined(__parallel)
29173  msglen = SIZE(msg)
29174  CALL mpi_send(msg, msglen, mpi_complex, dest, tag, comm%handle, ierr)
29175  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
29176  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_4_size))
29177 #else
29178  mark_used(msg)
29179  mark_used(dest)
29180  mark_used(tag)
29181  mark_used(comm)
29182  ! only defined in parallel
29183  cpabort("not in parallel mode")
29184 #endif
29185  CALL mp_timestop(handle)
29186  END SUBROUTINE mp_send_cv
29187 
29188 ! **************************************************************************************************
29189 !> \brief Send rank-2 data to another process
29190 !> \param[in] msg Rank-2 data to send
29191 !> \param dest ...
29192 !> \param tag ...
29193 !> \param comm ...
29194 !> \note see mp_send_c
29195 ! **************************************************************************************************
29196  SUBROUTINE mp_send_cm2(msg, dest, tag, comm)
29197  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
29198  INTEGER, INTENT(IN) :: dest, tag
29199  CLASS(mp_comm_type), INTENT(IN) :: comm
29200 
29201  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_cm2'
29202 
29203  INTEGER :: handle
29204 #if defined(__parallel)
29205  INTEGER :: ierr, msglen
29206 #endif
29207 
29208  CALL mp_timeset(routinen, handle)
29209 
29210 #if defined(__parallel)
29211  msglen = SIZE(msg)
29212  CALL mpi_send(msg, msglen, mpi_complex, dest, tag, comm%handle, ierr)
29213  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
29214  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_4_size))
29215 #else
29216  mark_used(msg)
29217  mark_used(dest)
29218  mark_used(tag)
29219  mark_used(comm)
29220  ! only defined in parallel
29221  cpabort("not in parallel mode")
29222 #endif
29223  CALL mp_timestop(handle)
29224  END SUBROUTINE mp_send_cm2
29225 
29226 ! **************************************************************************************************
29227 !> \brief Send rank-3 data to another process
29228 !> \param[in] msg Rank-3 data to send
29229 !> \param dest ...
29230 !> \param tag ...
29231 !> \param comm ...
29232 !> \note see mp_send_c
29233 ! **************************************************************************************************
29234  SUBROUTINE mp_send_cm3(msg, dest, tag, comm)
29235  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :, :)
29236  INTEGER, INTENT(IN) :: dest, tag
29237  CLASS(mp_comm_type), INTENT(IN) :: comm
29238 
29239  CHARACTER(len=*), PARAMETER :: routinen = 'mp_send_${nametype1}m3'
29240 
29241  INTEGER :: handle
29242 #if defined(__parallel)
29243  INTEGER :: ierr, msglen
29244 #endif
29245 
29246  CALL mp_timeset(routinen, handle)
29247 
29248 #if defined(__parallel)
29249  msglen = SIZE(msg)
29250  CALL mpi_send(msg, msglen, mpi_complex, dest, tag, comm%handle, ierr)
29251  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_send @ "//routinen)
29252  CALL add_perf(perf_id=13, count=1, msg_size=msglen*(2*real_4_size))
29253 #else
29254  mark_used(msg)
29255  mark_used(dest)
29256  mark_used(tag)
29257  mark_used(comm)
29258  ! only defined in parallel
29259  cpabort("not in parallel mode")
29260 #endif
29261  CALL mp_timestop(handle)
29262  END SUBROUTINE mp_send_cm3
29263 
29264 ! **************************************************************************************************
29265 !> \brief Receive one datum from another process
29266 !> \param[in,out] msg Place received data into this variable
29267 !> \param[in,out] source Process to receive from
29268 !> \param[in,out] tag Transfer identifier
29269 !> \param[in] comm Message passing environment identifier
29270 !> \par MPI mapping
29271 !> mpi_send
29272 ! **************************************************************************************************
29273  SUBROUTINE mp_recv_c (msg, source, tag, comm)
29274  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
29275  INTEGER, INTENT(INOUT) :: source, tag
29276  CLASS(mp_comm_type), INTENT(IN) :: comm
29277 
29278  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_c'
29279 
29280  INTEGER :: handle
29281 #if defined(__parallel)
29282  INTEGER :: ierr, msglen
29283  mpi_status_type :: status
29284 #endif
29285 
29286  CALL mp_timeset(routinen, handle)
29287 
29288 #if defined(__parallel)
29289  msglen = 1
29290  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
29291  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
29292  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29293  ELSE
29294  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, status, ierr)
29295  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29296  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_4_size))
29297  source = status mpi_status_extract(mpi_source)
29298  tag = status mpi_status_extract(mpi_tag)
29299  END IF
29300 #else
29301  mark_used(msg)
29302  mark_used(source)
29303  mark_used(tag)
29304  mark_used(comm)
29305  ! only defined in parallel
29306  cpabort("not in parallel mode")
29307 #endif
29308  CALL mp_timestop(handle)
29309  END SUBROUTINE mp_recv_c
29310 
29311 ! **************************************************************************************************
29312 !> \brief Receive rank-1 data from another process
29313 !> \param[in,out] msg Place received data into this rank-1 array
29314 !> \param source ...
29315 !> \param tag ...
29316 !> \param comm ...
29317 !> \note see mp_recv_c
29318 ! **************************************************************************************************
29319  SUBROUTINE mp_recv_cv(msg, source, tag, comm)
29320  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
29321  INTEGER, INTENT(INOUT) :: source, tag
29322  CLASS(mp_comm_type), INTENT(IN) :: comm
29323 
29324  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_cv'
29325 
29326  INTEGER :: handle
29327 #if defined(__parallel)
29328  INTEGER :: ierr, msglen
29329  mpi_status_type :: status
29330 #endif
29331 
29332  CALL mp_timeset(routinen, handle)
29333 
29334 #if defined(__parallel)
29335  msglen = SIZE(msg)
29336  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
29337  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
29338  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29339  ELSE
29340  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, status, ierr)
29341  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29342  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_4_size))
29343  source = status mpi_status_extract(mpi_source)
29344  tag = status mpi_status_extract(mpi_tag)
29345  END IF
29346 #else
29347  mark_used(msg)
29348  mark_used(source)
29349  mark_used(tag)
29350  mark_used(comm)
29351  ! only defined in parallel
29352  cpabort("not in parallel mode")
29353 #endif
29354  CALL mp_timestop(handle)
29355  END SUBROUTINE mp_recv_cv
29356 
29357 ! **************************************************************************************************
29358 !> \brief Receive rank-2 data from another process
29359 !> \param[in,out] msg Place received data into this rank-2 array
29360 !> \param source ...
29361 !> \param tag ...
29362 !> \param comm ...
29363 !> \note see mp_recv_c
29364 ! **************************************************************************************************
29365  SUBROUTINE mp_recv_cm2(msg, source, tag, comm)
29366  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
29367  INTEGER, INTENT(INOUT) :: source, tag
29368  CLASS(mp_comm_type), INTENT(IN) :: comm
29369 
29370  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_cm2'
29371 
29372  INTEGER :: handle
29373 #if defined(__parallel)
29374  INTEGER :: ierr, msglen
29375  mpi_status_type :: status
29376 #endif
29377 
29378  CALL mp_timeset(routinen, handle)
29379 
29380 #if defined(__parallel)
29381  msglen = SIZE(msg)
29382  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
29383  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
29384  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29385  ELSE
29386  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, status, ierr)
29387  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29388  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_4_size))
29389  source = status mpi_status_extract(mpi_source)
29390  tag = status mpi_status_extract(mpi_tag)
29391  END IF
29392 #else
29393  mark_used(msg)
29394  mark_used(source)
29395  mark_used(tag)
29396  mark_used(comm)
29397  ! only defined in parallel
29398  cpabort("not in parallel mode")
29399 #endif
29400  CALL mp_timestop(handle)
29401  END SUBROUTINE mp_recv_cm2
29402 
29403 ! **************************************************************************************************
29404 !> \brief Receive rank-3 data from another process
29405 !> \param[in,out] msg Place received data into this rank-3 array
29406 !> \param source ...
29407 !> \param tag ...
29408 !> \param comm ...
29409 !> \note see mp_recv_c
29410 ! **************************************************************************************************
29411  SUBROUTINE mp_recv_cm3(msg, source, tag, comm)
29412  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :)
29413  INTEGER, INTENT(INOUT) :: source, tag
29414  CLASS(mp_comm_type), INTENT(IN) :: comm
29415 
29416  CHARACTER(len=*), PARAMETER :: routinen = 'mp_recv_cm3'
29417 
29418  INTEGER :: handle
29419 #if defined(__parallel)
29420  INTEGER :: ierr, msglen
29421  mpi_status_type :: status
29422 #endif
29423 
29424  CALL mp_timeset(routinen, handle)
29425 
29426 #if defined(__parallel)
29427  msglen = SIZE(msg)
29428  IF (source /= mp_any_source .AND. tag /= mp_any_tag) THEN
29429  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, mpi_status_ignore, ierr)
29430  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29431  ELSE
29432  CALL mpi_recv(msg, msglen, mpi_complex, source, tag, comm%handle, status, ierr)
29433  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_recv @ "//routinen)
29434  CALL add_perf(perf_id=14, count=1, msg_size=msglen*(2*real_4_size))
29435  source = status mpi_status_extract(mpi_source)
29436  tag = status mpi_status_extract(mpi_tag)
29437  END IF
29438 #else
29439  mark_used(msg)
29440  mark_used(source)
29441  mark_used(tag)
29442  mark_used(comm)
29443  ! only defined in parallel
29444  cpabort("not in parallel mode")
29445 #endif
29446  CALL mp_timestop(handle)
29447  END SUBROUTINE mp_recv_cm3
29448 
29449 ! **************************************************************************************************
29450 !> \brief Broadcasts a datum to all processes.
29451 !> \param[in] msg Datum to broadcast
29452 !> \param[in] source Processes which broadcasts
29453 !> \param[in] comm Message passing environment identifier
29454 !> \par MPI mapping
29455 !> mpi_bcast
29456 ! **************************************************************************************************
29457  SUBROUTINE mp_bcast_c (msg, source, comm)
29458  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
29459  INTEGER, INTENT(IN) :: source
29460  CLASS(mp_comm_type), INTENT(IN) :: comm
29461 
29462  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_c'
29463 
29464  INTEGER :: handle
29465 #if defined(__parallel)
29466  INTEGER :: ierr, msglen
29467 #endif
29468 
29469  CALL mp_timeset(routinen, handle)
29470 
29471 #if defined(__parallel)
29472  msglen = 1
29473  CALL mpi_bcast(msg, msglen, mpi_complex, source, comm%handle, ierr)
29474  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29475  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29476 #else
29477  mark_used(msg)
29478  mark_used(source)
29479  mark_used(comm)
29480 #endif
29481  CALL mp_timestop(handle)
29482  END SUBROUTINE mp_bcast_c
29483 
29484 ! **************************************************************************************************
29485 !> \brief Broadcasts a datum to all processes. Convenience function using the source of the communicator
29486 !> \param[in] msg Datum to broadcast
29487 !> \param[in] comm Message passing environment identifier
29488 !> \par MPI mapping
29489 !> mpi_bcast
29490 ! **************************************************************************************************
29491  SUBROUTINE mp_bcast_c_src(msg, comm)
29492  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
29493  CLASS(mp_comm_type), INTENT(IN) :: comm
29494 
29495  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_c_src'
29496 
29497  INTEGER :: handle
29498 #if defined(__parallel)
29499  INTEGER :: ierr, msglen
29500 #endif
29501 
29502  CALL mp_timeset(routinen, handle)
29503 
29504 #if defined(__parallel)
29505  msglen = 1
29506  CALL mpi_bcast(msg, msglen, mpi_complex, comm%source, comm%handle, ierr)
29507  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29508  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29509 #else
29510  mark_used(msg)
29511  mark_used(comm)
29512 #endif
29513  CALL mp_timestop(handle)
29514  END SUBROUTINE mp_bcast_c_src
29515 
29516 ! **************************************************************************************************
29517 !> \brief Broadcasts a datum to all processes.
29518 !> \param[in] msg Datum to broadcast
29519 !> \param[in] source Processes which broadcasts
29520 !> \param[in] comm Message passing environment identifier
29521 !> \par MPI mapping
29522 !> mpi_bcast
29523 ! **************************************************************************************************
29524  SUBROUTINE mp_ibcast_c (msg, source, comm, request)
29525  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
29526  INTEGER, INTENT(IN) :: source
29527  CLASS(mp_comm_type), INTENT(IN) :: comm
29528  TYPE(mp_request_type), INTENT(OUT) :: request
29529 
29530  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_c'
29531 
29532  INTEGER :: handle
29533 #if defined(__parallel)
29534  INTEGER :: ierr, msglen
29535 #endif
29536 
29537  CALL mp_timeset(routinen, handle)
29538 
29539 #if defined(__parallel)
29540  msglen = 1
29541  CALL mpi_ibcast(msg, msglen, mpi_complex, source, comm%handle, request%handle, ierr)
29542  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
29543  CALL add_perf(perf_id=22, count=1, msg_size=msglen*(2*real_4_size))
29544 #else
29545  mark_used(msg)
29546  mark_used(source)
29547  mark_used(comm)
29548  request = mp_request_null
29549 #endif
29550  CALL mp_timestop(handle)
29551  END SUBROUTINE mp_ibcast_c
29552 
29553 ! **************************************************************************************************
29554 !> \brief Broadcasts rank-1 data to all processes
29555 !> \param[in] msg Data to broadcast
29556 !> \param source ...
29557 !> \param comm ...
29558 !> \note see mp_bcast_c1
29559 ! **************************************************************************************************
29560  SUBROUTINE mp_bcast_cv(msg, source, comm)
29561  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
29562  INTEGER, INTENT(IN) :: source
29563  CLASS(mp_comm_type), INTENT(IN) :: comm
29564 
29565  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_cv'
29566 
29567  INTEGER :: handle
29568 #if defined(__parallel)
29569  INTEGER :: ierr, msglen
29570 #endif
29571 
29572  CALL mp_timeset(routinen, handle)
29573 
29574 #if defined(__parallel)
29575  msglen = SIZE(msg)
29576  CALL mpi_bcast(msg, msglen, mpi_complex, source, comm%handle, ierr)
29577  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29578  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29579 #else
29580  mark_used(msg)
29581  mark_used(source)
29582  mark_used(comm)
29583 #endif
29584  CALL mp_timestop(handle)
29585  END SUBROUTINE mp_bcast_cv
29586 
29587 ! **************************************************************************************************
29588 !> \brief Broadcasts rank-1 data to all processes, uses the source of the communicator, convenience function
29589 !> \param[in] msg Data to broadcast
29590 !> \param comm ...
29591 !> \note see mp_bcast_c1
29592 ! **************************************************************************************************
29593  SUBROUTINE mp_bcast_cv_src(msg, comm)
29594  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
29595  CLASS(mp_comm_type), INTENT(IN) :: comm
29596 
29597  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_cv_src'
29598 
29599  INTEGER :: handle
29600 #if defined(__parallel)
29601  INTEGER :: ierr, msglen
29602 #endif
29603 
29604  CALL mp_timeset(routinen, handle)
29605 
29606 #if defined(__parallel)
29607  msglen = SIZE(msg)
29608  CALL mpi_bcast(msg, msglen, mpi_complex, comm%source, comm%handle, ierr)
29609  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29610  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29611 #else
29612  mark_used(msg)
29613  mark_used(comm)
29614 #endif
29615  CALL mp_timestop(handle)
29616  END SUBROUTINE mp_bcast_cv_src
29617 
29618 ! **************************************************************************************************
29619 !> \brief Broadcasts rank-1 data to all processes
29620 !> \param[in] msg Data to broadcast
29621 !> \param source ...
29622 !> \param comm ...
29623 !> \note see mp_bcast_c1
29624 ! **************************************************************************************************
29625  SUBROUTINE mp_ibcast_cv(msg, source, comm, request)
29626  COMPLEX(kind=real_4), INTENT(INOUT) :: msg(:)
29627  INTEGER, INTENT(IN) :: source
29628  CLASS(mp_comm_type), INTENT(IN) :: comm
29629  TYPE(mp_request_type) :: request
29630 
29631  CHARACTER(len=*), PARAMETER :: routinen = 'mp_ibcast_cv'
29632 
29633  INTEGER :: handle
29634 #if defined(__parallel)
29635  INTEGER :: ierr, msglen
29636 #endif
29637 
29638  CALL mp_timeset(routinen, handle)
29639 
29640 #if defined(__parallel)
29641 #if !defined(__GNUC__) || __GNUC__ >= 9
29642  cpassert(is_contiguous(msg))
29643 #endif
29644  msglen = SIZE(msg)
29645  CALL mpi_ibcast(msg, msglen, mpi_complex, source, comm%handle, request%handle, ierr)
29646  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ibcast @ "//routinen)
29647  CALL add_perf(perf_id=22, count=1, msg_size=msglen*(2*real_4_size))
29648 #else
29649  mark_used(msg)
29650  mark_used(source)
29651  mark_used(comm)
29652  request = mp_request_null
29653 #endif
29654  CALL mp_timestop(handle)
29655  END SUBROUTINE mp_ibcast_cv
29656 
29657 ! **************************************************************************************************
29658 !> \brief Broadcasts rank-2 data to all processes
29659 !> \param[in] msg Data to broadcast
29660 !> \param source ...
29661 !> \param comm ...
29662 !> \note see mp_bcast_c1
29663 ! **************************************************************************************************
29664  SUBROUTINE mp_bcast_cm(msg, source, comm)
29665  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
29666  INTEGER, INTENT(IN) :: source
29667  CLASS(mp_comm_type), INTENT(IN) :: comm
29668 
29669  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_cm'
29670 
29671  INTEGER :: handle
29672 #if defined(__parallel)
29673  INTEGER :: ierr, msglen
29674 #endif
29675 
29676  CALL mp_timeset(routinen, handle)
29677 
29678 #if defined(__parallel)
29679  msglen = SIZE(msg)
29680  CALL mpi_bcast(msg, msglen, mpi_complex, source, comm%handle, ierr)
29681  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29682  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29683 #else
29684  mark_used(msg)
29685  mark_used(source)
29686  mark_used(comm)
29687 #endif
29688  CALL mp_timestop(handle)
29689  END SUBROUTINE mp_bcast_cm
29690 
29691 ! **************************************************************************************************
29692 !> \brief Broadcasts rank-2 data to all processes
29693 !> \param[in] msg Data to broadcast
29694 !> \param source ...
29695 !> \param comm ...
29696 !> \note see mp_bcast_c1
29697 ! **************************************************************************************************
29698  SUBROUTINE mp_bcast_cm_src(msg, comm)
29699  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
29700  CLASS(mp_comm_type), INTENT(IN) :: comm
29701 
29702  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_cm_src'
29703 
29704  INTEGER :: handle
29705 #if defined(__parallel)
29706  INTEGER :: ierr, msglen
29707 #endif
29708 
29709  CALL mp_timeset(routinen, handle)
29710 
29711 #if defined(__parallel)
29712  msglen = SIZE(msg)
29713  CALL mpi_bcast(msg, msglen, mpi_complex, comm%source, comm%handle, ierr)
29714  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29715  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29716 #else
29717  mark_used(msg)
29718  mark_used(comm)
29719 #endif
29720  CALL mp_timestop(handle)
29721  END SUBROUTINE mp_bcast_cm_src
29722 
29723 ! **************************************************************************************************
29724 !> \brief Broadcasts rank-3 data to all processes
29725 !> \param[in] msg Data to broadcast
29726 !> \param source ...
29727 !> \param comm ...
29728 !> \note see mp_bcast_c1
29729 ! **************************************************************************************************
29730  SUBROUTINE mp_bcast_c3(msg, source, comm)
29731  COMPLEX(kind=real_4), CONTIGUOUS :: msg(:, :, :)
29732  INTEGER, INTENT(IN) :: source
29733  CLASS(mp_comm_type), INTENT(IN) :: comm
29734 
29735  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_c3'
29736 
29737  INTEGER :: handle
29738 #if defined(__parallel)
29739  INTEGER :: ierr, msglen
29740 #endif
29741 
29742  CALL mp_timeset(routinen, handle)
29743 
29744 #if defined(__parallel)
29745  msglen = SIZE(msg)
29746  CALL mpi_bcast(msg, msglen, mpi_complex, source, comm%handle, ierr)
29747  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29748  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29749 #else
29750  mark_used(msg)
29751  mark_used(source)
29752  mark_used(comm)
29753 #endif
29754  CALL mp_timestop(handle)
29755  END SUBROUTINE mp_bcast_c3
29756 
29757 ! **************************************************************************************************
29758 !> \brief Broadcasts rank-3 data to all processes. Uses the source of the communicator for convenience
29759 !> \param[in] msg Data to broadcast
29760 !> \param source ...
29761 !> \param comm ...
29762 !> \note see mp_bcast_c1
29763 ! **************************************************************************************************
29764  SUBROUTINE mp_bcast_c3_src(msg, comm)
29765  COMPLEX(kind=real_4), CONTIGUOUS :: msg(:, :, :)
29766  CLASS(mp_comm_type), INTENT(IN) :: comm
29767 
29768  CHARACTER(len=*), PARAMETER :: routinen = 'mp_bcast_c3_src'
29769 
29770  INTEGER :: handle
29771 #if defined(__parallel)
29772  INTEGER :: ierr, msglen
29773 #endif
29774 
29775  CALL mp_timeset(routinen, handle)
29776 
29777 #if defined(__parallel)
29778  msglen = SIZE(msg)
29779  CALL mpi_bcast(msg, msglen, mpi_complex, comm%source, comm%handle, ierr)
29780  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_bcast @ "//routinen)
29781  CALL add_perf(perf_id=2, count=1, msg_size=msglen*(2*real_4_size))
29782 #else
29783  mark_used(msg)
29784  mark_used(comm)
29785 #endif
29786  CALL mp_timestop(handle)
29787  END SUBROUTINE mp_bcast_c3_src
29788 
29789 ! **************************************************************************************************
29790 !> \brief Sums a datum from all processes with result left on all processes.
29791 !> \param[in,out] msg Datum to sum (input) and result (output)
29792 !> \param[in] comm Message passing environment identifier
29793 !> \par MPI mapping
29794 !> mpi_allreduce
29795 ! **************************************************************************************************
29796  SUBROUTINE mp_sum_c (msg, comm)
29797  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
29798  CLASS(mp_comm_type), INTENT(IN) :: comm
29799 
29800  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_c'
29801 
29802  INTEGER :: handle
29803 #if defined(__parallel)
29804  INTEGER :: ierr, msglen
29805 #endif
29806 
29807  CALL mp_timeset(routinen, handle)
29808 
29809 #if defined(__parallel)
29810  msglen = 1
29811  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_sum, comm%handle, ierr)
29812  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
29813  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
29814 #else
29815  mark_used(msg)
29816  mark_used(comm)
29817 #endif
29818  CALL mp_timestop(handle)
29819  END SUBROUTINE mp_sum_c
29820 
29821 ! **************************************************************************************************
29822 !> \brief Element-wise sum of a rank-1 array on all processes.
29823 !> \param[in,out] msg Vector to sum and result
29824 !> \param comm ...
29825 !> \note see mp_sum_c
29826 ! **************************************************************************************************
29827  SUBROUTINE mp_sum_cv(msg, comm)
29828  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
29829  CLASS(mp_comm_type), INTENT(IN) :: comm
29830 
29831  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_cv'
29832 
29833  INTEGER :: handle
29834 #if defined(__parallel)
29835  INTEGER :: ierr, msglen
29836 #endif
29837 
29838  CALL mp_timeset(routinen, handle)
29839 
29840 #if defined(__parallel)
29841  msglen = SIZE(msg)
29842  IF (msglen > 0) THEN
29843  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_sum, comm%handle, ierr)
29844  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
29845  END IF
29846  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
29847 #else
29848  mark_used(msg)
29849  mark_used(comm)
29850 #endif
29851  CALL mp_timestop(handle)
29852  END SUBROUTINE mp_sum_cv
29853 
29854 ! **************************************************************************************************
29855 !> \brief Element-wise sum of a rank-1 array on all processes.
29856 !> \param[in,out] msg Vector to sum and result
29857 !> \param comm ...
29858 !> \note see mp_sum_c
29859 ! **************************************************************************************************
29860  SUBROUTINE mp_isum_cv(msg, comm, request)
29861  COMPLEX(kind=real_4), INTENT(INOUT) :: msg(:)
29862  CLASS(mp_comm_type), INTENT(IN) :: comm
29863  TYPE(mp_request_type), INTENT(OUT) :: request
29864 
29865  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isum_cv'
29866 
29867  INTEGER :: handle
29868 #if defined(__parallel)
29869  INTEGER :: ierr, msglen
29870 #endif
29871 
29872  CALL mp_timeset(routinen, handle)
29873 
29874 #if defined(__parallel)
29875 #if !defined(__GNUC__) || __GNUC__ >= 9
29876  cpassert(is_contiguous(msg))
29877 #endif
29878  msglen = SIZE(msg)
29879  IF (msglen > 0) THEN
29880  CALL mpi_iallreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_sum, comm%handle, request%handle, ierr)
29881  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallreduce @ "//routinen)
29882  ELSE
29883  request = mp_request_null
29884  END IF
29885  CALL add_perf(perf_id=23, count=1, msg_size=msglen*(2*real_4_size))
29886 #else
29887  mark_used(msg)
29888  mark_used(comm)
29889  request = mp_request_null
29890 #endif
29891  CALL mp_timestop(handle)
29892  END SUBROUTINE mp_isum_cv
29893 
29894 ! **************************************************************************************************
29895 !> \brief Element-wise sum of a rank-2 array on all processes.
29896 !> \param[in] msg Matrix to sum and result
29897 !> \param comm ...
29898 !> \note see mp_sum_c
29899 ! **************************************************************************************************
29900  SUBROUTINE mp_sum_cm(msg, comm)
29901  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
29902  CLASS(mp_comm_type), INTENT(IN) :: comm
29903 
29904  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_cm'
29905 
29906  INTEGER :: handle
29907 #if defined(__parallel)
29908  INTEGER, PARAMETER :: max_msg = 2**25
29909  INTEGER :: ierr, m1, msglen, step, msglensum
29910 #endif
29911 
29912  CALL mp_timeset(routinen, handle)
29913 
29914 #if defined(__parallel)
29915  ! chunk up the call so that message sizes are limited, to avoid overflows in mpich triggered in large rpa calcs
29916  step = max(1, SIZE(msg, 2)/max(1, SIZE(msg)/max_msg))
29917  msglensum = 0
29918  DO m1 = lbound(msg, 2), ubound(msg, 2), step
29919  msglen = SIZE(msg, 1)*(min(ubound(msg, 2), m1 + step - 1) - m1 + 1)
29920  msglensum = msglensum + msglen
29921  IF (msglen > 0) THEN
29922  CALL mpi_allreduce(mpi_in_place, msg(lbound(msg, 1), m1), msglen, mpi_complex, mpi_sum, comm%handle, ierr)
29923  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
29924  END IF
29925  END DO
29926  CALL add_perf(perf_id=3, count=1, msg_size=msglensum*(2*real_4_size))
29927 #else
29928  mark_used(msg)
29929  mark_used(comm)
29930 #endif
29931  CALL mp_timestop(handle)
29932  END SUBROUTINE mp_sum_cm
29933 
29934 ! **************************************************************************************************
29935 !> \brief Element-wise sum of a rank-3 array on all processes.
29936 !> \param[in] msg Array to sum and result
29937 !> \param comm ...
29938 !> \note see mp_sum_c
29939 ! **************************************************************************************************
29940  SUBROUTINE mp_sum_cm3(msg, comm)
29941  COMPLEX(kind=real_4), INTENT(INOUT), CONTIGUOUS :: msg(:, :, :)
29942  CLASS(mp_comm_type), INTENT(IN) :: comm
29943 
29944  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_cm3'
29945 
29946  INTEGER :: handle
29947 #if defined(__parallel)
29948  INTEGER :: ierr, msglen
29949 #endif
29950 
29951  CALL mp_timeset(routinen, handle)
29952 
29953 #if defined(__parallel)
29954  msglen = SIZE(msg)
29955  IF (msglen > 0) THEN
29956  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_sum, comm%handle, ierr)
29957  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
29958  END IF
29959  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
29960 #else
29961  mark_used(msg)
29962  mark_used(comm)
29963 #endif
29964  CALL mp_timestop(handle)
29965  END SUBROUTINE mp_sum_cm3
29966 
29967 ! **************************************************************************************************
29968 !> \brief Element-wise sum of a rank-4 array on all processes.
29969 !> \param[in] msg Array to sum and result
29970 !> \param comm ...
29971 !> \note see mp_sum_c
29972 ! **************************************************************************************************
29973  SUBROUTINE mp_sum_cm4(msg, comm)
29974  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :, :, :)
29975  CLASS(mp_comm_type), INTENT(IN) :: comm
29976 
29977  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_cm4'
29978 
29979  INTEGER :: handle
29980 #if defined(__parallel)
29981  INTEGER :: ierr, msglen
29982 #endif
29983 
29984  CALL mp_timeset(routinen, handle)
29985 
29986 #if defined(__parallel)
29987  msglen = SIZE(msg)
29988  IF (msglen > 0) THEN
29989  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_sum, comm%handle, ierr)
29990  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
29991  END IF
29992  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
29993 #else
29994  mark_used(msg)
29995  mark_used(comm)
29996 #endif
29997  CALL mp_timestop(handle)
29998  END SUBROUTINE mp_sum_cm4
29999 
30000 ! **************************************************************************************************
30001 !> \brief Element-wise sum of data from all processes with result left only on
30002 !> one.
30003 !> \param[in,out] msg Vector to sum (input) and (only on process root)
30004 !> result (output)
30005 !> \param root ...
30006 !> \param[in] comm Message passing environment identifier
30007 !> \par MPI mapping
30008 !> mpi_reduce
30009 ! **************************************************************************************************
30010  SUBROUTINE mp_sum_root_cv(msg, root, comm)
30011  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
30012  INTEGER, INTENT(IN) :: root
30013  CLASS(mp_comm_type), INTENT(IN) :: comm
30014 
30015  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_cv'
30016 
30017  INTEGER :: handle
30018 #if defined(__parallel)
30019  INTEGER :: ierr, m1, msglen, taskid
30020  COMPLEX(kind=real_4), ALLOCATABLE :: res(:)
30021 #endif
30022 
30023  CALL mp_timeset(routinen, handle)
30024 
30025 #if defined(__parallel)
30026  msglen = SIZE(msg)
30027  CALL mpi_comm_rank(comm%handle, taskid, ierr)
30028  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
30029  IF (msglen > 0) THEN
30030  m1 = SIZE(msg, 1)
30031  ALLOCATE (res(m1))
30032  CALL mpi_reduce(msg, res, msglen, mpi_complex, mpi_sum, &
30033  root, comm%handle, ierr)
30034  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
30035  IF (taskid == root) THEN
30036  msg = res
30037  END IF
30038  DEALLOCATE (res)
30039  END IF
30040  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30041 #else
30042  mark_used(msg)
30043  mark_used(root)
30044  mark_used(comm)
30045 #endif
30046  CALL mp_timestop(handle)
30047  END SUBROUTINE mp_sum_root_cv
30048 
30049 ! **************************************************************************************************
30050 !> \brief Element-wise sum of data from all processes with result left only on
30051 !> one.
30052 !> \param[in,out] msg Matrix to sum (input) and (only on process root)
30053 !> result (output)
30054 !> \param root ...
30055 !> \param comm ...
30056 !> \note see mp_sum_root_cv
30057 ! **************************************************************************************************
30058  SUBROUTINE mp_sum_root_cm(msg, root, comm)
30059  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
30060  INTEGER, INTENT(IN) :: root
30061  CLASS(mp_comm_type), INTENT(IN) :: comm
30062 
30063  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_root_rm'
30064 
30065  INTEGER :: handle
30066 #if defined(__parallel)
30067  INTEGER :: ierr, m1, m2, msglen, taskid
30068  COMPLEX(kind=real_4), ALLOCATABLE :: res(:, :)
30069 #endif
30070 
30071  CALL mp_timeset(routinen, handle)
30072 
30073 #if defined(__parallel)
30074  msglen = SIZE(msg)
30075  CALL mpi_comm_rank(comm%handle, taskid, ierr)
30076  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
30077  IF (msglen > 0) THEN
30078  m1 = SIZE(msg, 1)
30079  m2 = SIZE(msg, 2)
30080  ALLOCATE (res(m1, m2))
30081  CALL mpi_reduce(msg, res, msglen, mpi_complex, mpi_sum, root, comm%handle, ierr)
30082  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
30083  IF (taskid == root) THEN
30084  msg = res
30085  END IF
30086  DEALLOCATE (res)
30087  END IF
30088  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30089 #else
30090  mark_used(root)
30091  mark_used(msg)
30092  mark_used(comm)
30093 #endif
30094  CALL mp_timestop(handle)
30095  END SUBROUTINE mp_sum_root_cm
30096 
30097 ! **************************************************************************************************
30098 !> \brief Partial sum of data from all processes with result on each process.
30099 !> \param[in] msg Matrix to sum (input)
30100 !> \param[out] res Matrix containing result (output)
30101 !> \param[in] comm Message passing environment identifier
30102 ! **************************************************************************************************
30103  SUBROUTINE mp_sum_partial_cm(msg, res, comm)
30104  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
30105  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: res(:, :)
30106  CLASS(mp_comm_type), INTENT(IN) :: comm
30107 
30108  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_partial_cm'
30109 
30110  INTEGER :: handle
30111 #if defined(__parallel)
30112  INTEGER :: ierr, msglen, taskid
30113 #endif
30114 
30115  CALL mp_timeset(routinen, handle)
30116 
30117 #if defined(__parallel)
30118  msglen = SIZE(msg)
30119  CALL mpi_comm_rank(comm%handle, taskid, ierr)
30120  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_comm_rank @ "//routinen)
30121  IF (msglen > 0) THEN
30122  CALL mpi_scan(msg, res, msglen, mpi_complex, mpi_sum, comm%handle, ierr)
30123  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scan @ "//routinen)
30124  END IF
30125  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30126  ! perf_id is same as for other summation routines
30127 #else
30128  res = msg
30129  mark_used(comm)
30130 #endif
30131  CALL mp_timestop(handle)
30132  END SUBROUTINE mp_sum_partial_cm
30133 
30134 ! **************************************************************************************************
30135 !> \brief Finds the maximum of a datum with the result left on all processes.
30136 !> \param[in,out] msg Find maximum among these data (input) and
30137 !> maximum (output)
30138 !> \param[in] comm Message passing environment identifier
30139 !> \par MPI mapping
30140 !> mpi_allreduce
30141 ! **************************************************************************************************
30142  SUBROUTINE mp_max_c (msg, comm)
30143  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
30144  CLASS(mp_comm_type), INTENT(IN) :: comm
30145 
30146  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_c'
30147 
30148  INTEGER :: handle
30149 #if defined(__parallel)
30150  INTEGER :: ierr, msglen
30151 #endif
30152 
30153  CALL mp_timeset(routinen, handle)
30154 
30155 #if defined(__parallel)
30156  msglen = 1
30157  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_max, comm%handle, ierr)
30158  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30159  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30160 #else
30161  mark_used(msg)
30162  mark_used(comm)
30163 #endif
30164  CALL mp_timestop(handle)
30165  END SUBROUTINE mp_max_c
30166 
30167 ! **************************************************************************************************
30168 !> \brief Finds the maximum of a datum with the result left on all processes.
30169 !> \param[in,out] msg Find maximum among these data (input) and
30170 !> maximum (output)
30171 !> \param[in] comm Message passing environment identifier
30172 !> \par MPI mapping
30173 !> mpi_allreduce
30174 ! **************************************************************************************************
30175  SUBROUTINE mp_max_root_c (msg, root, comm)
30176  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
30177  INTEGER, INTENT(IN) :: root
30178  CLASS(mp_comm_type), INTENT(IN) :: comm
30179 
30180  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_c'
30181 
30182  INTEGER :: handle
30183 #if defined(__parallel)
30184  INTEGER :: ierr, msglen
30185  COMPLEX(kind=real_4) :: res
30186 #endif
30187 
30188  CALL mp_timeset(routinen, handle)
30189 
30190 #if defined(__parallel)
30191  msglen = 1
30192  CALL mpi_reduce(msg, res, msglen, mpi_complex, mpi_max, root, comm%handle, ierr)
30193  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce @ "//routinen)
30194  IF (root == comm%mepos) msg = res
30195  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30196 #else
30197  mark_used(msg)
30198  mark_used(comm)
30199  mark_used(root)
30200 #endif
30201  CALL mp_timestop(handle)
30202  END SUBROUTINE mp_max_root_c
30203 
30204 ! **************************************************************************************************
30205 !> \brief Finds the element-wise maximum of a vector with the result left on
30206 !> all processes.
30207 !> \param[in,out] msg Find maximum among these data (input) and
30208 !> maximum (output)
30209 !> \param comm ...
30210 !> \note see mp_max_c
30211 ! **************************************************************************************************
30212  SUBROUTINE mp_max_cv(msg, comm)
30213  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:)
30214  CLASS(mp_comm_type), INTENT(IN) :: comm
30215 
30216  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_cv'
30217 
30218  INTEGER :: handle
30219 #if defined(__parallel)
30220  INTEGER :: ierr, msglen
30221 #endif
30222 
30223  CALL mp_timeset(routinen, handle)
30224 
30225 #if defined(__parallel)
30226  msglen = SIZE(msg)
30227  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_max, comm%handle, ierr)
30228  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30229  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30230 #else
30231  mark_used(msg)
30232  mark_used(comm)
30233 #endif
30234  CALL mp_timestop(handle)
30235  END SUBROUTINE mp_max_cv
30236 
30237 ! **************************************************************************************************
30238 !> \brief Finds the element-wise maximum of a vector with the result left on
30239 !> all processes.
30240 !> \param[in,out] msg Find maximum among these data (input) and
30241 !> maximum (output)
30242 !> \param comm ...
30243 !> \note see mp_max_c
30244 ! **************************************************************************************************
30245  SUBROUTINE mp_max_root_cm(msg, root, comm)
30246  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(INOUT) :: msg(:, :)
30247  INTEGER :: root
30248  CLASS(mp_comm_type), INTENT(IN) :: comm
30249 
30250  CHARACTER(len=*), PARAMETER :: routinen = 'mp_max_root_cm'
30251 
30252  INTEGER :: handle
30253 #if defined(__parallel)
30254  INTEGER :: ierr, msglen
30255  COMPLEX(kind=real_4) :: res(size(msg, 1), size(msg, 2))
30256 #endif
30257 
30258  CALL mp_timeset(routinen, handle)
30259 
30260 #if defined(__parallel)
30261  msglen = SIZE(msg)
30262  CALL mpi_reduce(msg, res, msglen, mpi_complex, mpi_max, root, comm%handle, ierr)
30263  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30264  IF (root == comm%mepos) msg = res
30265  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30266 #else
30267  mark_used(msg)
30268  mark_used(comm)
30269  mark_used(root)
30270 #endif
30271  CALL mp_timestop(handle)
30272  END SUBROUTINE mp_max_root_cm
30273 
30274 ! **************************************************************************************************
30275 !> \brief Finds the minimum of a datum with the result left on all processes.
30276 !> \param[in,out] msg Find minimum among these data (input) and
30277 !> maximum (output)
30278 !> \param[in] comm Message passing environment identifier
30279 !> \par MPI mapping
30280 !> mpi_allreduce
30281 ! **************************************************************************************************
30282  SUBROUTINE mp_min_c (msg, comm)
30283  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
30284  CLASS(mp_comm_type), INTENT(IN) :: comm
30285 
30286  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_c'
30287 
30288  INTEGER :: handle
30289 #if defined(__parallel)
30290  INTEGER :: ierr, msglen
30291 #endif
30292 
30293  CALL mp_timeset(routinen, handle)
30294 
30295 #if defined(__parallel)
30296  msglen = 1
30297  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_min, comm%handle, ierr)
30298  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30299  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30300 #else
30301  mark_used(msg)
30302  mark_used(comm)
30303 #endif
30304  CALL mp_timestop(handle)
30305  END SUBROUTINE mp_min_c
30306 
30307 ! **************************************************************************************************
30308 !> \brief Finds the element-wise minimum of vector with the result left on
30309 !> all processes.
30310 !> \param[in,out] msg Find minimum among these data (input) and
30311 !> maximum (output)
30312 !> \param comm ...
30313 !> \par MPI mapping
30314 !> mpi_allreduce
30315 !> \note see mp_min_c
30316 ! **************************************************************************************************
30317  SUBROUTINE mp_min_cv(msg, comm)
30318  COMPLEX(kind=real_4), INTENT(INOUT), CONTIGUOUS :: msg(:)
30319  CLASS(mp_comm_type), INTENT(IN) :: comm
30320 
30321  CHARACTER(len=*), PARAMETER :: routinen = 'mp_min_cv'
30322 
30323  INTEGER :: handle
30324 #if defined(__parallel)
30325  INTEGER :: ierr, msglen
30326 #endif
30327 
30328  CALL mp_timeset(routinen, handle)
30329 
30330 #if defined(__parallel)
30331  msglen = SIZE(msg)
30332  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_min, comm%handle, ierr)
30333  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30334  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30335 #else
30336  mark_used(msg)
30337  mark_used(comm)
30338 #endif
30339  CALL mp_timestop(handle)
30340  END SUBROUTINE mp_min_cv
30341 
30342 ! **************************************************************************************************
30343 !> \brief Multiplies a set of numbers scattered across a number of processes,
30344 !> then replicates the result.
30345 !> \param[in,out] msg a number to multiply (input) and result (output)
30346 !> \param[in] comm message passing environment identifier
30347 !> \par MPI mapping
30348 !> mpi_allreduce
30349 ! **************************************************************************************************
30350  SUBROUTINE mp_prod_c (msg, comm)
30351  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
30352  CLASS(mp_comm_type), INTENT(IN) :: comm
30353 
30354  CHARACTER(len=*), PARAMETER :: routinen = 'mp_prod_c'
30355 
30356  INTEGER :: handle
30357 #if defined(__parallel)
30358  INTEGER :: ierr, msglen
30359 #endif
30360 
30361  CALL mp_timeset(routinen, handle)
30362 
30363 #if defined(__parallel)
30364  msglen = 1
30365  CALL mpi_allreduce(mpi_in_place, msg, msglen, mpi_complex, mpi_prod, comm%handle, ierr)
30366  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allreduce @ "//routinen)
30367  CALL add_perf(perf_id=3, count=1, msg_size=msglen*(2*real_4_size))
30368 #else
30369  mark_used(msg)
30370  mark_used(comm)
30371 #endif
30372  CALL mp_timestop(handle)
30373  END SUBROUTINE mp_prod_c
30374 
30375 ! **************************************************************************************************
30376 !> \brief Scatters data from one processes to all others
30377 !> \param[in] msg_scatter Data to scatter (for root process)
30378 !> \param[out] msg Received data
30379 !> \param[in] root Process which scatters data
30380 !> \param[in] comm Message passing environment identifier
30381 !> \par MPI mapping
30382 !> mpi_scatter
30383 ! **************************************************************************************************
30384  SUBROUTINE mp_scatter_cv(msg_scatter, msg, root, comm)
30385  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg_scatter(:)
30386  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg(:)
30387  INTEGER, INTENT(IN) :: root
30388  CLASS(mp_comm_type), INTENT(IN) :: comm
30389 
30390  CHARACTER(len=*), PARAMETER :: routinen = 'mp_scatter_cv'
30391 
30392  INTEGER :: handle
30393 #if defined(__parallel)
30394  INTEGER :: ierr, msglen
30395 #endif
30396 
30397  CALL mp_timeset(routinen, handle)
30398 
30399 #if defined(__parallel)
30400  msglen = SIZE(msg)
30401  CALL mpi_scatter(msg_scatter, msglen, mpi_complex, msg, &
30402  msglen, mpi_complex, root, comm%handle, ierr)
30403  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_scatter @ "//routinen)
30404  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30405 #else
30406  mark_used(root)
30407  mark_used(comm)
30408  msg = msg_scatter
30409 #endif
30410  CALL mp_timestop(handle)
30411  END SUBROUTINE mp_scatter_cv
30412 
30413 ! **************************************************************************************************
30414 !> \brief Scatters data from one processes to all others
30415 !> \param[in] msg_scatter Data to scatter (for root process)
30416 !> \param[in] root Process which scatters data
30417 !> \param[in] comm Message passing environment identifier
30418 !> \par MPI mapping
30419 !> mpi_scatter
30420 ! **************************************************************************************************
30421  SUBROUTINE mp_iscatter_c (msg_scatter, msg, root, comm, request)
30422  COMPLEX(kind=real_4), INTENT(IN) :: msg_scatter(:)
30423  COMPLEX(kind=real_4), INTENT(INOUT) :: msg
30424  INTEGER, INTENT(IN) :: root
30425  CLASS(mp_comm_type), INTENT(IN) :: comm
30426  TYPE(mp_request_type), INTENT(OUT) :: request
30427 
30428  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_c'
30429 
30430  INTEGER :: handle
30431 #if defined(__parallel)
30432  INTEGER :: ierr, msglen
30433 #endif
30434 
30435  CALL mp_timeset(routinen, handle)
30436 
30437 #if defined(__parallel)
30438 #if !defined(__GNUC__) || __GNUC__ >= 9
30439  cpassert(is_contiguous(msg_scatter))
30440 #endif
30441  msglen = 1
30442  CALL mpi_iscatter(msg_scatter, msglen, mpi_complex, msg, &
30443  msglen, mpi_complex, root, comm%handle, request%handle, ierr)
30444  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
30445  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_4_size))
30446 #else
30447  mark_used(root)
30448  mark_used(comm)
30449  msg = msg_scatter(1)
30450  request = mp_request_null
30451 #endif
30452  CALL mp_timestop(handle)
30453  END SUBROUTINE mp_iscatter_c
30454 
30455 ! **************************************************************************************************
30456 !> \brief Scatters data from one processes to all others
30457 !> \param[in] msg_scatter Data to scatter (for root process)
30458 !> \param[in] root Process which scatters data
30459 !> \param[in] comm Message passing environment identifier
30460 !> \par MPI mapping
30461 !> mpi_scatter
30462 ! **************************************************************************************************
30463  SUBROUTINE mp_iscatter_cv2(msg_scatter, msg, root, comm, request)
30464  COMPLEX(kind=real_4), INTENT(IN) :: msg_scatter(:, :)
30465  COMPLEX(kind=real_4), INTENT(INOUT) :: msg(:)
30466  INTEGER, INTENT(IN) :: root
30467  CLASS(mp_comm_type), INTENT(IN) :: comm
30468  TYPE(mp_request_type), INTENT(OUT) :: request
30469 
30470  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatter_cv2'
30471 
30472  INTEGER :: handle
30473 #if defined(__parallel)
30474  INTEGER :: ierr, msglen
30475 #endif
30476 
30477  CALL mp_timeset(routinen, handle)
30478 
30479 #if defined(__parallel)
30480 #if !defined(__GNUC__) || __GNUC__ >= 9
30481  cpassert(is_contiguous(msg_scatter))
30482 #endif
30483  msglen = SIZE(msg)
30484  CALL mpi_iscatter(msg_scatter, msglen, mpi_complex, msg, &
30485  msglen, mpi_complex, root, comm%handle, request%handle, ierr)
30486  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatter @ "//routinen)
30487  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_4_size))
30488 #else
30489  mark_used(root)
30490  mark_used(comm)
30491  msg(:) = msg_scatter(:, 1)
30492  request = mp_request_null
30493 #endif
30494  CALL mp_timestop(handle)
30495  END SUBROUTINE mp_iscatter_cv2
30496 
30497 ! **************************************************************************************************
30498 !> \brief Scatters data from one processes to all others
30499 !> \param[in] msg_scatter Data to scatter (for root process)
30500 !> \param[in] root Process which scatters data
30501 !> \param[in] comm Message passing environment identifier
30502 !> \par MPI mapping
30503 !> mpi_scatter
30504 ! **************************************************************************************************
30505  SUBROUTINE mp_iscatterv_cv(msg_scatter, sendcounts, displs, msg, recvcount, root, comm, request)
30506  COMPLEX(kind=real_4), INTENT(IN) :: msg_scatter(:)
30507  INTEGER, INTENT(IN) :: sendcounts(:), displs(:)
30508  COMPLEX(kind=real_4), INTENT(INOUT) :: msg(:)
30509  INTEGER, INTENT(IN) :: recvcount, root
30510  CLASS(mp_comm_type), INTENT(IN) :: comm
30511  TYPE(mp_request_type), INTENT(OUT) :: request
30512 
30513  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iscatterv_cv'
30514 
30515  INTEGER :: handle
30516 #if defined(__parallel)
30517  INTEGER :: ierr
30518 #endif
30519 
30520  CALL mp_timeset(routinen, handle)
30521 
30522 #if defined(__parallel)
30523 #if !defined(__GNUC__) || __GNUC__ >= 9
30524  cpassert(is_contiguous(msg_scatter))
30525  cpassert(is_contiguous(msg))
30526  cpassert(is_contiguous(sendcounts))
30527  cpassert(is_contiguous(displs))
30528 #endif
30529  CALL mpi_iscatterv(msg_scatter, sendcounts, displs, mpi_complex, msg, &
30530  recvcount, mpi_complex, root, comm%handle, request%handle, ierr)
30531  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iscatterv @ "//routinen)
30532  CALL add_perf(perf_id=24, count=1, msg_size=1*(2*real_4_size))
30533 #else
30534  mark_used(sendcounts)
30535  mark_used(displs)
30536  mark_used(recvcount)
30537  mark_used(root)
30538  mark_used(comm)
30539  msg(1:recvcount) = msg_scatter(1 + displs(1):1 + displs(1) + sendcounts(1))
30540  request = mp_request_null
30541 #endif
30542  CALL mp_timestop(handle)
30543  END SUBROUTINE mp_iscatterv_cv
30544 
30545 ! **************************************************************************************************
30546 !> \brief Gathers a datum from all processes to one
30547 !> \param[in] msg Datum to send to root
30548 !> \param[out] msg_gather Received data (on root)
30549 !> \param[in] root Process which gathers the data
30550 !> \param[in] comm Message passing environment identifier
30551 !> \par MPI mapping
30552 !> mpi_gather
30553 ! **************************************************************************************************
30554  SUBROUTINE mp_gather_c (msg, msg_gather, root, comm)
30555  COMPLEX(kind=real_4), INTENT(IN) :: msg
30556  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
30557  INTEGER, INTENT(IN) :: root
30558  CLASS(mp_comm_type), INTENT(IN) :: comm
30559 
30560  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_c'
30561 
30562  INTEGER :: handle
30563 #if defined(__parallel)
30564  INTEGER :: ierr, msglen
30565 #endif
30566 
30567  CALL mp_timeset(routinen, handle)
30568 
30569 #if defined(__parallel)
30570  msglen = 1
30571  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30572  msglen, mpi_complex, root, comm%handle, ierr)
30573  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30574  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30575 #else
30576  mark_used(root)
30577  mark_used(comm)
30578  msg_gather(1) = msg
30579 #endif
30580  CALL mp_timestop(handle)
30581  END SUBROUTINE mp_gather_c
30582 
30583 ! **************************************************************************************************
30584 !> \brief Gathers a datum from all processes to one, uses the source process of comm
30585 !> \param[in] msg Datum to send to root
30586 !> \param[out] msg_gather Received data (on root)
30587 !> \param[in] comm Message passing environment identifier
30588 !> \par MPI mapping
30589 !> mpi_gather
30590 ! **************************************************************************************************
30591  SUBROUTINE mp_gather_c_src(msg, msg_gather, comm)
30592  COMPLEX(kind=real_4), INTENT(IN) :: msg
30593  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
30594  CLASS(mp_comm_type), INTENT(IN) :: comm
30595 
30596  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_c_src'
30597 
30598  INTEGER :: handle
30599 #if defined(__parallel)
30600  INTEGER :: ierr, msglen
30601 #endif
30602 
30603  CALL mp_timeset(routinen, handle)
30604 
30605 #if defined(__parallel)
30606  msglen = 1
30607  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30608  msglen, mpi_complex, comm%source, comm%handle, ierr)
30609  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30610  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30611 #else
30612  mark_used(comm)
30613  msg_gather(1) = msg
30614 #endif
30615  CALL mp_timestop(handle)
30616  END SUBROUTINE mp_gather_c_src
30617 
30618 ! **************************************************************************************************
30619 !> \brief Gathers data from all processes to one
30620 !> \param[in] msg Datum to send to root
30621 !> \param msg_gather ...
30622 !> \param root ...
30623 !> \param comm ...
30624 !> \par Data length
30625 !> All data (msg) is equal-sized
30626 !> \par MPI mapping
30627 !> mpi_gather
30628 !> \note see mp_gather_c
30629 ! **************************************************************************************************
30630  SUBROUTINE mp_gather_cv(msg, msg_gather, root, comm)
30631  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
30632  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
30633  INTEGER, INTENT(IN) :: root
30634  CLASS(mp_comm_type), INTENT(IN) :: comm
30635 
30636  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_cv'
30637 
30638  INTEGER :: handle
30639 #if defined(__parallel)
30640  INTEGER :: ierr, msglen
30641 #endif
30642 
30643  CALL mp_timeset(routinen, handle)
30644 
30645 #if defined(__parallel)
30646  msglen = SIZE(msg)
30647  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30648  msglen, mpi_complex, root, comm%handle, ierr)
30649  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30650  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30651 #else
30652  mark_used(root)
30653  mark_used(comm)
30654  msg_gather = msg
30655 #endif
30656  CALL mp_timestop(handle)
30657  END SUBROUTINE mp_gather_cv
30658 
30659 ! **************************************************************************************************
30660 !> \brief Gathers data from all processes to one. Gathers from comm%source
30661 !> \param[in] msg Datum to send to root
30662 !> \param msg_gather ...
30663 !> \param comm ...
30664 !> \par Data length
30665 !> All data (msg) is equal-sized
30666 !> \par MPI mapping
30667 !> mpi_gather
30668 !> \note see mp_gather_c
30669 ! **************************************************************************************************
30670  SUBROUTINE mp_gather_cv_src(msg, msg_gather, comm)
30671  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
30672  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:)
30673  CLASS(mp_comm_type), INTENT(IN) :: comm
30674 
30675  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_cv_src'
30676 
30677  INTEGER :: handle
30678 #if defined(__parallel)
30679  INTEGER :: ierr, msglen
30680 #endif
30681 
30682  CALL mp_timeset(routinen, handle)
30683 
30684 #if defined(__parallel)
30685  msglen = SIZE(msg)
30686  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30687  msglen, mpi_complex, comm%source, comm%handle, ierr)
30688  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30689  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30690 #else
30691  mark_used(comm)
30692  msg_gather = msg
30693 #endif
30694  CALL mp_timestop(handle)
30695  END SUBROUTINE mp_gather_cv_src
30696 
30697 ! **************************************************************************************************
30698 !> \brief Gathers data from all processes to one
30699 !> \param[in] msg Datum to send to root
30700 !> \param msg_gather ...
30701 !> \param root ...
30702 !> \param comm ...
30703 !> \par Data length
30704 !> All data (msg) is equal-sized
30705 !> \par MPI mapping
30706 !> mpi_gather
30707 !> \note see mp_gather_c
30708 ! **************************************************************************************************
30709  SUBROUTINE mp_gather_cm(msg, msg_gather, root, comm)
30710  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
30711  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
30712  INTEGER, INTENT(IN) :: root
30713  CLASS(mp_comm_type), INTENT(IN) :: comm
30714 
30715  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_cm'
30716 
30717  INTEGER :: handle
30718 #if defined(__parallel)
30719  INTEGER :: ierr, msglen
30720 #endif
30721 
30722  CALL mp_timeset(routinen, handle)
30723 
30724 #if defined(__parallel)
30725  msglen = SIZE(msg)
30726  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30727  msglen, mpi_complex, root, comm%handle, ierr)
30728  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30729  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30730 #else
30731  mark_used(root)
30732  mark_used(comm)
30733  msg_gather = msg
30734 #endif
30735  CALL mp_timestop(handle)
30736  END SUBROUTINE mp_gather_cm
30737 
30738 ! **************************************************************************************************
30739 !> \brief Gathers data from all processes to one. Gathers from comm%source
30740 !> \param[in] msg Datum to send to root
30741 !> \param msg_gather ...
30742 !> \param comm ...
30743 !> \par Data length
30744 !> All data (msg) is equal-sized
30745 !> \par MPI mapping
30746 !> mpi_gather
30747 !> \note see mp_gather_c
30748 ! **************************************************************************************************
30749  SUBROUTINE mp_gather_cm_src(msg, msg_gather, comm)
30750  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:, :)
30751  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msg_gather(:, :)
30752  CLASS(mp_comm_type), INTENT(IN) :: comm
30753 
30754  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gather_cm_src'
30755 
30756  INTEGER :: handle
30757 #if defined(__parallel)
30758  INTEGER :: ierr, msglen
30759 #endif
30760 
30761  CALL mp_timeset(routinen, handle)
30762 
30763 #if defined(__parallel)
30764  msglen = SIZE(msg)
30765  CALL mpi_gather(msg, msglen, mpi_complex, msg_gather, &
30766  msglen, mpi_complex, comm%source, comm%handle, ierr)
30767  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gather @ "//routinen)
30768  CALL add_perf(perf_id=4, count=1, msg_size=msglen*(2*real_4_size))
30769 #else
30770  mark_used(comm)
30771  msg_gather = msg
30772 #endif
30773  CALL mp_timestop(handle)
30774  END SUBROUTINE mp_gather_cm_src
30775 
30776 ! **************************************************************************************************
30777 !> \brief Gathers data from all processes to one.
30778 !> \param[in] sendbuf Data to send to root
30779 !> \param[out] recvbuf Received data (on root)
30780 !> \param[in] recvcounts Sizes of data received from processes
30781 !> \param[in] displs Offsets of data received from processes
30782 !> \param[in] root Process which gathers the data
30783 !> \param[in] comm Message passing environment identifier
30784 !> \par Data length
30785 !> Data can have different lengths
30786 !> \par Offsets
30787 !> Offsets start at 0
30788 !> \par MPI mapping
30789 !> mpi_gather
30790 ! **************************************************************************************************
30791  SUBROUTINE mp_gatherv_cv(sendbuf, recvbuf, recvcounts, displs, root, comm)
30792 
30793  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
30794  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
30795  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
30796  INTEGER, INTENT(IN) :: root
30797  CLASS(mp_comm_type), INTENT(IN) :: comm
30798 
30799  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_cv'
30800 
30801  INTEGER :: handle
30802 #if defined(__parallel)
30803  INTEGER :: ierr, sendcount
30804 #endif
30805 
30806  CALL mp_timeset(routinen, handle)
30807 
30808 #if defined(__parallel)
30809  sendcount = SIZE(sendbuf)
30810  CALL mpi_gatherv(sendbuf, sendcount, mpi_complex, &
30811  recvbuf, recvcounts, displs, mpi_complex, &
30812  root, comm%handle, ierr)
30813  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
30814  CALL add_perf(perf_id=4, &
30815  count=1, &
30816  msg_size=sendcount*(2*real_4_size))
30817 #else
30818  mark_used(recvcounts)
30819  mark_used(root)
30820  mark_used(comm)
30821  recvbuf(1 + displs(1):) = sendbuf
30822 #endif
30823  CALL mp_timestop(handle)
30824  END SUBROUTINE mp_gatherv_cv
30825 
30826 ! **************************************************************************************************
30827 !> \brief Gathers data from all processes to one. Gathers from comm%source
30828 !> \param[in] sendbuf Data to send to root
30829 !> \param[out] recvbuf Received data (on root)
30830 !> \param[in] recvcounts Sizes of data received from processes
30831 !> \param[in] displs Offsets of data received from processes
30832 !> \param[in] comm Message passing environment identifier
30833 !> \par Data length
30834 !> Data can have different lengths
30835 !> \par Offsets
30836 !> Offsets start at 0
30837 !> \par MPI mapping
30838 !> mpi_gather
30839 ! **************************************************************************************************
30840  SUBROUTINE mp_gatherv_cv_src(sendbuf, recvbuf, recvcounts, displs, comm)
30841 
30842  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(IN) :: sendbuf
30843  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(OUT) :: recvbuf
30844  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
30845  CLASS(mp_comm_type), INTENT(IN) :: comm
30846 
30847  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_cv_src'
30848 
30849  INTEGER :: handle
30850 #if defined(__parallel)
30851  INTEGER :: ierr, sendcount
30852 #endif
30853 
30854  CALL mp_timeset(routinen, handle)
30855 
30856 #if defined(__parallel)
30857  sendcount = SIZE(sendbuf)
30858  CALL mpi_gatherv(sendbuf, sendcount, mpi_complex, &
30859  recvbuf, recvcounts, displs, mpi_complex, &
30860  comm%source, comm%handle, ierr)
30861  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
30862  CALL add_perf(perf_id=4, &
30863  count=1, &
30864  msg_size=sendcount*(2*real_4_size))
30865 #else
30866  mark_used(recvcounts)
30867  mark_used(comm)
30868  recvbuf(1 + displs(1):) = sendbuf
30869 #endif
30870  CALL mp_timestop(handle)
30871  END SUBROUTINE mp_gatherv_cv_src
30872 
30873 ! **************************************************************************************************
30874 !> \brief Gathers data from all processes to one.
30875 !> \param[in] sendbuf Data to send to root
30876 !> \param[out] recvbuf Received data (on root)
30877 !> \param[in] recvcounts Sizes of data received from processes
30878 !> \param[in] displs Offsets of data received from processes
30879 !> \param[in] root Process which gathers the data
30880 !> \param[in] comm Message passing environment identifier
30881 !> \par Data length
30882 !> Data can have different lengths
30883 !> \par Offsets
30884 !> Offsets start at 0
30885 !> \par MPI mapping
30886 !> mpi_gather
30887 ! **************************************************************************************************
30888  SUBROUTINE mp_gatherv_cm2(sendbuf, recvbuf, recvcounts, displs, root, comm)
30889 
30890  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
30891  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
30892  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
30893  INTEGER, INTENT(IN) :: root
30894  CLASS(mp_comm_type), INTENT(IN) :: comm
30895 
30896  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_cm2'
30897 
30898  INTEGER :: handle
30899 #if defined(__parallel)
30900  INTEGER :: ierr, sendcount
30901 #endif
30902 
30903  CALL mp_timeset(routinen, handle)
30904 
30905 #if defined(__parallel)
30906  sendcount = SIZE(sendbuf)
30907  CALL mpi_gatherv(sendbuf, sendcount, mpi_complex, &
30908  recvbuf, recvcounts, displs, mpi_complex, &
30909  root, comm%handle, ierr)
30910  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
30911  CALL add_perf(perf_id=4, &
30912  count=1, &
30913  msg_size=sendcount*(2*real_4_size))
30914 #else
30915  mark_used(recvcounts)
30916  mark_used(root)
30917  mark_used(comm)
30918  recvbuf(:, 1 + displs(1):) = sendbuf
30919 #endif
30920  CALL mp_timestop(handle)
30921  END SUBROUTINE mp_gatherv_cm2
30922 
30923 ! **************************************************************************************************
30924 !> \brief Gathers data from all processes to one.
30925 !> \param[in] sendbuf Data to send to root
30926 !> \param[out] recvbuf Received data (on root)
30927 !> \param[in] recvcounts Sizes of data received from processes
30928 !> \param[in] displs Offsets of data received from processes
30929 !> \param[in] comm Message passing environment identifier
30930 !> \par Data length
30931 !> Data can have different lengths
30932 !> \par Offsets
30933 !> Offsets start at 0
30934 !> \par MPI mapping
30935 !> mpi_gather
30936 ! **************************************************************************************************
30937  SUBROUTINE mp_gatherv_cm2_src(sendbuf, recvbuf, recvcounts, displs, comm)
30938 
30939  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(IN) :: sendbuf
30940  COMPLEX(kind=real_4), DIMENSION(:, :), CONTIGUOUS, INTENT(OUT) :: recvbuf
30941  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
30942  CLASS(mp_comm_type), INTENT(IN) :: comm
30943 
30944  CHARACTER(len=*), PARAMETER :: routinen = 'mp_gatherv_cm2_src'
30945 
30946  INTEGER :: handle
30947 #if defined(__parallel)
30948  INTEGER :: ierr, sendcount
30949 #endif
30950 
30951  CALL mp_timeset(routinen, handle)
30952 
30953 #if defined(__parallel)
30954  sendcount = SIZE(sendbuf)
30955  CALL mpi_gatherv(sendbuf, sendcount, mpi_complex, &
30956  recvbuf, recvcounts, displs, mpi_complex, &
30957  comm%source, comm%handle, ierr)
30958  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
30959  CALL add_perf(perf_id=4, &
30960  count=1, &
30961  msg_size=sendcount*(2*real_4_size))
30962 #else
30963  mark_used(recvcounts)
30964  mark_used(comm)
30965  recvbuf(:, 1 + displs(1):) = sendbuf
30966 #endif
30967  CALL mp_timestop(handle)
30968  END SUBROUTINE mp_gatherv_cm2_src
30969 
30970 ! **************************************************************************************************
30971 !> \brief Gathers data from all processes to one.
30972 !> \param[in] sendbuf Data to send to root
30973 !> \param[out] recvbuf Received data (on root)
30974 !> \param[in] recvcounts Sizes of data received from processes
30975 !> \param[in] displs Offsets of data received from processes
30976 !> \param[in] root Process which gathers the data
30977 !> \param[in] comm Message passing environment identifier
30978 !> \par Data length
30979 !> Data can have different lengths
30980 !> \par Offsets
30981 !> Offsets start at 0
30982 !> \par MPI mapping
30983 !> mpi_gather
30984 ! **************************************************************************************************
30985  SUBROUTINE mp_igatherv_cv(sendbuf, sendcount, recvbuf, recvcounts, displs, root, comm, request)
30986  COMPLEX(kind=real_4), DIMENSION(:), INTENT(IN) :: sendbuf
30987  COMPLEX(kind=real_4), DIMENSION(:), INTENT(OUT) :: recvbuf
30988  INTEGER, DIMENSION(:), CONTIGUOUS, INTENT(IN) :: recvcounts, displs
30989  INTEGER, INTENT(IN) :: sendcount, root
30990  CLASS(mp_comm_type), INTENT(IN) :: comm
30991  TYPE(mp_request_type), INTENT(OUT) :: request
30992 
30993  CHARACTER(len=*), PARAMETER :: routinen = 'mp_igatherv_cv'
30994 
30995  INTEGER :: handle
30996 #if defined(__parallel)
30997  INTEGER :: ierr
30998 #endif
30999 
31000  CALL mp_timeset(routinen, handle)
31001 
31002 #if defined(__parallel)
31003 #if !defined(__GNUC__) || __GNUC__ >= 9
31004  cpassert(is_contiguous(sendbuf))
31005  cpassert(is_contiguous(recvbuf))
31006  cpassert(is_contiguous(recvcounts))
31007  cpassert(is_contiguous(displs))
31008 #endif
31009  CALL mpi_igatherv(sendbuf, sendcount, mpi_complex, &
31010  recvbuf, recvcounts, displs, mpi_complex, &
31011  root, comm%handle, request%handle, ierr)
31012  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_gatherv @ "//routinen)
31013  CALL add_perf(perf_id=24, &
31014  count=1, &
31015  msg_size=sendcount*(2*real_4_size))
31016 #else
31017  mark_used(sendcount)
31018  mark_used(recvcounts)
31019  mark_used(root)
31020  mark_used(comm)
31021  recvbuf(1 + displs(1):1 + displs(1) + recvcounts(1)) = sendbuf(1:sendcount)
31022  request = mp_request_null
31023 #endif
31024  CALL mp_timestop(handle)
31025  END SUBROUTINE mp_igatherv_cv
31026 
31027 ! **************************************************************************************************
31028 !> \brief Gathers a datum from all processes and all processes receive the
31029 !> same data
31030 !> \param[in] msgout Datum to send
31031 !> \param[out] msgin Received data
31032 !> \param[in] comm Message passing environment identifier
31033 !> \par Data size
31034 !> All processes send equal-sized data
31035 !> \par MPI mapping
31036 !> mpi_allgather
31037 ! **************************************************************************************************
31038  SUBROUTINE mp_allgather_c (msgout, msgin, comm)
31039  COMPLEX(kind=real_4), INTENT(IN) :: msgout
31040  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:)
31041  CLASS(mp_comm_type), INTENT(IN) :: comm
31042 
31043  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c'
31044 
31045  INTEGER :: handle
31046 #if defined(__parallel)
31047  INTEGER :: ierr, rcount, scount
31048 #endif
31049 
31050  CALL mp_timeset(routinen, handle)
31051 
31052 #if defined(__parallel)
31053  scount = 1
31054  rcount = 1
31055  CALL mpi_allgather(msgout, scount, mpi_complex, &
31056  msgin, rcount, mpi_complex, &
31057  comm%handle, ierr)
31058  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31059 #else
31060  mark_used(comm)
31061  msgin = msgout
31062 #endif
31063  CALL mp_timestop(handle)
31064  END SUBROUTINE mp_allgather_c
31065 
31066 ! **************************************************************************************************
31067 !> \brief Gathers a datum from all processes and all processes receive the
31068 !> same data
31069 !> \param[in] msgout Datum to send
31070 !> \param[out] msgin Received data
31071 !> \param[in] comm Message passing environment identifier
31072 !> \par Data size
31073 !> All processes send equal-sized data
31074 !> \par MPI mapping
31075 !> mpi_allgather
31076 ! **************************************************************************************************
31077  SUBROUTINE mp_allgather_c2(msgout, msgin, comm)
31078  COMPLEX(kind=real_4), INTENT(IN) :: msgout
31079  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
31080  CLASS(mp_comm_type), INTENT(IN) :: comm
31081 
31082  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c2'
31083 
31084  INTEGER :: handle
31085 #if defined(__parallel)
31086  INTEGER :: ierr, rcount, scount
31087 #endif
31088 
31089  CALL mp_timeset(routinen, handle)
31090 
31091 #if defined(__parallel)
31092  scount = 1
31093  rcount = 1
31094  CALL mpi_allgather(msgout, scount, mpi_complex, &
31095  msgin, rcount, mpi_complex, &
31096  comm%handle, ierr)
31097  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31098 #else
31099  mark_used(comm)
31100  msgin = msgout
31101 #endif
31102  CALL mp_timestop(handle)
31103  END SUBROUTINE mp_allgather_c2
31104 
31105 ! **************************************************************************************************
31106 !> \brief Gathers a datum from all processes and all processes receive the
31107 !> same data
31108 !> \param[in] msgout Datum to send
31109 !> \param[out] msgin Received data
31110 !> \param[in] comm Message passing environment identifier
31111 !> \par Data size
31112 !> All processes send equal-sized data
31113 !> \par MPI mapping
31114 !> mpi_allgather
31115 ! **************************************************************************************************
31116  SUBROUTINE mp_iallgather_c (msgout, msgin, comm, request)
31117  COMPLEX(kind=real_4), INTENT(IN) :: msgout
31118  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:)
31119  CLASS(mp_comm_type), INTENT(IN) :: comm
31120  TYPE(mp_request_type), INTENT(OUT) :: request
31121 
31122  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c'
31123 
31124  INTEGER :: handle
31125 #if defined(__parallel)
31126  INTEGER :: ierr, rcount, scount
31127 #endif
31128 
31129  CALL mp_timeset(routinen, handle)
31130 
31131 #if defined(__parallel)
31132 #if !defined(__GNUC__) || __GNUC__ >= 9
31133  cpassert(is_contiguous(msgin))
31134 #endif
31135  scount = 1
31136  rcount = 1
31137  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31138  msgin, rcount, mpi_complex, &
31139  comm%handle, request%handle, ierr)
31140  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31141 #else
31142  mark_used(comm)
31143  msgin = msgout
31144  request = mp_request_null
31145 #endif
31146  CALL mp_timestop(handle)
31147  END SUBROUTINE mp_iallgather_c
31148 
31149 ! **************************************************************************************************
31150 !> \brief Gathers vector data from all processes and all processes receive the
31151 !> same data
31152 !> \param[in] msgout Rank-1 data to send
31153 !> \param[out] msgin Received data
31154 !> \param[in] comm Message passing environment identifier
31155 !> \par Data size
31156 !> All processes send equal-sized data
31157 !> \par Ranks
31158 !> The last rank counts the processes
31159 !> \par MPI mapping
31160 !> mpi_allgather
31161 ! **************************************************************************************************
31162  SUBROUTINE mp_allgather_c12(msgout, msgin, comm)
31163  COMPLEX(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:)
31164  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
31165  CLASS(mp_comm_type), INTENT(IN) :: comm
31166 
31167  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c12'
31168 
31169  INTEGER :: handle
31170 #if defined(__parallel)
31171  INTEGER :: ierr, rcount, scount
31172 #endif
31173 
31174  CALL mp_timeset(routinen, handle)
31175 
31176 #if defined(__parallel)
31177  scount = SIZE(msgout(:))
31178  rcount = scount
31179  CALL mpi_allgather(msgout, scount, mpi_complex, &
31180  msgin, rcount, mpi_complex, &
31181  comm%handle, ierr)
31182  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31183 #else
31184  mark_used(comm)
31185  msgin(:, 1) = msgout(:)
31186 #endif
31187  CALL mp_timestop(handle)
31188  END SUBROUTINE mp_allgather_c12
31189 
31190 ! **************************************************************************************************
31191 !> \brief Gathers matrix data from all processes and all processes receive the
31192 !> same data
31193 !> \param[in] msgout Rank-2 data to send
31194 !> \param msgin ...
31195 !> \param comm ...
31196 !> \note see mp_allgather_c12
31197 ! **************************************************************************************************
31198  SUBROUTINE mp_allgather_c23(msgout, msgin, comm)
31199  COMPLEX(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
31200  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :)
31201  CLASS(mp_comm_type), INTENT(IN) :: comm
31202 
31203  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c23'
31204 
31205  INTEGER :: handle
31206 #if defined(__parallel)
31207  INTEGER :: ierr, rcount, scount
31208 #endif
31209 
31210  CALL mp_timeset(routinen, handle)
31211 
31212 #if defined(__parallel)
31213  scount = SIZE(msgout(:, :))
31214  rcount = scount
31215  CALL mpi_allgather(msgout, scount, mpi_complex, &
31216  msgin, rcount, mpi_complex, &
31217  comm%handle, ierr)
31218  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31219 #else
31220  mark_used(comm)
31221  msgin(:, :, 1) = msgout(:, :)
31222 #endif
31223  CALL mp_timestop(handle)
31224  END SUBROUTINE mp_allgather_c23
31225 
31226 ! **************************************************************************************************
31227 !> \brief Gathers rank-3 data from all processes and all processes receive the
31228 !> same data
31229 !> \param[in] msgout Rank-3 data to send
31230 !> \param msgin ...
31231 !> \param comm ...
31232 !> \note see mp_allgather_c12
31233 ! **************************************************************************************************
31234  SUBROUTINE mp_allgather_c34(msgout, msgin, comm)
31235  COMPLEX(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :, :)
31236  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :, :, :)
31237  CLASS(mp_comm_type), INTENT(IN) :: comm
31238 
31239  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c34'
31240 
31241  INTEGER :: handle
31242 #if defined(__parallel)
31243  INTEGER :: ierr, rcount, scount
31244 #endif
31245 
31246  CALL mp_timeset(routinen, handle)
31247 
31248 #if defined(__parallel)
31249  scount = SIZE(msgout(:, :, :))
31250  rcount = scount
31251  CALL mpi_allgather(msgout, scount, mpi_complex, &
31252  msgin, rcount, mpi_complex, &
31253  comm%handle, ierr)
31254  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31255 #else
31256  mark_used(comm)
31257  msgin(:, :, :, 1) = msgout(:, :, :)
31258 #endif
31259  CALL mp_timestop(handle)
31260  END SUBROUTINE mp_allgather_c34
31261 
31262 ! **************************************************************************************************
31263 !> \brief Gathers rank-2 data from all processes and all processes receive the
31264 !> same data
31265 !> \param[in] msgout Rank-2 data to send
31266 !> \param msgin ...
31267 !> \param comm ...
31268 !> \note see mp_allgather_c12
31269 ! **************************************************************************************************
31270  SUBROUTINE mp_allgather_c22(msgout, msgin, comm)
31271  COMPLEX(kind=real_4), INTENT(IN), CONTIGUOUS :: msgout(:, :)
31272  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msgin(:, :)
31273  CLASS(mp_comm_type), INTENT(IN) :: comm
31274 
31275  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgather_c22'
31276 
31277  INTEGER :: handle
31278 #if defined(__parallel)
31279  INTEGER :: ierr, rcount, scount
31280 #endif
31281 
31282  CALL mp_timeset(routinen, handle)
31283 
31284 #if defined(__parallel)
31285  scount = SIZE(msgout(:, :))
31286  rcount = scount
31287  CALL mpi_allgather(msgout, scount, mpi_complex, &
31288  msgin, rcount, mpi_complex, &
31289  comm%handle, ierr)
31290  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgather @ "//routinen)
31291 #else
31292  mark_used(comm)
31293  msgin(:, :) = msgout(:, :)
31294 #endif
31295  CALL mp_timestop(handle)
31296  END SUBROUTINE mp_allgather_c22
31297 
31298 ! **************************************************************************************************
31299 !> \brief Gathers rank-1 data from all processes and all processes receive the
31300 !> same data
31301 !> \param[in] msgout Rank-1 data to send
31302 !> \param msgin ...
31303 !> \param comm ...
31304 !> \param request ...
31305 !> \note see mp_allgather_c11
31306 ! **************************************************************************************************
31307  SUBROUTINE mp_iallgather_c11(msgout, msgin, comm, request)
31308  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:)
31309  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:)
31310  CLASS(mp_comm_type), INTENT(IN) :: comm
31311  TYPE(mp_request_type), INTENT(OUT) :: request
31312 
31313  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c11'
31314 
31315  INTEGER :: handle
31316 #if defined(__parallel)
31317  INTEGER :: ierr, rcount, scount
31318 #endif
31319 
31320  CALL mp_timeset(routinen, handle)
31321 
31322 #if defined(__parallel)
31323 #if !defined(__GNUC__) || __GNUC__ >= 9
31324  cpassert(is_contiguous(msgout))
31325  cpassert(is_contiguous(msgin))
31326 #endif
31327  scount = SIZE(msgout(:))
31328  rcount = scount
31329  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31330  msgin, rcount, mpi_complex, &
31331  comm%handle, request%handle, ierr)
31332  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
31333 #else
31334  mark_used(comm)
31335  msgin = msgout
31336  request = mp_request_null
31337 #endif
31338  CALL mp_timestop(handle)
31339  END SUBROUTINE mp_iallgather_c11
31340 
31341 ! **************************************************************************************************
31342 !> \brief Gathers rank-2 data from all processes and all processes receive the
31343 !> same data
31344 !> \param[in] msgout Rank-2 data to send
31345 !> \param msgin ...
31346 !> \param comm ...
31347 !> \param request ...
31348 !> \note see mp_allgather_c12
31349 ! **************************************************************************************************
31350  SUBROUTINE mp_iallgather_c13(msgout, msgin, comm, request)
31351  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:)
31352  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:, :, :)
31353  CLASS(mp_comm_type), INTENT(IN) :: comm
31354  TYPE(mp_request_type), INTENT(OUT) :: request
31355 
31356  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c13'
31357 
31358  INTEGER :: handle
31359 #if defined(__parallel)
31360  INTEGER :: ierr, rcount, scount
31361 #endif
31362 
31363  CALL mp_timeset(routinen, handle)
31364 
31365 #if defined(__parallel)
31366 #if !defined(__GNUC__) || __GNUC__ >= 9
31367  cpassert(is_contiguous(msgout))
31368  cpassert(is_contiguous(msgin))
31369 #endif
31370 
31371  scount = SIZE(msgout(:))
31372  rcount = scount
31373  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31374  msgin, rcount, mpi_complex, &
31375  comm%handle, request%handle, ierr)
31376  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
31377 #else
31378  mark_used(comm)
31379  msgin(:, 1, 1) = msgout(:)
31380  request = mp_request_null
31381 #endif
31382  CALL mp_timestop(handle)
31383  END SUBROUTINE mp_iallgather_c13
31384 
31385 ! **************************************************************************************************
31386 !> \brief Gathers rank-2 data from all processes and all processes receive the
31387 !> same data
31388 !> \param[in] msgout Rank-2 data to send
31389 !> \param msgin ...
31390 !> \param comm ...
31391 !> \param request ...
31392 !> \note see mp_allgather_c12
31393 ! **************************************************************************************************
31394  SUBROUTINE mp_iallgather_c22(msgout, msgin, comm, request)
31395  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:, :)
31396  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:, :)
31397  CLASS(mp_comm_type), INTENT(IN) :: comm
31398  TYPE(mp_request_type), INTENT(OUT) :: request
31399 
31400  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c22'
31401 
31402  INTEGER :: handle
31403 #if defined(__parallel)
31404  INTEGER :: ierr, rcount, scount
31405 #endif
31406 
31407  CALL mp_timeset(routinen, handle)
31408 
31409 #if defined(__parallel)
31410 #if !defined(__GNUC__) || __GNUC__ >= 9
31411  cpassert(is_contiguous(msgout))
31412  cpassert(is_contiguous(msgin))
31413 #endif
31414 
31415  scount = SIZE(msgout(:, :))
31416  rcount = scount
31417  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31418  msgin, rcount, mpi_complex, &
31419  comm%handle, request%handle, ierr)
31420  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
31421 #else
31422  mark_used(comm)
31423  msgin(:, :) = msgout(:, :)
31424  request = mp_request_null
31425 #endif
31426  CALL mp_timestop(handle)
31427  END SUBROUTINE mp_iallgather_c22
31428 
31429 ! **************************************************************************************************
31430 !> \brief Gathers rank-2 data from all processes and all processes receive the
31431 !> same data
31432 !> \param[in] msgout Rank-2 data to send
31433 !> \param msgin ...
31434 !> \param comm ...
31435 !> \param request ...
31436 !> \note see mp_allgather_c12
31437 ! **************************************************************************************************
31438  SUBROUTINE mp_iallgather_c24(msgout, msgin, comm, request)
31439  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:, :)
31440  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:, :, :, :)
31441  CLASS(mp_comm_type), INTENT(IN) :: comm
31442  TYPE(mp_request_type), INTENT(OUT) :: request
31443 
31444  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c24'
31445 
31446  INTEGER :: handle
31447 #if defined(__parallel)
31448  INTEGER :: ierr, rcount, scount
31449 #endif
31450 
31451  CALL mp_timeset(routinen, handle)
31452 
31453 #if defined(__parallel)
31454 #if !defined(__GNUC__) || __GNUC__ >= 9
31455  cpassert(is_contiguous(msgout))
31456  cpassert(is_contiguous(msgin))
31457 #endif
31458 
31459  scount = SIZE(msgout(:, :))
31460  rcount = scount
31461  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31462  msgin, rcount, mpi_complex, &
31463  comm%handle, request%handle, ierr)
31464  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
31465 #else
31466  mark_used(comm)
31467  msgin(:, :, 1, 1) = msgout(:, :)
31468  request = mp_request_null
31469 #endif
31470  CALL mp_timestop(handle)
31471  END SUBROUTINE mp_iallgather_c24
31472 
31473 ! **************************************************************************************************
31474 !> \brief Gathers rank-3 data from all processes and all processes receive the
31475 !> same data
31476 !> \param[in] msgout Rank-3 data to send
31477 !> \param msgin ...
31478 !> \param comm ...
31479 !> \param request ...
31480 !> \note see mp_allgather_c12
31481 ! **************************************************************************************************
31482  SUBROUTINE mp_iallgather_c33(msgout, msgin, comm, request)
31483  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:, :, :)
31484  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:, :, :)
31485  CLASS(mp_comm_type), INTENT(IN) :: comm
31486  TYPE(mp_request_type), INTENT(OUT) :: request
31487 
31488  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgather_c33'
31489 
31490  INTEGER :: handle
31491 #if defined(__parallel)
31492  INTEGER :: ierr, rcount, scount
31493 #endif
31494 
31495  CALL mp_timeset(routinen, handle)
31496 
31497 #if defined(__parallel)
31498 #if !defined(__GNUC__) || __GNUC__ >= 9
31499  cpassert(is_contiguous(msgout))
31500  cpassert(is_contiguous(msgin))
31501 #endif
31502 
31503  scount = SIZE(msgout(:, :, :))
31504  rcount = scount
31505  CALL mpi_iallgather(msgout, scount, mpi_complex, &
31506  msgin, rcount, mpi_complex, &
31507  comm%handle, request%handle, ierr)
31508  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgather @ "//routinen)
31509 #else
31510  mark_used(comm)
31511  msgin(:, :, :) = msgout(:, :, :)
31512  request = mp_request_null
31513 #endif
31514  CALL mp_timestop(handle)
31515  END SUBROUTINE mp_iallgather_c33
31516 
31517 ! **************************************************************************************************
31518 !> \brief Gathers vector data from all processes and all processes receive the
31519 !> same data
31520 !> \param[in] msgout Rank-1 data to send
31521 !> \param[out] msgin Received data
31522 !> \param[in] rcount Size of sent data for every process
31523 !> \param[in] rdispl Offset of sent data for every process
31524 !> \param[in] comm Message passing environment identifier
31525 !> \par Data size
31526 !> Processes can send different-sized data
31527 !> \par Ranks
31528 !> The last rank counts the processes
31529 !> \par Offsets
31530 !> Offsets are from 0
31531 !> \par MPI mapping
31532 !> mpi_allgather
31533 ! **************************************************************************************************
31534  SUBROUTINE mp_allgatherv_cv(msgout, msgin, rcount, rdispl, comm)
31535  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
31536  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
31537  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
31538  CLASS(mp_comm_type), INTENT(IN) :: comm
31539 
31540  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_cv'
31541 
31542  INTEGER :: handle
31543 #if defined(__parallel)
31544  INTEGER :: ierr, scount
31545 #endif
31546 
31547  CALL mp_timeset(routinen, handle)
31548 
31549 #if defined(__parallel)
31550  scount = SIZE(msgout)
31551  CALL mpi_allgatherv(msgout, scount, mpi_complex, msgin, rcount, &
31552  rdispl, mpi_complex, comm%handle, ierr)
31553  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
31554 #else
31555  mark_used(rcount)
31556  mark_used(rdispl)
31557  mark_used(comm)
31558  msgin = msgout
31559 #endif
31560  CALL mp_timestop(handle)
31561  END SUBROUTINE mp_allgatherv_cv
31562 
31563 ! **************************************************************************************************
31564 !> \brief Gathers vector data from all processes and all processes receive the
31565 !> same data
31566 !> \param[in] msgout Rank-1 data to send
31567 !> \param[out] msgin Received data
31568 !> \param[in] rcount Size of sent data for every process
31569 !> \param[in] rdispl Offset of sent data for every process
31570 !> \param[in] comm Message passing environment identifier
31571 !> \par Data size
31572 !> Processes can send different-sized data
31573 !> \par Ranks
31574 !> The last rank counts the processes
31575 !> \par Offsets
31576 !> Offsets are from 0
31577 !> \par MPI mapping
31578 !> mpi_allgather
31579 ! **************************************************************************************************
31580  SUBROUTINE mp_allgatherv_cm2(msgout, msgin, rcount, rdispl, comm)
31581  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
31582  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:, :)
31583  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
31584  CLASS(mp_comm_type), INTENT(IN) :: comm
31585 
31586  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allgatherv_cv'
31587 
31588  INTEGER :: handle
31589 #if defined(__parallel)
31590  INTEGER :: ierr, scount
31591 #endif
31592 
31593  CALL mp_timeset(routinen, handle)
31594 
31595 #if defined(__parallel)
31596  scount = SIZE(msgout)
31597  CALL mpi_allgatherv(msgout, scount, mpi_complex, msgin, rcount, &
31598  rdispl, mpi_complex, comm%handle, ierr)
31599  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_allgatherv @ "//routinen)
31600 #else
31601  mark_used(rcount)
31602  mark_used(rdispl)
31603  mark_used(comm)
31604  msgin = msgout
31605 #endif
31606  CALL mp_timestop(handle)
31607  END SUBROUTINE mp_allgatherv_cm2
31608 
31609 ! **************************************************************************************************
31610 !> \brief Gathers vector data from all processes and all processes receive the
31611 !> same data
31612 !> \param[in] msgout Rank-1 data to send
31613 !> \param[out] msgin Received data
31614 !> \param[in] rcount Size of sent data for every process
31615 !> \param[in] rdispl Offset of sent data for every process
31616 !> \param[in] comm Message passing environment identifier
31617 !> \par Data size
31618 !> Processes can send different-sized data
31619 !> \par Ranks
31620 !> The last rank counts the processes
31621 !> \par Offsets
31622 !> Offsets are from 0
31623 !> \par MPI mapping
31624 !> mpi_allgather
31625 ! **************************************************************************************************
31626  SUBROUTINE mp_iallgatherv_cv(msgout, msgin, rcount, rdispl, comm, request)
31627  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:)
31628  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:)
31629  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:), rdispl(:)
31630  CLASS(mp_comm_type), INTENT(IN) :: comm
31631  TYPE(mp_request_type), INTENT(OUT) :: request
31632 
31633  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_cv'
31634 
31635  INTEGER :: handle
31636 #if defined(__parallel)
31637  INTEGER :: ierr, scount, rsize
31638 #endif
31639 
31640  CALL mp_timeset(routinen, handle)
31641 
31642 #if defined(__parallel)
31643 #if !defined(__GNUC__) || __GNUC__ >= 9
31644  cpassert(is_contiguous(msgout))
31645  cpassert(is_contiguous(msgin))
31646  cpassert(is_contiguous(rcount))
31647  cpassert(is_contiguous(rdispl))
31648 #endif
31649 
31650  scount = SIZE(msgout)
31651  rsize = SIZE(rcount)
31652  CALL mp_iallgatherv_cv_internal(msgout, scount, msgin, rsize, rcount, &
31653  rdispl, comm, request, ierr)
31654  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
31655 #else
31656  mark_used(rcount)
31657  mark_used(rdispl)
31658  mark_used(comm)
31659  msgin = msgout
31660  request = mp_request_null
31661 #endif
31662  CALL mp_timestop(handle)
31663  END SUBROUTINE mp_iallgatherv_cv
31664 
31665 ! **************************************************************************************************
31666 !> \brief Gathers vector data from all processes and all processes receive the
31667 !> same data
31668 !> \param[in] msgout Rank-1 data to send
31669 !> \param[out] msgin Received data
31670 !> \param[in] rcount Size of sent data for every process
31671 !> \param[in] rdispl Offset of sent data for every process
31672 !> \param[in] comm Message passing environment identifier
31673 !> \par Data size
31674 !> Processes can send different-sized data
31675 !> \par Ranks
31676 !> The last rank counts the processes
31677 !> \par Offsets
31678 !> Offsets are from 0
31679 !> \par MPI mapping
31680 !> mpi_allgather
31681 ! **************************************************************************************************
31682  SUBROUTINE mp_iallgatherv_cv2(msgout, msgin, rcount, rdispl, comm, request)
31683  COMPLEX(kind=real_4), INTENT(IN) :: msgout(:)
31684  COMPLEX(kind=real_4), INTENT(OUT) :: msgin(:)
31685  INTEGER, INTENT(IN) :: rcount(:, :), rdispl(:, :)
31686  CLASS(mp_comm_type), INTENT(IN) :: comm
31687  TYPE(mp_request_type), INTENT(OUT) :: request
31688 
31689  CHARACTER(len=*), PARAMETER :: routinen = 'mp_iallgatherv_cv2'
31690 
31691  INTEGER :: handle
31692 #if defined(__parallel)
31693  INTEGER :: ierr, scount, rsize
31694 #endif
31695 
31696  CALL mp_timeset(routinen, handle)
31697 
31698 #if defined(__parallel)
31699 #if !defined(__GNUC__) || __GNUC__ >= 9
31700  cpassert(is_contiguous(msgout))
31701  cpassert(is_contiguous(msgin))
31702  cpassert(is_contiguous(rcount))
31703  cpassert(is_contiguous(rdispl))
31704 #endif
31705 
31706  scount = SIZE(msgout)
31707  rsize = SIZE(rcount)
31708  CALL mp_iallgatherv_cv_internal(msgout, scount, msgin, rsize, rcount, &
31709  rdispl, comm, request, ierr)
31710  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_iallgatherv @ "//routinen)
31711 #else
31712  mark_used(rcount)
31713  mark_used(rdispl)
31714  mark_used(comm)
31715  msgin = msgout
31716  request = mp_request_null
31717 #endif
31718  CALL mp_timestop(handle)
31719  END SUBROUTINE mp_iallgatherv_cv2
31720 
31721 ! **************************************************************************************************
31722 !> \brief wrapper needed to deal with interfaces as present in openmpi 1.8.1
31723 !> the issue is with the rank of rcount and rdispl
31724 !> \param count ...
31725 !> \param array_of_requests ...
31726 !> \param array_of_statuses ...
31727 !> \param ierr ...
31728 !> \author Alfio Lazzaro
31729 ! **************************************************************************************************
31730 #if defined(__parallel)
31731  SUBROUTINE mp_iallgatherv_cv_internal(msgout, scount, msgin, rsize, rcount, rdispl, comm, request, ierr)
31732  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:)
31733  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
31734  INTEGER, INTENT(IN) :: rsize
31735  INTEGER, INTENT(IN) :: rcount(rsize), rdispl(rsize), scount
31736  CLASS(mp_comm_type), INTENT(IN) :: comm
31737  TYPE(mp_request_type), INTENT(OUT) :: request
31738  INTEGER, INTENT(INOUT) :: ierr
31739 
31740  CALL mpi_iallgatherv(msgout, scount, mpi_complex, msgin, rcount, &
31741  rdispl, mpi_complex, comm%handle, request%handle, ierr)
31742 
31743  END SUBROUTINE mp_iallgatherv_cv_internal
31744 #endif
31745 
31746 ! **************************************************************************************************
31747 !> \brief Sums a vector and partitions the result among processes
31748 !> \param[in] msgout Data to sum
31749 !> \param[out] msgin Received portion of summed data
31750 !> \param[in] rcount Partition sizes of the summed data for
31751 !> every process
31752 !> \param[in] comm Message passing environment identifier
31753 ! **************************************************************************************************
31754  SUBROUTINE mp_sum_scatter_cv(msgout, msgin, rcount, comm)
31755  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgout(:, :)
31756  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgin(:)
31757  INTEGER, CONTIGUOUS, INTENT(IN) :: rcount(:)
31758  CLASS(mp_comm_type), INTENT(IN) :: comm
31759 
31760  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sum_scatter_cv'
31761 
31762  INTEGER :: handle
31763 #if defined(__parallel)
31764  INTEGER :: ierr
31765 #endif
31766 
31767  CALL mp_timeset(routinen, handle)
31768 
31769 #if defined(__parallel)
31770  CALL mpi_reduce_scatter(msgout, msgin, rcount, mpi_complex, mpi_sum, &
31771  comm%handle, ierr)
31772  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_reduce_scatter @ "//routinen)
31773 
31774  CALL add_perf(perf_id=3, count=1, &
31775  msg_size=rcount(1)*2*(2*real_4_size))
31776 #else
31777  mark_used(rcount)
31778  mark_used(comm)
31779  msgin = msgout(:, 1)
31780 #endif
31781  CALL mp_timestop(handle)
31782  END SUBROUTINE mp_sum_scatter_cv
31783 
31784 ! **************************************************************************************************
31785 !> \brief Sends and receives vector data
31786 !> \param[in] msgin Data to send
31787 !> \param[in] dest Process to send data to
31788 !> \param[out] msgout Received data
31789 !> \param[in] source Process from which to receive
31790 !> \param[in] comm Message passing environment identifier
31791 !> \param[in] tag Send and recv tag (default: 0)
31792 ! **************************************************************************************************
31793  SUBROUTINE mp_sendrecv_c (msgin, dest, msgout, source, comm, tag)
31794  COMPLEX(kind=real_4), INTENT(IN) :: msgin
31795  INTEGER, INTENT(IN) :: dest
31796  COMPLEX(kind=real_4), INTENT(OUT) :: msgout
31797  INTEGER, INTENT(IN) :: source
31798  CLASS(mp_comm_type), INTENT(IN) :: comm
31799  INTEGER, INTENT(IN), OPTIONAL :: tag
31800 
31801  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_c'
31802 
31803  INTEGER :: handle
31804 #if defined(__parallel)
31805  INTEGER :: ierr, msglen_in, msglen_out, &
31806  recv_tag, send_tag
31807 #endif
31808 
31809  CALL mp_timeset(routinen, handle)
31810 
31811 #if defined(__parallel)
31812  msglen_in = 1
31813  msglen_out = 1
31814  send_tag = 0 ! cannot think of something better here, this might be dangerous
31815  recv_tag = 0 ! cannot think of something better here, this might be dangerous
31816  IF (PRESENT(tag)) THEN
31817  send_tag = tag
31818  recv_tag = tag
31819  END IF
31820  CALL mpi_sendrecv(msgin, msglen_in, mpi_complex, dest, send_tag, msgout, &
31821  msglen_out, mpi_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
31822  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
31823  CALL add_perf(perf_id=7, count=1, &
31824  msg_size=(msglen_in + msglen_out)*(2*real_4_size)/2)
31825 #else
31826  mark_used(dest)
31827  mark_used(source)
31828  mark_used(comm)
31829  mark_used(tag)
31830  msgout = msgin
31831 #endif
31832  CALL mp_timestop(handle)
31833  END SUBROUTINE mp_sendrecv_c
31834 
31835 ! **************************************************************************************************
31836 !> \brief Sends and receives vector data
31837 !> \param[in] msgin Data to send
31838 !> \param[in] dest Process to send data to
31839 !> \param[out] msgout Received data
31840 !> \param[in] source Process from which to receive
31841 !> \param[in] comm Message passing environment identifier
31842 !> \param[in] tag Send and recv tag (default: 0)
31843 ! **************************************************************************************************
31844  SUBROUTINE mp_sendrecv_cv(msgin, dest, msgout, source, comm, tag)
31845  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:)
31846  INTEGER, INTENT(IN) :: dest
31847  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:)
31848  INTEGER, INTENT(IN) :: source
31849  CLASS(mp_comm_type), INTENT(IN) :: comm
31850  INTEGER, INTENT(IN), OPTIONAL :: tag
31851 
31852  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_cv'
31853 
31854  INTEGER :: handle
31855 #if defined(__parallel)
31856  INTEGER :: ierr, msglen_in, msglen_out, &
31857  recv_tag, send_tag
31858 #endif
31859 
31860  CALL mp_timeset(routinen, handle)
31861 
31862 #if defined(__parallel)
31863  msglen_in = SIZE(msgin)
31864  msglen_out = SIZE(msgout)
31865  send_tag = 0 ! cannot think of something better here, this might be dangerous
31866  recv_tag = 0 ! cannot think of something better here, this might be dangerous
31867  IF (PRESENT(tag)) THEN
31868  send_tag = tag
31869  recv_tag = tag
31870  END IF
31871  CALL mpi_sendrecv(msgin, msglen_in, mpi_complex, dest, send_tag, msgout, &
31872  msglen_out, mpi_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
31873  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
31874  CALL add_perf(perf_id=7, count=1, &
31875  msg_size=(msglen_in + msglen_out)*(2*real_4_size)/2)
31876 #else
31877  mark_used(dest)
31878  mark_used(source)
31879  mark_used(comm)
31880  mark_used(tag)
31881  msgout = msgin
31882 #endif
31883  CALL mp_timestop(handle)
31884  END SUBROUTINE mp_sendrecv_cv
31885 
31886 ! **************************************************************************************************
31887 !> \brief Sends and receives matrix data
31888 !> \param msgin ...
31889 !> \param dest ...
31890 !> \param msgout ...
31891 !> \param source ...
31892 !> \param comm ...
31893 !> \param tag ...
31894 !> \note see mp_sendrecv_cv
31895 ! **************************************************************************************************
31896  SUBROUTINE mp_sendrecv_cm2(msgin, dest, msgout, source, comm, tag)
31897  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :)
31898  INTEGER, INTENT(IN) :: dest
31899  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :)
31900  INTEGER, INTENT(IN) :: source
31901  CLASS(mp_comm_type), INTENT(IN) :: comm
31902  INTEGER, INTENT(IN), OPTIONAL :: tag
31903 
31904  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_cm2'
31905 
31906  INTEGER :: handle
31907 #if defined(__parallel)
31908  INTEGER :: ierr, msglen_in, msglen_out, &
31909  recv_tag, send_tag
31910 #endif
31911 
31912  CALL mp_timeset(routinen, handle)
31913 
31914 #if defined(__parallel)
31915  msglen_in = SIZE(msgin, 1)*SIZE(msgin, 2)
31916  msglen_out = SIZE(msgout, 1)*SIZE(msgout, 2)
31917  send_tag = 0 ! cannot think of something better here, this might be dangerous
31918  recv_tag = 0 ! cannot think of something better here, this might be dangerous
31919  IF (PRESENT(tag)) THEN
31920  send_tag = tag
31921  recv_tag = tag
31922  END IF
31923  CALL mpi_sendrecv(msgin, msglen_in, mpi_complex, dest, send_tag, msgout, &
31924  msglen_out, mpi_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
31925  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
31926  CALL add_perf(perf_id=7, count=1, &
31927  msg_size=(msglen_in + msglen_out)*(2*real_4_size)/2)
31928 #else
31929  mark_used(dest)
31930  mark_used(source)
31931  mark_used(comm)
31932  mark_used(tag)
31933  msgout = msgin
31934 #endif
31935  CALL mp_timestop(handle)
31936  END SUBROUTINE mp_sendrecv_cm2
31937 
31938 ! **************************************************************************************************
31939 !> \brief Sends and receives rank-3 data
31940 !> \param msgin ...
31941 !> \param dest ...
31942 !> \param msgout ...
31943 !> \param source ...
31944 !> \param comm ...
31945 !> \note see mp_sendrecv_cv
31946 ! **************************************************************************************************
31947  SUBROUTINE mp_sendrecv_cm3(msgin, dest, msgout, source, comm, tag)
31948  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :)
31949  INTEGER, INTENT(IN) :: dest
31950  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :)
31951  INTEGER, INTENT(IN) :: source
31952  CLASS(mp_comm_type), INTENT(IN) :: comm
31953  INTEGER, INTENT(IN), OPTIONAL :: tag
31954 
31955  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_cm3'
31956 
31957  INTEGER :: handle
31958 #if defined(__parallel)
31959  INTEGER :: ierr, msglen_in, msglen_out, &
31960  recv_tag, send_tag
31961 #endif
31962 
31963  CALL mp_timeset(routinen, handle)
31964 
31965 #if defined(__parallel)
31966  msglen_in = SIZE(msgin)
31967  msglen_out = SIZE(msgout)
31968  send_tag = 0 ! cannot think of something better here, this might be dangerous
31969  recv_tag = 0 ! cannot think of something better here, this might be dangerous
31970  IF (PRESENT(tag)) THEN
31971  send_tag = tag
31972  recv_tag = tag
31973  END IF
31974  CALL mpi_sendrecv(msgin, msglen_in, mpi_complex, dest, send_tag, msgout, &
31975  msglen_out, mpi_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
31976  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
31977  CALL add_perf(perf_id=7, count=1, &
31978  msg_size=(msglen_in + msglen_out)*(2*real_4_size)/2)
31979 #else
31980  mark_used(dest)
31981  mark_used(source)
31982  mark_used(comm)
31983  mark_used(tag)
31984  msgout = msgin
31985 #endif
31986  CALL mp_timestop(handle)
31987  END SUBROUTINE mp_sendrecv_cm3
31988 
31989 ! **************************************************************************************************
31990 !> \brief Sends and receives rank-4 data
31991 !> \param msgin ...
31992 !> \param dest ...
31993 !> \param msgout ...
31994 !> \param source ...
31995 !> \param comm ...
31996 !> \note see mp_sendrecv_cv
31997 ! **************************************************************************************************
31998  SUBROUTINE mp_sendrecv_cm4(msgin, dest, msgout, source, comm, tag)
31999  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msgin(:, :, :, :)
32000  INTEGER, INTENT(IN) :: dest
32001  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(OUT) :: msgout(:, :, :, :)
32002  INTEGER, INTENT(IN) :: source
32003  CLASS(mp_comm_type), INTENT(IN) :: comm
32004  INTEGER, INTENT(IN), OPTIONAL :: tag
32005 
32006  CHARACTER(len=*), PARAMETER :: routinen = 'mp_sendrecv_cm4'
32007 
32008  INTEGER :: handle
32009 #if defined(__parallel)
32010  INTEGER :: ierr, msglen_in, msglen_out, &
32011  recv_tag, send_tag
32012 #endif
32013 
32014  CALL mp_timeset(routinen, handle)
32015 
32016 #if defined(__parallel)
32017  msglen_in = SIZE(msgin)
32018  msglen_out = SIZE(msgout)
32019  send_tag = 0 ! cannot think of something better here, this might be dangerous
32020  recv_tag = 0 ! cannot think of something better here, this might be dangerous
32021  IF (PRESENT(tag)) THEN
32022  send_tag = tag
32023  recv_tag = tag
32024  END IF
32025  CALL mpi_sendrecv(msgin, msglen_in, mpi_complex, dest, send_tag, msgout, &
32026  msglen_out, mpi_complex, source, recv_tag, comm%handle, mpi_status_ignore, ierr)
32027  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_sendrecv @ "//routinen)
32028  CALL add_perf(perf_id=7, count=1, &
32029  msg_size=(msglen_in + msglen_out)*(2*real_4_size)/2)
32030 #else
32031  mark_used(dest)
32032  mark_used(source)
32033  mark_used(comm)
32034  mark_used(tag)
32035  msgout = msgin
32036 #endif
32037  CALL mp_timestop(handle)
32038  END SUBROUTINE mp_sendrecv_cm4
32039 
32040 ! **************************************************************************************************
32041 !> \brief Non-blocking send and receive of a scalar
32042 !> \param[in] msgin Scalar data to send
32043 !> \param[in] dest Which process to send to
32044 !> \param[out] msgout Receive data into this pointer
32045 !> \param[in] source Process to receive from
32046 !> \param[in] comm Message passing environment identifier
32047 !> \param[out] send_request Request handle for the send
32048 !> \param[out] recv_request Request handle for the receive
32049 !> \param[in] tag (optional) tag to differentiate requests
32050 !> \par Implementation
32051 !> Calls mpi_isend and mpi_irecv.
32052 !> \par History
32053 !> 02.2005 created [Alfio Lazzaro]
32054 ! **************************************************************************************************
32055  SUBROUTINE mp_isendrecv_c (msgin, dest, msgout, source, comm, send_request, &
32056  recv_request, tag)
32057  COMPLEX(kind=real_4), INTENT(IN) :: msgin
32058  INTEGER, INTENT(IN) :: dest
32059  COMPLEX(kind=real_4), INTENT(INOUT) :: msgout
32060  INTEGER, INTENT(IN) :: source
32061  CLASS(mp_comm_type), INTENT(IN) :: comm
32062  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
32063  INTEGER, INTENT(in), OPTIONAL :: tag
32064 
32065  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_c'
32066 
32067  INTEGER :: handle
32068 #if defined(__parallel)
32069  INTEGER :: ierr, my_tag
32070 #endif
32071 
32072  CALL mp_timeset(routinen, handle)
32073 
32074 #if defined(__parallel)
32075  my_tag = 0
32076  IF (PRESENT(tag)) my_tag = tag
32077 
32078  CALL mpi_irecv(msgout, 1, mpi_complex, source, my_tag, &
32079  comm%handle, recv_request%handle, ierr)
32080  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
32081 
32082  CALL mpi_isend(msgin, 1, mpi_complex, dest, my_tag, &
32083  comm%handle, send_request%handle, ierr)
32084  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32085 
32086  CALL add_perf(perf_id=8, count=1, msg_size=2*(2*real_4_size))
32087 #else
32088  mark_used(dest)
32089  mark_used(source)
32090  mark_used(comm)
32091  mark_used(tag)
32092  send_request = mp_request_null
32093  recv_request = mp_request_null
32094  msgout = msgin
32095 #endif
32096  CALL mp_timestop(handle)
32097  END SUBROUTINE mp_isendrecv_c
32098 
32099 ! **************************************************************************************************
32100 !> \brief Non-blocking send and receive of a vector
32101 !> \param[in] msgin Vector data to send
32102 !> \param[in] dest Which process to send to
32103 !> \param[out] msgout Receive data into this pointer
32104 !> \param[in] source Process to receive from
32105 !> \param[in] comm Message passing environment identifier
32106 !> \param[out] send_request Request handle for the send
32107 !> \param[out] recv_request Request handle for the receive
32108 !> \param[in] tag (optional) tag to differentiate requests
32109 !> \par Implementation
32110 !> Calls mpi_isend and mpi_irecv.
32111 !> \par History
32112 !> 11.2004 created [Joost VandeVondele]
32113 !> \note
32114 !> arrays can be pointers or assumed shape, but they must be contiguous!
32115 ! **************************************************************************************************
32116  SUBROUTINE mp_isendrecv_cv(msgin, dest, msgout, source, comm, send_request, &
32117  recv_request, tag)
32118  COMPLEX(kind=real_4), DIMENSION(:), INTENT(IN) :: msgin
32119  INTEGER, INTENT(IN) :: dest
32120  COMPLEX(kind=real_4), DIMENSION(:), INTENT(INOUT) :: msgout
32121  INTEGER, INTENT(IN) :: source
32122  CLASS(mp_comm_type), INTENT(IN) :: comm
32123  TYPE(mp_request_type), INTENT(out) :: send_request, recv_request
32124  INTEGER, INTENT(in), OPTIONAL :: tag
32125 
32126  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isendrecv_cv'
32127 
32128  INTEGER :: handle
32129 #if defined(__parallel)
32130  INTEGER :: ierr, msglen, my_tag
32131  COMPLEX(kind=real_4) :: foo
32132 #endif
32133 
32134  CALL mp_timeset(routinen, handle)
32135 
32136 #if defined(__parallel)
32137 #if !defined(__GNUC__) || __GNUC__ >= 9
32138  cpassert(is_contiguous(msgout))
32139  cpassert(is_contiguous(msgin))
32140 #endif
32141 
32142  my_tag = 0
32143  IF (PRESENT(tag)) my_tag = tag
32144 
32145  msglen = SIZE(msgout, 1)
32146  IF (msglen > 0) THEN
32147  CALL mpi_irecv(msgout(1), msglen, mpi_complex, source, my_tag, &
32148  comm%handle, recv_request%handle, ierr)
32149  ELSE
32150  CALL mpi_irecv(foo, msglen, mpi_complex, source, my_tag, &
32151  comm%handle, recv_request%handle, ierr)
32152  END IF
32153  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
32154 
32155  msglen = SIZE(msgin, 1)
32156  IF (msglen > 0) THEN
32157  CALL mpi_isend(msgin(1), msglen, mpi_complex, dest, my_tag, &
32158  comm%handle, send_request%handle, ierr)
32159  ELSE
32160  CALL mpi_isend(foo, msglen, mpi_complex, dest, my_tag, &
32161  comm%handle, send_request%handle, ierr)
32162  END IF
32163  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32164 
32165  msglen = (msglen + SIZE(msgout, 1) + 1)/2
32166  CALL add_perf(perf_id=8, count=1, msg_size=msglen*(2*real_4_size))
32167 #else
32168  mark_used(dest)
32169  mark_used(source)
32170  mark_used(comm)
32171  mark_used(tag)
32172  send_request = mp_request_null
32173  recv_request = mp_request_null
32174  msgout = msgin
32175 #endif
32176  CALL mp_timestop(handle)
32177  END SUBROUTINE mp_isendrecv_cv
32178 
32179 ! **************************************************************************************************
32180 !> \brief Non-blocking send of vector data
32181 !> \param msgin ...
32182 !> \param dest ...
32183 !> \param comm ...
32184 !> \param request ...
32185 !> \param tag ...
32186 !> \par History
32187 !> 08.2003 created [f&j]
32188 !> \note see mp_isendrecv_cv
32189 !> \note
32190 !> arrays can be pointers or assumed shape, but they must be contiguous!
32191 ! **************************************************************************************************
32192  SUBROUTINE mp_isend_cv(msgin, dest, comm, request, tag)
32193  COMPLEX(kind=real_4), DIMENSION(:), INTENT(IN) :: msgin
32194  INTEGER, INTENT(IN) :: dest
32195  CLASS(mp_comm_type), INTENT(IN) :: comm
32196  TYPE(mp_request_type), INTENT(out) :: request
32197  INTEGER, INTENT(in), OPTIONAL :: tag
32198 
32199  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_cv'
32200 
32201  INTEGER :: handle, ierr
32202 #if defined(__parallel)
32203  INTEGER :: msglen, my_tag
32204  COMPLEX(kind=real_4) :: foo(1)
32205 #endif
32206 
32207  CALL mp_timeset(routinen, handle)
32208 
32209 #if defined(__parallel)
32210 #if !defined(__GNUC__) || __GNUC__ >= 9
32211  cpassert(is_contiguous(msgin))
32212 #endif
32213  my_tag = 0
32214  IF (PRESENT(tag)) my_tag = tag
32215 
32216  msglen = SIZE(msgin)
32217  IF (msglen > 0) THEN
32218  CALL mpi_isend(msgin(1), msglen, mpi_complex, dest, my_tag, &
32219  comm%handle, request%handle, ierr)
32220  ELSE
32221  CALL mpi_isend(foo, msglen, mpi_complex, dest, my_tag, &
32222  comm%handle, request%handle, ierr)
32223  END IF
32224  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32225 
32226  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_4_size))
32227 #else
32228  mark_used(msgin)
32229  mark_used(dest)
32230  mark_used(comm)
32231  mark_used(request)
32232  mark_used(tag)
32233  ierr = 1
32234  request = mp_request_null
32235  CALL mp_stop(ierr, "mp_isend called in non parallel case")
32236 #endif
32237  CALL mp_timestop(handle)
32238  END SUBROUTINE mp_isend_cv
32239 
32240 ! **************************************************************************************************
32241 !> \brief Non-blocking send of matrix data
32242 !> \param msgin ...
32243 !> \param dest ...
32244 !> \param comm ...
32245 !> \param request ...
32246 !> \param tag ...
32247 !> \par History
32248 !> 2009-11-25 [UB] Made type-generic for templates
32249 !> \author fawzi
32250 !> \note see mp_isendrecv_cv
32251 !> \note see mp_isend_cv
32252 !> \note
32253 !> arrays can be pointers or assumed shape, but they must be contiguous!
32254 ! **************************************************************************************************
32255  SUBROUTINE mp_isend_cm2(msgin, dest, comm, request, tag)
32256  COMPLEX(kind=real_4), DIMENSION(:, :), INTENT(IN) :: msgin
32257  INTEGER, INTENT(IN) :: dest
32258  CLASS(mp_comm_type), INTENT(IN) :: comm
32259  TYPE(mp_request_type), INTENT(out) :: request
32260  INTEGER, INTENT(in), OPTIONAL :: tag
32261 
32262  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_cm2'
32263 
32264  INTEGER :: handle, ierr
32265 #if defined(__parallel)
32266  INTEGER :: msglen, my_tag
32267  COMPLEX(kind=real_4) :: foo(1)
32268 #endif
32269 
32270  CALL mp_timeset(routinen, handle)
32271 
32272 #if defined(__parallel)
32273 #if !defined(__GNUC__) || __GNUC__ >= 9
32274  cpassert(is_contiguous(msgin))
32275 #endif
32276 
32277  my_tag = 0
32278  IF (PRESENT(tag)) my_tag = tag
32279 
32280  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)
32281  IF (msglen > 0) THEN
32282  CALL mpi_isend(msgin(1, 1), msglen, mpi_complex, dest, my_tag, &
32283  comm%handle, request%handle, ierr)
32284  ELSE
32285  CALL mpi_isend(foo, msglen, mpi_complex, dest, my_tag, &
32286  comm%handle, request%handle, ierr)
32287  END IF
32288  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32289 
32290  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_4_size))
32291 #else
32292  mark_used(msgin)
32293  mark_used(dest)
32294  mark_used(comm)
32295  mark_used(request)
32296  mark_used(tag)
32297  ierr = 1
32298  request = mp_request_null
32299  CALL mp_stop(ierr, "mp_isend called in non parallel case")
32300 #endif
32301  CALL mp_timestop(handle)
32302  END SUBROUTINE mp_isend_cm2
32303 
32304 ! **************************************************************************************************
32305 !> \brief Non-blocking send of rank-3 data
32306 !> \param msgin ...
32307 !> \param dest ...
32308 !> \param comm ...
32309 !> \param request ...
32310 !> \param tag ...
32311 !> \par History
32312 !> 9.2008 added _rm3 subroutine [Iain Bethune]
32313 !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
32314 !> 2009-11-25 [UB] Made type-generic for templates
32315 !> \author fawzi
32316 !> \note see mp_isendrecv_cv
32317 !> \note see mp_isend_cv
32318 !> \note
32319 !> arrays can be pointers or assumed shape, but they must be contiguous!
32320 ! **************************************************************************************************
32321  SUBROUTINE mp_isend_cm3(msgin, dest, comm, request, tag)
32322  COMPLEX(kind=real_4), DIMENSION(:, :, :), INTENT(IN) :: msgin
32323  INTEGER, INTENT(IN) :: dest
32324  CLASS(mp_comm_type), INTENT(IN) :: comm
32325  TYPE(mp_request_type), INTENT(out) :: request
32326  INTEGER, INTENT(in), OPTIONAL :: tag
32327 
32328  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_cm3'
32329 
32330  INTEGER :: handle, ierr
32331 #if defined(__parallel)
32332  INTEGER :: msglen, my_tag
32333  COMPLEX(kind=real_4) :: foo(1)
32334 #endif
32335 
32336  CALL mp_timeset(routinen, handle)
32337 
32338 #if defined(__parallel)
32339 #if !defined(__GNUC__) || __GNUC__ >= 9
32340  cpassert(is_contiguous(msgin))
32341 #endif
32342 
32343  my_tag = 0
32344  IF (PRESENT(tag)) my_tag = tag
32345 
32346  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)
32347  IF (msglen > 0) THEN
32348  CALL mpi_isend(msgin(1, 1, 1), msglen, mpi_complex, dest, my_tag, &
32349  comm%handle, request%handle, ierr)
32350  ELSE
32351  CALL mpi_isend(foo, msglen, mpi_complex, dest, my_tag, &
32352  comm%handle, request%handle, ierr)
32353  END IF
32354  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32355 
32356  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_4_size))
32357 #else
32358  mark_used(msgin)
32359  mark_used(dest)
32360  mark_used(comm)
32361  mark_used(request)
32362  mark_used(tag)
32363  ierr = 1
32364  request = mp_request_null
32365  CALL mp_stop(ierr, "mp_isend called in non parallel case")
32366 #endif
32367  CALL mp_timestop(handle)
32368  END SUBROUTINE mp_isend_cm3
32369 
32370 ! **************************************************************************************************
32371 !> \brief Non-blocking send of rank-4 data
32372 !> \param msgin the input message
32373 !> \param dest the destination processor
32374 !> \param comm the communicator object
32375 !> \param request the communication request id
32376 !> \param tag the message tag
32377 !> \par History
32378 !> 2.2016 added _cm4 subroutine [Nico Holmberg]
32379 !> \author fawzi
32380 !> \note see mp_isend_cv
32381 !> \note
32382 !> arrays can be pointers or assumed shape, but they must be contiguous!
32383 ! **************************************************************************************************
32384  SUBROUTINE mp_isend_cm4(msgin, dest, comm, request, tag)
32385  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), INTENT(IN) :: msgin
32386  INTEGER, INTENT(IN) :: dest
32387  CLASS(mp_comm_type), INTENT(IN) :: comm
32388  TYPE(mp_request_type), INTENT(out) :: request
32389  INTEGER, INTENT(in), OPTIONAL :: tag
32390 
32391  CHARACTER(len=*), PARAMETER :: routinen = 'mp_isend_cm4'
32392 
32393  INTEGER :: handle, ierr
32394 #if defined(__parallel)
32395  INTEGER :: msglen, my_tag
32396  COMPLEX(kind=real_4) :: foo(1)
32397 #endif
32398 
32399  CALL mp_timeset(routinen, handle)
32400 
32401 #if defined(__parallel)
32402 #if !defined(__GNUC__) || __GNUC__ >= 9
32403  cpassert(is_contiguous(msgin))
32404 #endif
32405 
32406  my_tag = 0
32407  IF (PRESENT(tag)) my_tag = tag
32408 
32409  msglen = SIZE(msgin, 1)*SIZE(msgin, 2)*SIZE(msgin, 3)*SIZE(msgin, 4)
32410  IF (msglen > 0) THEN
32411  CALL mpi_isend(msgin(1, 1, 1, 1), msglen, mpi_complex, dest, my_tag, &
32412  comm%handle, request%handle, ierr)
32413  ELSE
32414  CALL mpi_isend(foo, msglen, mpi_complex, dest, my_tag, &
32415  comm%handle, request%handle, ierr)
32416  END IF
32417  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_isend @ "//routinen)
32418 
32419  CALL add_perf(perf_id=11, count=1, msg_size=msglen*(2*real_4_size))
32420 #else
32421  mark_used(msgin)
32422  mark_used(dest)
32423  mark_used(comm)
32424  mark_used(request)
32425  mark_used(tag)
32426  ierr = 1
32427  request = mp_request_null
32428  CALL mp_stop(ierr, "mp_isend called in non parallel case")
32429 #endif
32430  CALL mp_timestop(handle)
32431  END SUBROUTINE mp_isend_cm4
32432 
32433 ! **************************************************************************************************
32434 !> \brief Non-blocking receive of vector data
32435 !> \param msgout ...
32436 !> \param source ...
32437 !> \param comm ...
32438 !> \param request ...
32439 !> \param tag ...
32440 !> \par History
32441 !> 08.2003 created [f&j]
32442 !> 2009-11-25 [UB] Made type-generic for templates
32443 !> \note see mp_isendrecv_cv
32444 !> \note
32445 !> arrays can be pointers or assumed shape, but they must be contiguous!
32446 ! **************************************************************************************************
32447  SUBROUTINE mp_irecv_cv(msgout, source, comm, request, tag)
32448  COMPLEX(kind=real_4), DIMENSION(:), INTENT(INOUT) :: msgout
32449  INTEGER, INTENT(IN) :: source
32450  CLASS(mp_comm_type), INTENT(IN) :: comm
32451  TYPE(mp_request_type), INTENT(out) :: request
32452  INTEGER, INTENT(in), OPTIONAL :: tag
32453 
32454  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_cv'
32455 
32456  INTEGER :: handle
32457 #if defined(__parallel)
32458  INTEGER :: ierr, msglen, my_tag
32459  COMPLEX(kind=real_4) :: foo(1)
32460 #endif
32461 
32462  CALL mp_timeset(routinen, handle)
32463 
32464 #if defined(__parallel)
32465 #if !defined(__GNUC__) || __GNUC__ >= 9
32466  cpassert(is_contiguous(msgout))
32467 #endif
32468 
32469  my_tag = 0
32470  IF (PRESENT(tag)) my_tag = tag
32471 
32472  msglen = SIZE(msgout)
32473  IF (msglen > 0) THEN
32474  CALL mpi_irecv(msgout(1), msglen, mpi_complex, source, my_tag, &
32475  comm%handle, request%handle, ierr)
32476  ELSE
32477  CALL mpi_irecv(foo, msglen, mpi_complex, source, my_tag, &
32478  comm%handle, request%handle, ierr)
32479  END IF
32480  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
32481 
32482  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_4_size))
32483 #else
32484  cpabort("mp_irecv called in non parallel case")
32485  mark_used(msgout)
32486  mark_used(source)
32487  mark_used(comm)
32488  mark_used(tag)
32489  request = mp_request_null
32490 #endif
32491  CALL mp_timestop(handle)
32492  END SUBROUTINE mp_irecv_cv
32493 
32494 ! **************************************************************************************************
32495 !> \brief Non-blocking receive of matrix data
32496 !> \param msgout ...
32497 !> \param source ...
32498 !> \param comm ...
32499 !> \param request ...
32500 !> \param tag ...
32501 !> \par History
32502 !> 2009-11-25 [UB] Made type-generic for templates
32503 !> \author fawzi
32504 !> \note see mp_isendrecv_cv
32505 !> \note see mp_irecv_cv
32506 !> \note
32507 !> arrays can be pointers or assumed shape, but they must be contiguous!
32508 ! **************************************************************************************************
32509  SUBROUTINE mp_irecv_cm2(msgout, source, comm, request, tag)
32510  COMPLEX(kind=real_4), DIMENSION(:, :), INTENT(INOUT) :: msgout
32511  INTEGER, INTENT(IN) :: source
32512  CLASS(mp_comm_type), INTENT(IN) :: comm
32513  TYPE(mp_request_type), INTENT(out) :: request
32514  INTEGER, INTENT(in), OPTIONAL :: tag
32515 
32516  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_cm2'
32517 
32518  INTEGER :: handle
32519 #if defined(__parallel)
32520  INTEGER :: ierr, msglen, my_tag
32521  COMPLEX(kind=real_4) :: foo(1)
32522 #endif
32523 
32524  CALL mp_timeset(routinen, handle)
32525 
32526 #if defined(__parallel)
32527 #if !defined(__GNUC__) || __GNUC__ >= 9
32528  cpassert(is_contiguous(msgout))
32529 #endif
32530 
32531  my_tag = 0
32532  IF (PRESENT(tag)) my_tag = tag
32533 
32534  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)
32535  IF (msglen > 0) THEN
32536  CALL mpi_irecv(msgout(1, 1), msglen, mpi_complex, source, my_tag, &
32537  comm%handle, request%handle, ierr)
32538  ELSE
32539  CALL mpi_irecv(foo, msglen, mpi_complex, source, my_tag, &
32540  comm%handle, request%handle, ierr)
32541  END IF
32542  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_irecv @ "//routinen)
32543 
32544  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_4_size))
32545 #else
32546  mark_used(msgout)
32547  mark_used(source)
32548  mark_used(comm)
32549  mark_used(tag)
32550  request = mp_request_null
32551  cpabort("mp_irecv called in non parallel case")
32552 #endif
32553  CALL mp_timestop(handle)
32554  END SUBROUTINE mp_irecv_cm2
32555 
32556 ! **************************************************************************************************
32557 !> \brief Non-blocking send of rank-3 data
32558 !> \param msgout ...
32559 !> \param source ...
32560 !> \param comm ...
32561 !> \param request ...
32562 !> \param tag ...
32563 !> \par History
32564 !> 9.2008 added _rm3 subroutine [Iain Bethune] (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
32565 !> 2009-11-25 [UB] Made type-generic for templates
32566 !> \author fawzi
32567 !> \note see mp_isendrecv_cv
32568 !> \note see mp_irecv_cv
32569 !> \note
32570 !> arrays can be pointers or assumed shape, but they must be contiguous!
32571 ! **************************************************************************************************
32572  SUBROUTINE mp_irecv_cm3(msgout, source, comm, request, tag)
32573  COMPLEX(kind=real_4), DIMENSION(:, :, :), INTENT(INOUT) :: msgout
32574  INTEGER, INTENT(IN) :: source
32575  CLASS(mp_comm_type), INTENT(IN) :: comm
32576  TYPE(mp_request_type), INTENT(out) :: request
32577  INTEGER, INTENT(in), OPTIONAL :: tag
32578 
32579  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_cm3'
32580 
32581  INTEGER :: handle
32582 #if defined(__parallel)
32583  INTEGER :: ierr, msglen, my_tag
32584  COMPLEX(kind=real_4) :: foo(1)
32585 #endif
32586 
32587  CALL mp_timeset(routinen, handle)
32588 
32589 #if defined(__parallel)
32590 #if !defined(__GNUC__) || __GNUC__ >= 9
32591  cpassert(is_contiguous(msgout))
32592 #endif
32593 
32594  my_tag = 0
32595  IF (PRESENT(tag)) my_tag = tag
32596 
32597  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)
32598  IF (msglen > 0) THEN
32599  CALL mpi_irecv(msgout(1, 1, 1), msglen, mpi_complex, source, my_tag, &
32600  comm%handle, request%handle, ierr)
32601  ELSE
32602  CALL mpi_irecv(foo, msglen, mpi_complex, source, my_tag, &
32603  comm%handle, request%handle, ierr)
32604  END IF
32605  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
32606 
32607  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_4_size))
32608 #else
32609  mark_used(msgout)
32610  mark_used(source)
32611  mark_used(comm)
32612  mark_used(tag)
32613  request = mp_request_null
32614  cpabort("mp_irecv called in non parallel case")
32615 #endif
32616  CALL mp_timestop(handle)
32617  END SUBROUTINE mp_irecv_cm3
32618 
32619 ! **************************************************************************************************
32620 !> \brief Non-blocking receive of rank-4 data
32621 !> \param msgout the output message
32622 !> \param source the source processor
32623 !> \param comm the communicator object
32624 !> \param request the communication request id
32625 !> \param tag the message tag
32626 !> \par History
32627 !> 2.2016 added _cm4 subroutine [Nico Holmberg]
32628 !> \author fawzi
32629 !> \note see mp_irecv_cv
32630 !> \note
32631 !> arrays can be pointers or assumed shape, but they must be contiguous!
32632 ! **************************************************************************************************
32633  SUBROUTINE mp_irecv_cm4(msgout, source, comm, request, tag)
32634  COMPLEX(kind=real_4), DIMENSION(:, :, :, :), INTENT(INOUT) :: msgout
32635  INTEGER, INTENT(IN) :: source
32636  CLASS(mp_comm_type), INTENT(IN) :: comm
32637  TYPE(mp_request_type), INTENT(out) :: request
32638  INTEGER, INTENT(in), OPTIONAL :: tag
32639 
32640  CHARACTER(len=*), PARAMETER :: routinen = 'mp_irecv_cm4'
32641 
32642  INTEGER :: handle
32643 #if defined(__parallel)
32644  INTEGER :: ierr, msglen, my_tag
32645  COMPLEX(kind=real_4) :: foo(1)
32646 #endif
32647 
32648  CALL mp_timeset(routinen, handle)
32649 
32650 #if defined(__parallel)
32651 #if !defined(__GNUC__) || __GNUC__ >= 9
32652  cpassert(is_contiguous(msgout))
32653 #endif
32654 
32655  my_tag = 0
32656  IF (PRESENT(tag)) my_tag = tag
32657 
32658  msglen = SIZE(msgout, 1)*SIZE(msgout, 2)*SIZE(msgout, 3)*SIZE(msgout, 4)
32659  IF (msglen > 0) THEN
32660  CALL mpi_irecv(msgout(1, 1, 1, 1), msglen, mpi_complex, source, my_tag, &
32661  comm%handle, request%handle, ierr)
32662  ELSE
32663  CALL mpi_irecv(foo, msglen, mpi_complex, source, my_tag, &
32664  comm%handle, request%handle, ierr)
32665  END IF
32666  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_ircv @ "//routinen)
32667 
32668  CALL add_perf(perf_id=12, count=1, msg_size=msglen*(2*real_4_size))
32669 #else
32670  mark_used(msgout)
32671  mark_used(source)
32672  mark_used(comm)
32673  mark_used(tag)
32674  request = mp_request_null
32675  cpabort("mp_irecv called in non parallel case")
32676 #endif
32677  CALL mp_timestop(handle)
32678  END SUBROUTINE mp_irecv_cm4
32679 
32680 ! **************************************************************************************************
32681 !> \brief Window initialization function for vector data
32682 !> \param base ...
32683 !> \param comm ...
32684 !> \param win ...
32685 !> \par History
32686 !> 02.2015 created [Alfio Lazzaro]
32687 !> \note
32688 !> arrays can be pointers or assumed shape, but they must be contiguous!
32689 ! **************************************************************************************************
32690  SUBROUTINE mp_win_create_cv(base, comm, win)
32691  COMPLEX(kind=real_4), DIMENSION(:), INTENT(INOUT), CONTIGUOUS :: base
32692  TYPE(mp_comm_type), INTENT(IN) :: comm
32693  CLASS(mp_win_type), INTENT(INOUT) :: win
32694 
32695  CHARACTER(len=*), PARAMETER :: routinen = 'mp_win_create_cv'
32696 
32697  INTEGER :: handle
32698 #if defined(__parallel)
32699  INTEGER :: ierr
32700  INTEGER(kind=mpi_address_kind) :: len
32701  COMPLEX(kind=real_4) :: foo(1)
32702 #endif
32703 
32704  CALL mp_timeset(routinen, handle)
32705 
32706 #if defined(__parallel)
32707 
32708  len = SIZE(base)*(2*real_4_size)
32709  IF (len > 0) THEN
32710  CALL mpi_win_create(base(1), len, (2*real_4_size), mpi_info_null, comm%handle, win%handle, ierr)
32711  ELSE
32712  CALL mpi_win_create(foo, len, (2*real_4_size), mpi_info_null, comm%handle, win%handle, ierr)
32713  END IF
32714  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_win_create @ "//routinen)
32715 
32716  CALL add_perf(perf_id=20, count=1)
32717 #else
32718  mark_used(base)
32719  mark_used(comm)
32720  win%handle = mp_win_null_handle
32721 #endif
32722  CALL mp_timestop(handle)
32723  END SUBROUTINE mp_win_create_cv
32724 
32725 ! **************************************************************************************************
32726 !> \brief Single-sided get function for vector data
32727 !> \param base ...
32728 !> \param comm ...
32729 !> \param win ...
32730 !> \par History
32731 !> 02.2015 created [Alfio Lazzaro]
32732 !> \note
32733 !> arrays can be pointers or assumed shape, but they must be contiguous!
32734 ! **************************************************************************************************
32735  SUBROUTINE mp_rget_cv(base, source, win, win_data, myproc, disp, request, &
32736  origin_datatype, target_datatype)
32737  COMPLEX(kind=real_4), DIMENSION(:), CONTIGUOUS, INTENT(INOUT) :: base
32738  INTEGER, INTENT(IN) :: source
32739  CLASS(mp_win_type), INTENT(IN) :: win
32740  COMPLEX(kind=real_4), DIMENSION(:), INTENT(IN) :: win_data
32741  INTEGER, INTENT(IN), OPTIONAL :: myproc, disp
32742  TYPE(mp_request_type), INTENT(OUT) :: request
32743  TYPE(mp_type_descriptor_type), INTENT(IN), OPTIONAL :: origin_datatype, target_datatype
32744 
32745  CHARACTER(len=*), PARAMETER :: routinen = 'mp_rget_cv'
32746 
32747  INTEGER :: handle
32748 #if defined(__parallel)
32749  INTEGER :: ierr, len, &
32750  origin_len, target_len
32751  LOGICAL :: do_local_copy
32752  INTEGER(kind=mpi_address_kind) :: disp_aint
32753  mpi_data_type :: handle_origin_datatype, handle_target_datatype
32754 #endif
32755 
32756  CALL mp_timeset(routinen, handle)
32757 
32758 #if defined(__parallel)
32759  len = SIZE(base)
32760  disp_aint = 0
32761  IF (PRESENT(disp)) THEN
32762  disp_aint = int(disp, kind=mpi_address_kind)
32763  END IF
32764  handle_origin_datatype = mpi_complex
32765  origin_len = len
32766  IF (PRESENT(origin_datatype)) THEN
32767  handle_origin_datatype = origin_datatype%type_handle
32768  origin_len = 1
32769  END IF
32770  handle_target_datatype = mpi_complex
32771  target_len = len
32772  IF (PRESENT(target_datatype)) THEN
32773  handle_target_datatype = target_datatype%type_handle
32774  target_len = 1
32775  END IF
32776  IF (len > 0) THEN
32777  do_local_copy = .false.
32778  IF (PRESENT(myproc) .AND. .NOT. PRESENT(origin_datatype) .AND. .NOT. PRESENT(target_datatype)) THEN
32779  IF (myproc .EQ. source) do_local_copy = .true.
32780  END IF
32781  IF (do_local_copy) THEN
32782  !$OMP PARALLEL WORKSHARE DEFAULT(none) SHARED(base,win_data,disp_aint,len)
32783  base(:) = win_data(disp_aint + 1:disp_aint + len)
32784  !$OMP END PARALLEL WORKSHARE
32785  request = mp_request_null
32786  ierr = 0
32787  ELSE
32788  CALL mpi_rget(base(1), origin_len, handle_origin_datatype, source, disp_aint, &
32789  target_len, handle_target_datatype, win%handle, request%handle, ierr)
32790  END IF
32791  ELSE
32792  request = mp_request_null
32793  ierr = 0
32794  END IF
32795  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_rget @ "//routinen)
32796 
32797  CALL add_perf(perf_id=25, count=1, msg_size=SIZE(base)*(2*real_4_size))
32798 #else
32799  mark_used(source)
32800  mark_used(win)
32801  mark_used(myproc)
32802  mark_used(origin_datatype)
32803  mark_used(target_datatype)
32804 
32805  request = mp_request_null
32806  !
32807  IF (PRESENT(disp)) THEN
32808  base(:) = win_data(disp + 1:disp + SIZE(base))
32809  ELSE
32810  base(:) = win_data(:SIZE(base))
32811  END IF
32812 
32813 #endif
32814  CALL mp_timestop(handle)
32815  END SUBROUTINE mp_rget_cv
32816 
32817 ! **************************************************************************************************
32818 !> \brief ...
32819 !> \param count ...
32820 !> \param lengths ...
32821 !> \param displs ...
32822 !> \return ...
32823 ! ***************************************************************************
32824  FUNCTION mp_type_indexed_make_c (count, lengths, displs) &
32825  result(type_descriptor)
32826  INTEGER, INTENT(IN) :: count
32827  INTEGER, DIMENSION(1:count), INTENT(IN), TARGET :: lengths, displs
32828  TYPE(mp_type_descriptor_type) :: type_descriptor
32829 
32830  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_indexed_make_c'
32831 
32832  INTEGER :: handle
32833 #if defined(__parallel)
32834  INTEGER :: ierr
32835 #endif
32836 
32837  CALL mp_timeset(routinen, handle)
32838 
32839 #if defined(__parallel)
32840  CALL mpi_type_indexed(count, lengths, displs, mpi_complex, &
32841  type_descriptor%type_handle, ierr)
32842  IF (ierr /= 0) &
32843  cpabort("MPI_Type_Indexed @ "//routinen)
32844  CALL mpi_type_commit(type_descriptor%type_handle, ierr)
32845  IF (ierr /= 0) &
32846  cpabort("MPI_Type_commit @ "//routinen)
32847 #else
32848  type_descriptor%type_handle = 5
32849 #endif
32850  type_descriptor%length = count
32851  NULLIFY (type_descriptor%subtype)
32852  type_descriptor%vector_descriptor(1:2) = 1
32853  type_descriptor%has_indexing = .true.
32854  type_descriptor%index_descriptor%index => lengths
32855  type_descriptor%index_descriptor%chunks => displs
32856 
32857  CALL mp_timestop(handle)
32858 
32859  END FUNCTION mp_type_indexed_make_c
32860 
32861 ! **************************************************************************************************
32862 !> \brief Allocates special parallel memory
32863 !> \param[in] DATA pointer to integer array to allocate
32864 !> \param[in] len number of integers to allocate
32865 !> \param[out] stat (optional) allocation status result
32866 !> \author UB
32867 ! **************************************************************************************************
32868  SUBROUTINE mp_allocate_c (DATA, len, stat)
32869  COMPLEX(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
32870  INTEGER, INTENT(IN) :: len
32871  INTEGER, INTENT(OUT), OPTIONAL :: stat
32872 
32873  CHARACTER(len=*), PARAMETER :: routinen = 'mp_allocate_c'
32874 
32875  INTEGER :: handle, ierr
32876 
32877  CALL mp_timeset(routinen, handle)
32878 
32879 #if defined(__parallel)
32880  NULLIFY (data)
32881  CALL mp_alloc_mem(DATA, len, stat=ierr)
32882  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
32883  CALL mp_stop(ierr, "mpi_alloc_mem @ "//routinen)
32884  CALL add_perf(perf_id=15, count=1)
32885 #else
32886  ALLOCATE (DATA(len), stat=ierr)
32887  IF (ierr /= 0 .AND. .NOT. PRESENT(stat)) &
32888  CALL mp_stop(ierr, "ALLOCATE @ "//routinen)
32889 #endif
32890  IF (PRESENT(stat)) stat = ierr
32891  CALL mp_timestop(handle)
32892  END SUBROUTINE mp_allocate_c
32893 
32894 ! **************************************************************************************************
32895 !> \brief Deallocates special parallel memory
32896 !> \param[in] DATA pointer to special memory to deallocate
32897 !> \param stat ...
32898 !> \author UB
32899 ! **************************************************************************************************
32900  SUBROUTINE mp_deallocate_c (DATA, stat)
32901  COMPLEX(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
32902  INTEGER, INTENT(OUT), OPTIONAL :: stat
32903 
32904  CHARACTER(len=*), PARAMETER :: routinen = 'mp_deallocate_c'
32905 
32906  INTEGER :: handle
32907 #if defined(__parallel)
32908  INTEGER :: ierr
32909 #endif
32910 
32911  CALL mp_timeset(routinen, handle)
32912 
32913 #if defined(__parallel)
32914  CALL mp_free_mem(DATA, ierr)
32915  IF (PRESENT(stat)) THEN
32916  stat = ierr
32917  ELSE
32918  IF (ierr /= 0) CALL mp_stop(ierr, "mpi_free_mem @ "//routinen)
32919  END IF
32920  NULLIFY (data)
32921  CALL add_perf(perf_id=15, count=1)
32922 #else
32923  DEALLOCATE (data)
32924  IF (PRESENT(stat)) stat = 0
32925 #endif
32926  CALL mp_timestop(handle)
32927  END SUBROUTINE mp_deallocate_c
32928 
32929 ! **************************************************************************************************
32930 !> \brief (parallel) Blocking individual file write using explicit offsets
32931 !> (serial) Unformatted stream write
32932 !> \param[in] fh file handle (file storage unit)
32933 !> \param[in] offset file offset (position)
32934 !> \param[in] msg data to be written to the file
32935 !> \param msglen ...
32936 !> \par MPI-I/O mapping mpi_file_write_at
32937 !> \par STREAM-I/O mapping WRITE
32938 !> \param[in](optional) msglen number of the elements of data
32939 ! **************************************************************************************************
32940  SUBROUTINE mp_file_write_at_cv(fh, offset, msg, msglen)
32941  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
32942  CLASS(mp_file_type), INTENT(IN) :: fh
32943  INTEGER, INTENT(IN), OPTIONAL :: msglen
32944  INTEGER(kind=file_offset), INTENT(IN) :: offset
32945 
32946  INTEGER :: msg_len
32947 #if defined(__parallel)
32948  INTEGER :: ierr
32949 #endif
32950 
32951  msg_len = SIZE(msg)
32952  IF (PRESENT(msglen)) msg_len = msglen
32953 #if defined(__parallel)
32954  CALL mpi_file_write_at(fh%handle, offset, msg, msg_len, mpi_complex, mpi_status_ignore, ierr)
32955  IF (ierr .NE. 0) &
32956  cpabort("mpi_file_write_at_cv @ mp_file_write_at_cv")
32957 #else
32958  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
32959 #endif
32960  END SUBROUTINE mp_file_write_at_cv
32961 
32962 ! **************************************************************************************************
32963 !> \brief ...
32964 !> \param fh ...
32965 !> \param offset ...
32966 !> \param msg ...
32967 ! **************************************************************************************************
32968  SUBROUTINE mp_file_write_at_c (fh, offset, msg)
32969  COMPLEX(kind=real_4), INTENT(IN) :: msg
32970  CLASS(mp_file_type), INTENT(IN) :: fh
32971  INTEGER(kind=file_offset), INTENT(IN) :: offset
32972 
32973 #if defined(__parallel)
32974  INTEGER :: ierr
32975 
32976  ierr = 0
32977  CALL mpi_file_write_at(fh%handle, offset, msg, 1, mpi_complex, mpi_status_ignore, ierr)
32978  IF (ierr .NE. 0) &
32979  cpabort("mpi_file_write_at_c @ mp_file_write_at_c")
32980 #else
32981  WRITE (unit=fh%handle, pos=offset + 1) msg
32982 #endif
32983  END SUBROUTINE mp_file_write_at_c
32984 
32985 ! **************************************************************************************************
32986 !> \brief (parallel) Blocking collective file write using explicit offsets
32987 !> (serial) Unformatted stream write
32988 !> \param fh ...
32989 !> \param offset ...
32990 !> \param msg ...
32991 !> \param msglen ...
32992 !> \par MPI-I/O mapping mpi_file_write_at_all
32993 !> \par STREAM-I/O mapping WRITE
32994 ! **************************************************************************************************
32995  SUBROUTINE mp_file_write_at_all_cv(fh, offset, msg, msglen)
32996  COMPLEX(kind=real_4), CONTIGUOUS, INTENT(IN) :: msg(:)
32997  CLASS(mp_file_type), INTENT(IN) :: fh
32998  INTEGER, INTENT(IN), OPTIONAL :: msglen
32999  INTEGER(kind=file_offset), INTENT(IN) :: offset
33000 
33001  INTEGER :: msg_len
33002 #if defined(__parallel)
33003  INTEGER :: ierr
33004 #endif
33005 
33006  msg_len = SIZE(msg)
33007  IF (PRESENT(msglen)) msg_len = msglen
33008 #if defined(__parallel)
33009  CALL mpi_file_write_at_all(fh%handle, offset, msg, msg_len, mpi_complex, mpi_status_ignore, ierr)
33010  IF (ierr .NE. 0) &
33011  cpabort("mpi_file_write_at_all_cv @ mp_file_write_at_all_cv")
33012 #else
33013  WRITE (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
33014 #endif
33015  END SUBROUTINE mp_file_write_at_all_cv
33016 
33017 ! **************************************************************************************************
33018 !> \brief ...
33019 !> \param fh ...
33020 !> \param offset ...
33021 !> \param msg ...
33022 ! **************************************************************************************************
33023  SUBROUTINE mp_file_write_at_all_c (fh, offset, msg)
33024  COMPLEX(kind=real_4), INTENT(IN) :: msg
33025  CLASS(mp_file_type), INTENT(IN) :: fh
33026  INTEGER(kind=file_offset), INTENT(IN) :: offset
33027 
33028 #if defined(__parallel)
33029  INTEGER :: ierr
33030 
33031  ierr = 0
33032  CALL mpi_file_write_at_all(fh%handle, offset, msg, 1, mpi_complex, mpi_status_ignore, ierr)
33033  IF (ierr .NE. 0) &
33034  cpabort("mpi_file_write_at_all_c @ mp_file_write_at_all_c")
33035 #else
33036  WRITE (unit=fh%handle, pos=offset + 1) msg
33037 #endif
33038  END SUBROUTINE mp_file_write_at_all_c
33039 
33040 ! **************************************************************************************************
33041 !> \brief (parallel) Blocking individual file read using explicit offsets
33042 !> (serial) Unformatted stream read
33043 !> \param[in] fh file handle (file storage unit)
33044 !> \param[in] offset file offset (position)
33045 !> \param[out] msg data to be read from the file
33046 !> \param msglen ...
33047 !> \par MPI-I/O mapping mpi_file_read_at
33048 !> \par STREAM-I/O mapping READ
33049 !> \param[in](optional) msglen number of elements of data
33050 ! **************************************************************************************************
33051  SUBROUTINE mp_file_read_at_cv(fh, offset, msg, msglen)
33052  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msg(:)
33053  CLASS(mp_file_type), INTENT(IN) :: fh
33054  INTEGER, INTENT(IN), OPTIONAL :: msglen
33055  INTEGER(kind=file_offset), INTENT(IN) :: offset
33056 
33057  INTEGER :: msg_len
33058 #if defined(__parallel)
33059  INTEGER :: ierr
33060 #endif
33061 
33062  msg_len = SIZE(msg)
33063  IF (PRESENT(msglen)) msg_len = msglen
33064 #if defined(__parallel)
33065  CALL mpi_file_read_at(fh%handle, offset, msg, msg_len, mpi_complex, mpi_status_ignore, ierr)
33066  IF (ierr .NE. 0) &
33067  cpabort("mpi_file_read_at_cv @ mp_file_read_at_cv")
33068 #else
33069  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
33070 #endif
33071  END SUBROUTINE mp_file_read_at_cv
33072 
33073 ! **************************************************************************************************
33074 !> \brief ...
33075 !> \param fh ...
33076 !> \param offset ...
33077 !> \param msg ...
33078 ! **************************************************************************************************
33079  SUBROUTINE mp_file_read_at_c (fh, offset, msg)
33080  COMPLEX(kind=real_4), INTENT(OUT) :: msg
33081  CLASS(mp_file_type), INTENT(IN) :: fh
33082  INTEGER(kind=file_offset), INTENT(IN) :: offset
33083 
33084 #if defined(__parallel)
33085  INTEGER :: ierr
33086 
33087  ierr = 0
33088  CALL mpi_file_read_at(fh%handle, offset, msg, 1, mpi_complex, mpi_status_ignore, ierr)
33089  IF (ierr .NE. 0) &
33090  cpabort("mpi_file_read_at_c @ mp_file_read_at_c")
33091 #else
33092  READ (unit=fh%handle, pos=offset + 1) msg
33093 #endif
33094  END SUBROUTINE mp_file_read_at_c
33095 
33096 ! **************************************************************************************************
33097 !> \brief (parallel) Blocking collective file read using explicit offsets
33098 !> (serial) Unformatted stream read
33099 !> \param fh ...
33100 !> \param offset ...
33101 !> \param msg ...
33102 !> \param msglen ...
33103 !> \par MPI-I/O mapping mpi_file_read_at_all
33104 !> \par STREAM-I/O mapping READ
33105 ! **************************************************************************************************
33106  SUBROUTINE mp_file_read_at_all_cv(fh, offset, msg, msglen)
33107  COMPLEX(kind=real_4), INTENT(OUT), CONTIGUOUS :: msg(:)
33108  CLASS(mp_file_type), INTENT(IN) :: fh
33109  INTEGER, INTENT(IN), OPTIONAL :: msglen
33110  INTEGER(kind=file_offset), INTENT(IN) :: offset
33111 
33112  INTEGER :: msg_len
33113 #if defined(__parallel)
33114  INTEGER :: ierr
33115 #endif
33116 
33117  msg_len = SIZE(msg)
33118  IF (PRESENT(msglen)) msg_len = msglen
33119 #if defined(__parallel)
33120  CALL mpi_file_read_at_all(fh%handle, offset, msg, msg_len, mpi_complex, mpi_status_ignore, ierr)
33121  IF (ierr .NE. 0) &
33122  cpabort("mpi_file_read_at_all_cv @ mp_file_read_at_all_cv")
33123 #else
33124  READ (unit=fh%handle, pos=offset + 1) msg(1:msg_len)
33125 #endif
33126  END SUBROUTINE mp_file_read_at_all_cv
33127 
33128 ! **************************************************************************************************
33129 !> \brief ...
33130 !> \param fh ...
33131 !> \param offset ...
33132 !> \param msg ...
33133 ! **************************************************************************************************
33134  SUBROUTINE mp_file_read_at_all_c (fh, offset, msg)
33135  COMPLEX(kind=real_4), INTENT(OUT) :: msg
33136  CLASS(mp_file_type), INTENT(IN) :: fh
33137  INTEGER(kind=file_offset), INTENT(IN) :: offset
33138 
33139 #if defined(__parallel)
33140  INTEGER :: ierr
33141 
33142  ierr = 0
33143  CALL mpi_file_read_at_all(fh%handle, offset, msg, 1, mpi_complex, mpi_status_ignore, ierr)
33144  IF (ierr .NE. 0) &
33145  cpabort("mpi_file_read_at_all_c @ mp_file_read_at_all_c")
33146 #else
33147  READ (unit=fh%handle, pos=offset + 1) msg
33148 #endif
33149  END SUBROUTINE mp_file_read_at_all_c
33150 
33151 ! **************************************************************************************************
33152 !> \brief ...
33153 !> \param ptr ...
33154 !> \param vector_descriptor ...
33155 !> \param index_descriptor ...
33156 !> \return ...
33157 ! **************************************************************************************************
33158  FUNCTION mp_type_make_c (ptr, &
33159  vector_descriptor, index_descriptor) &
33160  result(type_descriptor)
33161  COMPLEX(kind=real_4), DIMENSION(:), TARGET, asynchronous :: ptr
33162  INTEGER, DIMENSION(2), INTENT(IN), OPTIONAL :: vector_descriptor
33163  TYPE(mp_indexing_meta_type), INTENT(IN), OPTIONAL :: index_descriptor
33164  TYPE(mp_type_descriptor_type) :: type_descriptor
33165 
33166  CHARACTER(len=*), PARAMETER :: routinen = 'mp_type_make_c'
33167 
33168 #if defined(__parallel)
33169  INTEGER :: ierr
33170 #endif
33171 
33172  NULLIFY (type_descriptor%subtype)
33173  type_descriptor%length = SIZE(ptr)
33174 #if defined(__parallel)
33175  type_descriptor%type_handle = mpi_complex
33176  CALL mpi_get_address(ptr, type_descriptor%base, ierr)
33177  IF (ierr /= 0) &
33178  cpabort("MPI_Get_address @ "//routinen)
33179 #else
33180  type_descriptor%type_handle = 5
33181 #endif
33182  type_descriptor%vector_descriptor(1:2) = 1
33183  type_descriptor%has_indexing = .false.
33184  type_descriptor%data_c => ptr
33185  IF (PRESENT(vector_descriptor) .OR. PRESENT(index_descriptor)) THEN
33186  cpabort(routinen//": Vectors and indices NYI")
33187  END IF
33188  END FUNCTION mp_type_make_c
33189 
33190 ! **************************************************************************************************
33191 !> \brief Allocates an array, using MPI_ALLOC_MEM ... this is hackish
33192 !> as the Fortran version returns an integer, which we take to be a C_PTR
33193 !> \param DATA data array to allocate
33194 !> \param[in] len length (in data elements) of data array allocation
33195 !> \param[out] stat (optional) allocation status result
33196 ! **************************************************************************************************
33197  SUBROUTINE mp_alloc_mem_c (DATA, len, stat)
33198  COMPLEX(kind=real_4), CONTIGUOUS, DIMENSION(:), POINTER :: data
33199  INTEGER, INTENT(IN) :: len
33200  INTEGER, INTENT(OUT), OPTIONAL :: stat
33201 
33202 #if defined(__parallel)
33203  INTEGER :: size, ierr, length, &
33204  mp_res
33205  INTEGER(KIND=MPI_ADDRESS_KIND) :: mp_size
33206  TYPE(c_ptr) :: mp_baseptr
33207  mpi_info_type :: mp_info
33208 
33209  length = max(len, 1)
33210  CALL mpi_type_size(mpi_complex, size, ierr)
33211  mp_size = int(length, kind=mpi_address_kind)*size
33212  IF (mp_size .GT. mp_max_memory_size) THEN
33213  cpabort("MPI cannot allocate more than 2 GiByte")
33214  END IF
33215  mp_info = mpi_info_null
33216  CALL mpi_alloc_mem(mp_size, mp_info, mp_baseptr, mp_res)
33217  CALL c_f_pointer(mp_baseptr, DATA, (/length/))
33218  IF (PRESENT(stat)) stat = mp_res
33219 #else
33220  INTEGER :: length, mystat
33221  length = max(len, 1)
33222  IF (PRESENT(stat)) THEN
33223  ALLOCATE (DATA(length), stat=mystat)
33224  stat = mystat ! show to convention checker that stat is used
33225  ELSE
33226  ALLOCATE (DATA(length))
33227  END IF
33228 #endif
33229  END SUBROUTINE mp_alloc_mem_c
33230 
33231 ! **************************************************************************************************
33232 !> \brief Deallocates am array, ... this is hackish
33233 !> as the Fortran version takes an integer, which we hope to get by reference
33234 !> \param DATA data array to allocate
33235 !> \param[out] stat (optional) allocation status result
33236 ! **************************************************************************************************
33237  SUBROUTINE mp_free_mem_c (DATA, stat)
33238  COMPLEX(kind=real_4), DIMENSION(:), &
33239  POINTER, asynchronous :: data
33240  INTEGER, INTENT(OUT), OPTIONAL :: stat
33241 
33242 #if defined(__parallel)
33243  INTEGER :: mp_res
33244  CALL mpi_free_mem(DATA, mp_res)
33245  IF (PRESENT(stat)) stat = mp_res
33246 #else
33247  DEALLOCATE (data)
33248  IF (PRESENT(stat)) stat = 0
33249 #endif
33250  END SUBROUTINE mp_free_mem_c
33251 
33252  END MODULE message_passing
static int isum(const int n, const int input[n])
Private routine for computing the sum of the given integers.
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Definition: grid_common.h:117
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public int_8
Definition: kinds.F:54
integer, parameter, public dp
Definition: kinds.F:34
integer, parameter, public int_4_size
Definition: kinds.F:52
integer, parameter, public default_string_length
Definition: kinds.F:57
integer, parameter, public real_8_size
Definition: kinds.F:43
integer, parameter, public int_8_size
Definition: kinds.F:55
integer, parameter, public real_4_size
Definition: kinds.F:42
integer, parameter, public real_4
Definition: kinds.F:40
integer, parameter, public real_8
Definition: kinds.F:41
integer, parameter, public int_4
Definition: kinds.F:51
Machine interface based on Fortran 2003 and POSIX.
Definition: machine.F:17
subroutine, public m_abort()
Can be used to get a nice core.
Definition: machine.F:284
Interface to the message passing library MPI.
type(mp_comm_type), parameter, public mp_comm_null
integer, parameter, public mp_comm_unequal
logical, save, public mp_collect_timings
subroutine, public mp_dims_create(nodes, dims)
wrapper to MPI_Dims_create
subroutine, public mp_para_env_create(para_env, group)
creates a new para environment
type(mp_file_descriptor_type) function, public mp_file_type_hindexed_make_chv(count, lengths, displs)
Creates an indexed MPI type for arrays of strings using bytes for spacing (hindexed type)
subroutine, public mp_world_init(mp_comm)
initializes the system default communicator
integer, parameter, public file_amode_rdwr
subroutine, public mp_para_cart_create(cart, group)
creates a cart (multidimensional parallel environment)
subroutine, public mp_file_type_free(type_descriptor)
Releases the type used for MPI I/O.
integer, parameter, public mp_any_tag
integer, parameter, public file_amode_wronly
integer, parameter, public mpi_character_size
integer, parameter, public mp_comm_ident
type(mp_type_descriptor_type) function, public mp_type_indexed_make_z(count, lengths, displs)
...
subroutine, public mp_abort()
globally stops all tasks this is intended to be low level, most of CP2K should call cp_abort()
type(mp_type_descriptor_type) function, public mp_type_indexed_make_r(count, lengths, displs)
...
type(mp_comm_type), parameter, public mp_comm_world
integer, parameter, public file_amode_create
subroutine, public mp_para_env_release(para_env)
releases the para object (to be called when you don't want anymore the shared copy of this object)
type(mp_comm_type), parameter, public mp_comm_self
integer, parameter, public mp_comm_congruent
subroutine, public mp_para_cart_release(cart)
releases the given cart
type(mp_type_descriptor_type) function, public mp_type_indexed_make_d(count, lengths, displs)
...
integer, parameter, public mp_comm_compare_default
integer function, public mp_get_node_global_rank()
Get the local rank on the node according to the global communicator.
subroutine, public mp_world_finalize()
finalizes the system default communicator
subroutine, public mp_file_delete(filepath, info)
Deletes a file. Auxiliary routine to emulate 'replace' action for mp_file_open. Only the master proce...
integer, parameter, public mp_comm_similar
type(mp_file_type), parameter, public mp_file_null
integer, parameter, public mp_any_source
type(mp_type_descriptor_type) function, public mp_type_indexed_make_c(count, lengths, displs)
...
type(mp_info_type), parameter, public mp_info_null
type(mp_win_type), parameter, public mp_win_null
integer, parameter, public file_amode_append
subroutine, public mp_get_library_version(version, resultlen)
Get Version of the MPI Library (MPI 3)
integer, parameter, public address_kind
subroutine, public mp_file_get_amode(mpi_io, replace, amode, form, action, status, position)
(parallel) Utility routine to determine MPI file access mode based on variables
integer, parameter, public file_amode_rdonly
subroutine, public mp_waitany(requests, completed)
waits for completion of any of the given requests
integer, parameter, public file_amode_excl
type(mp_request_type), parameter, public mp_request_null
subroutine, public mp_file_type_set_view_chv(fh, offset, type_descriptor)
Uses a previously created indexed MPI character type to tell the MPI processes how to partition (set_...
subroutine, public mp_type_size(type_descriptor, type_size)
Returns the size of a data type in bytes.
integer, parameter, public mpi_integer_size
Defines all routines to deal with the performance of MPI routines.
Definition: mp_perf_env.F:11
subroutine, public rm_mp_perf_env()
...
Definition: mp_perf_env.F:192
subroutine, public add_perf(perf_id, count, msg_size)
adds the performance informations of one call
Definition: mp_perf_env.F:233
subroutine, public add_mp_perf_env(perf_env)
start and stop the performance indicators for every call to start there has to be (exactly) one call ...
Definition: mp_perf_env.F:76