Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
gs_comm.f90
Go to the documentation of this file.
1! Copyright (c) 2022-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
34module gs_comm
35 use num_types, only : rp
36 use comm, only : pe_size
37 use stack, only : stack_i4_t
38 use utils, only : neko_error
39 use, intrinsic :: iso_c_binding
40 implicit none
41 private
42
43 integer, public, parameter :: gs_comm_mpi = 1, gs_comm_mpigpu = 2, &
47
50 integer, public, parameter :: gs_vec_nc = 3
51
53 type, public, abstract :: gs_comm_t
55 type(stack_i4_t), allocatable :: send_dof(:)
58 type(stack_i4_t), allocatable :: recv_dof(:)
62 integer, allocatable :: send_pe(:)
64 integer, allocatable :: recv_pe(:)
68 logical :: vec_supported = .false.
69 contains
70 procedure(gs_comm_init), pass(this), deferred :: init
71 procedure(gs_comm_free), pass(this), deferred :: free
72 procedure(gs_nbsend), pass(this), deferred :: nbsend
73 procedure(gs_nbrecv), pass(this), deferred :: nbrecv
74 procedure(gs_nbwait), pass(this), deferred :: nbwait
75 procedure, pass(this) :: init_dofs
76 procedure, pass(this) :: free_dofs
77 procedure, pass(this) :: init_order
78 procedure, pass(this) :: free_order
79 procedure, pass(this) :: take_schedule
80 procedure, pass(this) :: init_schedule
83 procedure, pass(this) :: nbsend_vec => gs_nbsend_vec
84 procedure, pass(this) :: nbrecv_vec => gs_nbrecv_vec
85 procedure, pass(this) :: nbwait_vec => gs_nbwait_vec
86 end type gs_comm_t
87
91 abstract interface
92 subroutine gs_comm_init(this, send_pe, recv_pe)
93 import gs_comm_t
94 import stack_i4_t
95 class(gs_comm_t), intent(inout) :: this
96 type(stack_i4_t), intent(inout) :: send_pe
97 type(stack_i4_t), intent(inout) :: recv_pe
98 end subroutine gs_comm_init
99 end interface
100
102 abstract interface
103 subroutine gs_comm_free(this)
104 import gs_comm_t
105 class(gs_comm_t), intent(inout) :: this
106 end subroutine gs_comm_free
107 end interface
108
115 abstract interface
116 subroutine gs_nbsend(this, u, n, tag, deps, strm)
117 import gs_comm_t
118 import stack_i4_t
119 import c_ptr
120 import rp
121 class(gs_comm_t), intent(inout) :: this
122 integer, intent(in) :: n
123 real(kind=rp), dimension(n), intent(inout) :: u
124 integer, intent(in) :: tag
125 type(c_ptr), intent(inout) :: deps
126 type(c_ptr), intent(inout) :: strm
127 end subroutine gs_nbsend
128 end interface
129
130
133 abstract interface
134 subroutine gs_nbrecv(this, tag)
135 import gs_comm_t
136 class(gs_comm_t), intent(inout) :: this
137 integer, intent(in) :: tag
138 end subroutine gs_nbrecv
139 end interface
140
149 abstract interface
150 subroutine gs_nbwait(this, u, n, op, strm)
151 import gs_comm_t
152 import stack_i4_t
153 import c_ptr
154 import rp
155 class(gs_comm_t), intent(inout) :: this
156 integer, intent(in) :: n
157 real(kind=rp), dimension(n), intent(inout) :: u
158 integer :: op
159 type(c_ptr), intent(inout) :: strm
160 end subroutine gs_nbwait
161 end interface
162
164contains
165 !Initalize stacks for each rank of dof indices to send/recv
166 subroutine init_dofs(this)
167 class(gs_comm_t), intent(inout) :: this
168 integer :: i
169
170 call this%free_dofs()
171
172 allocate(this%send_dof(0:pe_size-1))
173 allocate(this%recv_dof(0:pe_size-1))
174
175 do i = 0, pe_size -1
176 call this%send_dof(i)%init()
177 call this%recv_dof(i)%init()
178 end do
179
180 end subroutine init_dofs
181
182 subroutine free_dofs(this)
183 class(gs_comm_t), intent(inout) :: this
184 integer :: i
185
186 if (allocated(this%send_dof)) then
187 do i = 0, pe_size - 1
188 call this%send_dof(i)%free()
189 end do
190 deallocate(this%send_dof)
191 end if
192
193 if (allocated(this%recv_dof)) then
194 do i = 0, pe_size - 1
195 call this%recv_dof(i)%free()
196 end do
197 deallocate(this%recv_dof)
198 end if
199
200 end subroutine free_dofs
201
205 subroutine init_order(this, send_pe, recv_pe)
206 class(gs_comm_t), intent(inout) :: this
207 type(stack_i4_t), intent(inout) :: send_pe
208 type(stack_i4_t), intent(inout) :: recv_pe
209 integer, pointer :: sp(:)
210 integer :: i
211
212 allocate(this%send_pe(send_pe%size()))
213
214 sp => send_pe%array()
215 do i = 1, send_pe%size()
216 this%send_pe(i) = sp(i)
217 end do
218
219 allocate(this%recv_pe(recv_pe%size()))
220
221 sp => recv_pe%array()
222 do i = 1, recv_pe%size()
223 this%recv_pe(i) = sp(i)
224 end do
225
226 end subroutine init_order
227
228 subroutine free_order(this)
229 class(gs_comm_t), intent(inout) :: this
230
231 if (allocated(this%send_pe)) then
232 deallocate(this%send_pe)
233 end if
234
235 if (allocated(this%recv_pe)) then
236 deallocate(this%recv_pe)
237 end if
238
239 end subroutine free_order
240
249 subroutine take_schedule(this, src)
250 class(gs_comm_t), intent(inout) :: this
251 class(gs_comm_t), intent(inout) :: src
252
253 if (.not. allocated(src%send_dof) .or. .not. allocated(src%recv_dof) .or. &
254 .not. allocated(src%send_pe) .or. .not. allocated(src%recv_pe)) then
255 call neko_error('Gather-scatter comm. method has no schedule')
256 end if
257
258 call this%free_dofs()
259 call this%free_order()
260
261 call move_alloc(src%send_dof, this%send_dof)
262 call move_alloc(src%recv_dof, this%recv_dof)
263 call move_alloc(src%send_pe, this%send_pe)
264 call move_alloc(src%recv_pe, this%recv_pe)
265
266 end subroutine take_schedule
267
270 subroutine init_schedule(this)
271 class(gs_comm_t), intent(inout) :: this
272 type(stack_i4_t) :: send_pe, recv_pe
273 integer, allocatable :: sp(:), rp(:)
274 integer :: i, pe
275
276 if (.not. allocated(this%send_pe) .or. .not. allocated(this%recv_pe)) then
277 call neko_error('Gather-scatter comm. method has no schedule')
278 end if
279
280 ! init_order allocates send_pe/recv_pe from the stacks, so hand the
281 ! peer lists back as stacks and leave the arrays deallocated
282 call move_alloc(this%send_pe, sp)
283 call move_alloc(this%recv_pe, rp)
284
285 call send_pe%init(max(size(sp), 1))
286 do i = 1, size(sp)
287 pe = sp(i)
288 call send_pe%push(pe)
289 end do
290
291 call recv_pe%init(max(size(rp), 1))
292 do i = 1, size(rp)
293 pe = rp(i)
294 call recv_pe%push(pe)
295 end do
296
297 deallocate(sp, rp)
298
299 call this%init(send_pe, recv_pe)
300
301 call send_pe%free()
302 call recv_pe%free()
303
304 end subroutine init_schedule
305
310 subroutine gs_nbsend_vec(this, u, n, nc, tag, deps, strm)
311 class(gs_comm_t), intent(inout) :: this
312 integer, intent(in) :: n, nc
313 real(kind=rp), dimension(nc*n), intent(inout) :: u
314 integer, intent(in) :: tag
315 type(c_ptr), intent(inout) :: deps
316 type(c_ptr), intent(inout) :: strm
317 call neko_error('Vector gather-scatter not supported by this comm backend')
318 end subroutine gs_nbsend_vec
319
321 subroutine gs_nbrecv_vec(this, tag, nc)
322 class(gs_comm_t), intent(inout) :: this
323 integer, intent(in) :: tag, nc
324 call neko_error('Vector gather-scatter not supported by this comm backend')
325 end subroutine gs_nbrecv_vec
326
328 subroutine gs_nbwait_vec(this, u, n, nc, op, strm)
329 class(gs_comm_t), intent(inout) :: this
330 integer, intent(in) :: n, nc
331 real(kind=rp), dimension(nc*n), intent(inout) :: u
332 integer :: op
333 type(c_ptr), intent(inout) :: strm
334 call neko_error('Vector gather-scatter not supported by this comm backend')
335 end subroutine gs_nbwait_vec
336
337end module gs_comm
Abstract interface for deallocating a Gather-scatter communication method.
Definition gs_comm.f90:103
Abstract interface for initializing a Gather-scatter communication method.
Definition gs_comm.f90:92
Abstract interface for initiating non-blocking recieve operations Posts non-blocking recieve of value...
Definition gs_comm.f90:134
Abstract interface for initiating non-blocking send operations Sends the values in u(send_dof(send_pe...
Definition gs_comm.f90:116
Abstract interface for waiting on non-blocking operations Waits and checks that data is in buffers an...
Definition gs_comm.f90:150
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
Defines a gather-scatter communication method.
Definition gs_comm.f90:34
integer, parameter, public gs_comm_mpirma
Definition gs_comm.f90:43
subroutine init_schedule(this)
Set up this communication method for the schedule taken over by take_schedule. Collective,...
Definition gs_comm.f90:271
subroutine gs_nbsend_vec(this, u, n, nc, tag, deps, strm)
Default fused vector send. Abort unless a backend overrides it.
Definition gs_comm.f90:311
subroutine init_dofs(this)
Definition gs_comm.f90:167
subroutine gs_nbrecv_vec(this, tag, nc)
Default fused vector receive. Abort unless a backend overrides it.
Definition gs_comm.f90:322
integer, parameter, public gs_vec_nc
Maximum number of components handled by the fused vector (multi-component) halo exchange used by gs_o...
Definition gs_comm.f90:50
integer, parameter, public gs_comm_crystal
Definition gs_comm.f90:43
integer, parameter, public gs_comm_mpigpu
Definition gs_comm.f90:43
integer, parameter, public gs_comm_crystalgpu
Definition gs_comm.f90:43
subroutine take_schedule(this, src)
Take over the gather-scatter schedule (dof lists and peer order) of src, avoiding a second (expensive...
Definition gs_comm.f90:250
integer, parameter, public gs_comm_neighbour
Definition gs_comm.f90:43
integer, parameter, public gs_comm_mpi
Definition gs_comm.f90:43
subroutine init_order(this, send_pe, recv_pe)
Obtains which ranks to send and receive data from.
Definition gs_comm.f90:206
subroutine gs_nbwait_vec(this, u, n, nc, op, strm)
Default fused vector wait/reduce. Abort unless a backend overrides it.
Definition gs_comm.f90:329
integer, parameter, public gs_comm_nvshmem
Definition gs_comm.f90:43
integer, parameter, public gs_comm_openshmem
Definition gs_comm.f90:43
integer, parameter, public gs_comm_utofu
Definition gs_comm.f90:43
subroutine free_dofs(this)
Definition gs_comm.f90:183
integer, parameter, public gs_comm_nccl
Definition gs_comm.f90:43
subroutine free_order(this)
Definition gs_comm.f90:229
integer, parameter, public gs_comm_caf
Definition gs_comm.f90:43
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Implements a dynamic stack ADT.
Definition stack.f90:49
Utilities.
Definition utils.f90:35
Gather-scatter communication method.
Definition gs_comm.f90:53
Integer based stack.
Definition stack.f90:77
#define max(a, b)
Definition tensor.cu:40