ComIn 0.5.1
ICON Community Interface
Loading...
Searching...
No Matches
comin_parallel.F90
Go to the documentation of this file.
1!> @file comin_parallel.F90
2!! @brief Definitions for parallel communication.
3!
4! @authors 09/2022 :: ICON Community Interface <comin@icon-model.org>
5!
6! SPDX-License-Identifier: BSD-3-Clause
7!
8! See LICENSES for license information.
9! Where software is supplied by third parties, it is indicated in the
10! headers of the routines.
11!
13
14 USE mpi
15 USE comin_state, ONLY: state
17 USE iso_c_binding, ONLY: c_int
20
21 IMPLICIT NONE
22
23 PRIVATE
24
31
32#include "comin_global.inc"
33
34 ! max. character string length (e.g. MPI group name)
35 INTEGER, PARAMETER :: MAX_GRPNAMELEN = 256
36
37 INTEGER, PARAMETER :: MAX_GROUPS = 64
38
39 ! level for debug output verbosity (0: quiet)
40 INTEGER, PARAMETER :: debug_level = 0
41
42CONTAINS
43
44 !> Procedure for the communicator splitting ("MPI handshake") that
45 !> has been harmonized with the respective algorithm of the YAC
46 !> coupler software
47 !!
48 SUBROUTINE comin_parallel_mpi_handshake(comm, group_names, component_name)
50
51 INTEGER, INTENT(IN) :: comm
52 CHARACTER(LEN=MAX_GRPNAMELEN), INTENT(IN) :: group_names(:)
53 CHARACTER(LEN=*), INTENT(IN) :: component_name
54 !
55 INTEGER :: num_plugin_comms
56 CHARACTER(LEN=MAX_GRPNAMELEN), ALLOCATABLE :: all_group_names(:)
57 INTEGER, ALLOCATABLE :: all_comms(:)
58
59 num_plugin_comms = count(group_names /= "")
60 ALLOCATE(all_group_names(num_plugin_comms+1))
61 IF(num_plugin_comms > 0) &
62 all_group_names(1:num_plugin_comms) = pack(group_names, group_names /= "")
63 all_group_names(num_plugin_comms+1) = "comin_host_"//component_name
64
65 ALLOCATE(all_comms(num_plugin_comms+1))
66 CALL mpi_handshake(comm, all_group_names, all_comms)
67
68 ALLOCATE(state%parallel_info%component_name_bilateral(num_plugin_comms))
69 state%parallel_info%component_name_bilateral = all_group_names(1:num_plugin_comms)
70 state%parallel_info%mpi_comm_bilateral = all_comms(1:num_plugin_comms)
71 state%parallel_info%host_comm = all_comms(num_plugin_comms+1)
72
73 DEALLOCATE(all_group_names)
74 DEALLOCATE(all_comms)
75 END SUBROUTINE comin_parallel_mpi_handshake
76
78 INTEGER :: i, ierr, nmpi_comm
79
80 IF (.NOT. ALLOCATED(state%parallel_info%mpi_comm_bilateral)) RETURN
81 nmpi_comm = SIZE(state%parallel_info%mpi_comm_bilateral)
82 DO i=1,nmpi_comm
83 CALL mpi_comm_free(state%parallel_info%mpi_comm_bilateral(i), ierr)
85 state%parallel_info%mpi_comm_bilateral(i) = mpi_comm_null
86 END DO
87 DEALLOCATE(state%parallel_info%mpi_comm_bilateral)
88 DEALLOCATE(state%parallel_info%component_name_bilateral)
90
91 !> Returns the communicator with all ICON processes.
92 !! @ingroup fortran_interface
93 INTEGER FUNCTION comin_parallel_get_host_mpi_comm() RESULT(mpi_comm)
94 mpi_comm = state%parallel_info%host_comm
96
97 ! Wrapper function that converts the communicator to C_INT
98 INTEGER(KIND=C_INT) FUNCTION comin_parallel_get_host_mpi_comm_c() &
99 result(mpi_comm) BIND(C, name="comin_parallel_get_host_mpi_comm")
101 END FUNCTION comin_parallel_get_host_mpi_comm_c
102
103 !> Called within a plugin's callback function: get MPI communicator
104 !> which contains all MPI tasks of the host model together with the
105 !> plugin's external MPI partners (if any).
106 !! @ingroup fortran_interface
107 !!
108 INTEGER FUNCTION comin_parallel_get_plugin_mpi_comm() RESULT(mpi_comm)
109 mpi_comm = comin_parallel_find_mpi_comm(state%parallel_info, comin_current_get_plugin_comm())
110 IF(mpi_comm == mpi_comm_null) THEN
111 CALL comin_plugin_finish("comin_parallel_get_plugin_mpi_comm", &
112 & "Error: To use the plugin_comm, 'comm' must be set in the plugin namelist")
113 END IF
115
116 ! Wrapper function that converts the communicator to C_INT
117 INTEGER(KIND=C_INT) FUNCTION comin_parallel_get_plugin_mpi_comm_c() &
118 result(mpi_comm) BIND(C, name="comin_parallel_get_plugin_mpi_comm")
120 END FUNCTION comin_parallel_get_plugin_mpi_comm_c
121
122 !> Called within a plugin's callback function: get MPI rank with
123 !> respect to the "host" MPI communicator.
124 !! @ingroup fortran_interface
125 !!
126 INTEGER(KIND=C_INT) FUNCTION comin_parallel_get_host_mpi_rank() RESULT(mpi_rank) BIND(C)
127 INTEGER :: mpi_comm, ierr, rank_f
129 CALL mpi_comm_rank(mpi_comm, rank_f, ierr)
131 mpi_rank = rank_f
133
134 !> Auxiliary routine for finding an MPI intra-communicator, formed
135 ! by a PE of each group plus a "root group".
136 !
137 INTEGER FUNCTION comin_parallel_find_mpi_comm(parallel_info, component_name)
138 TYPE(t_comin_parallel_info), INTENT(IN) :: parallel_info
139 CHARACTER(LEN=*), INTENT(IN) :: component_name
140 !
141 INTEGER :: i, nmpi_comm
142
143 comin_parallel_find_mpi_comm = mpi_comm_null
144 IF (.NOT. ALLOCATED(parallel_info%mpi_comm_bilateral)) RETURN
145 nmpi_comm = SIZE(parallel_info%mpi_comm_bilateral)
146 loop : DO i=1,nmpi_comm
147 IF (trim(parallel_info%component_name_bilateral(i)) == component_name) THEN
148 comin_parallel_find_mpi_comm = parallel_info%mpi_comm_bilateral(i)
149 EXIT loop
150 END IF
151 END DO loop
152 END FUNCTION comin_parallel_find_mpi_comm
153
154 !> Utility function.
156 INTEGER, INTENT(IN) :: errcode
157 INTEGER :: ierr
158 IF (errcode .NE. mpi_success) THEN
159 WRITE (0,*) "Error in MPI program. Terminating."
160 CALL mpi_abort(mpi_comm_world, errcode, ierr)
161 END IF
163
164END MODULE comin_parallel
const char * comin_current_get_plugin_comm()
integer function, public comin_parallel_get_host_mpi_comm()
Returns the communicator with all ICON processes.
subroutine, public comin_plugin_finish(routine, text)
Wrapper function for callback to ICON's "finish" routine.
integer(kind=c_int) function, public comin_parallel_get_host_mpi_rank()
Called within a plugin's callback function: get MPI rank with respect to the "host" MPI communicator.
integer function, public comin_parallel_get_plugin_mpi_comm()
Called within a plugin's callback function: get MPI communicator which contains all MPI tasks of the ...
subroutine, public comin_parallel_handle_mpi_errcode(errcode)
Utility function.
subroutine, public comin_parallel_mpi_handshake(comm, group_names, component_name)
Procedure for the communicator splitting ("MPI handshake") that has been harmonized with the respecti...
subroutine, public comin_parallel_free_mpi_comms()
type(t_comin_state), pointer, public state
subroutine, public mpi_handshake(comm, group_names, group_comms)
Procedure for the communicator splitting ("MPI handshake") that has been harmonized with the respecti...