Neko 1.99.7
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, &
46
49 integer, public, parameter :: gs_vec_nc = 3
50
52 type, public, abstract :: gs_comm_t
54 type(stack_i4_t), allocatable :: send_dof(:)
57 type(stack_i4_t), allocatable :: recv_dof(:)
61 integer, allocatable :: send_pe(:)
63 integer, allocatable :: recv_pe(:)
67 logical :: vec_supported = .false.
68 contains
69 procedure(gs_comm_init), pass(this), deferred :: init
70 procedure(gs_comm_free), pass(this), deferred :: free
71 procedure(gs_nbsend), pass(this), deferred :: nbsend
72 procedure(gs_nbrecv), pass(this), deferred :: nbrecv
73 procedure(gs_nbwait), pass(this), deferred :: nbwait
74 procedure, pass(this) :: init_dofs
75 procedure, pass(this) :: free_dofs
76 procedure, pass(this) :: init_order
77 procedure, pass(this) :: free_order
78 procedure, pass(this) :: take_schedule
79 procedure, pass(this) :: init_schedule
82 procedure, pass(this) :: nbsend_vec => gs_nbsend_vec
83 procedure, pass(this) :: nbrecv_vec => gs_nbrecv_vec
84 procedure, pass(this) :: nbwait_vec => gs_nbwait_vec
85 end type gs_comm_t
86
90 abstract interface
91 subroutine gs_comm_init(this, send_pe, recv_pe)
92 import gs_comm_t
93 import stack_i4_t
94 class(gs_comm_t), intent(inout) :: this
95 type(stack_i4_t), intent(inout) :: send_pe
96 type(stack_i4_t), intent(inout) :: recv_pe
97 end subroutine gs_comm_init
98 end interface
99
101 abstract interface
102 subroutine gs_comm_free(this)
103 import gs_comm_t
104 class(gs_comm_t), intent(inout) :: this
105 end subroutine gs_comm_free
106 end interface
107
114 abstract interface
115 subroutine gs_nbsend(this, u, n, tag, deps, strm)
116 import gs_comm_t
117 import stack_i4_t
118 import c_ptr
119 import rp
120 class(gs_comm_t), intent(inout) :: this
121 integer, intent(in) :: n
122 real(kind=rp), dimension(n), intent(inout) :: u
123 integer, intent(in) :: tag
124 type(c_ptr), intent(inout) :: deps
125 type(c_ptr), intent(inout) :: strm
126 end subroutine gs_nbsend
127 end interface
128
129
132 abstract interface
133 subroutine gs_nbrecv(this, tag)
134 import gs_comm_t
135 class(gs_comm_t), intent(inout) :: this
136 integer, intent(in) :: tag
137 end subroutine gs_nbrecv
138 end interface
139
148 abstract interface
149 subroutine gs_nbwait(this, u, n, op, strm)
150 import gs_comm_t
151 import stack_i4_t
152 import c_ptr
153 import rp
154 class(gs_comm_t), intent(inout) :: this
155 integer, intent(in) :: n
156 real(kind=rp), dimension(n), intent(inout) :: u
157 integer :: op
158 type(c_ptr), intent(inout) :: strm
159 end subroutine gs_nbwait
160 end interface
161
163contains
164 !Initalize stacks for each rank of dof indices to send/recv
165 subroutine init_dofs(this)
166 class(gs_comm_t), intent(inout) :: this
167 integer :: i
168
169 call this%free_dofs()
170
171 allocate(this%send_dof(0:pe_size-1))
172 allocate(this%recv_dof(0:pe_size-1))
173
174 do i = 0, pe_size -1
175 call this%send_dof(i)%init()
176 call this%recv_dof(i)%init()
177 end do
178
179 end subroutine init_dofs
180
181 subroutine free_dofs(this)
182 class(gs_comm_t), intent(inout) :: this
183 integer :: i
184
185 if (allocated(this%send_dof)) then
186 do i = 0, pe_size - 1
187 call this%send_dof(i)%free()
188 end do
189 deallocate(this%send_dof)
190 end if
191
192 if (allocated(this%recv_dof)) then
193 do i = 0, pe_size - 1
194 call this%recv_dof(i)%free()
195 end do
196 deallocate(this%recv_dof)
197 end if
198
199 end subroutine free_dofs
200
204 subroutine init_order(this, send_pe, recv_pe)
205 class(gs_comm_t), intent(inout) :: this
206 type(stack_i4_t), intent(inout) :: send_pe
207 type(stack_i4_t), intent(inout) :: recv_pe
208 integer, pointer :: sp(:)
209 integer :: i
210
211 allocate(this%send_pe(send_pe%size()))
212
213 sp => send_pe%array()
214 do i = 1, send_pe%size()
215 this%send_pe(i) = sp(i)
216 end do
217
218 allocate(this%recv_pe(recv_pe%size()))
219
220 sp => recv_pe%array()
221 do i = 1, recv_pe%size()
222 this%recv_pe(i) = sp(i)
223 end do
224
225 end subroutine init_order
226
227 subroutine free_order(this)
228 class(gs_comm_t), intent(inout) :: this
229
230 if (allocated(this%send_pe)) then
231 deallocate(this%send_pe)
232 end if
233
234 if (allocated(this%recv_pe)) then
235 deallocate(this%recv_pe)
236 end if
237
238 end subroutine free_order
239
248 subroutine take_schedule(this, src)
249 class(gs_comm_t), intent(inout) :: this
250 class(gs_comm_t), intent(inout) :: src
251
252 if (.not. allocated(src%send_dof) .or. .not. allocated(src%recv_dof) .or. &
253 .not. allocated(src%send_pe) .or. .not. allocated(src%recv_pe)) then
254 call neko_error('Gather-scatter comm. method has no schedule')
255 end if
256
257 call this%free_dofs()
258 call this%free_order()
259
260 call move_alloc(src%send_dof, this%send_dof)
261 call move_alloc(src%recv_dof, this%recv_dof)
262 call move_alloc(src%send_pe, this%send_pe)
263 call move_alloc(src%recv_pe, this%recv_pe)
264
265 end subroutine take_schedule
266
269 subroutine init_schedule(this)
270 class(gs_comm_t), intent(inout) :: this
271 type(stack_i4_t) :: send_pe, recv_pe
272 integer, allocatable :: sp(:), rp(:)
273 integer :: i, pe
274
275 if (.not. allocated(this%send_pe) .or. .not. allocated(this%recv_pe)) then
276 call neko_error('Gather-scatter comm. method has no schedule')
277 end if
278
279 ! init_order allocates send_pe/recv_pe from the stacks, so hand the
280 ! peer lists back as stacks and leave the arrays deallocated
281 call move_alloc(this%send_pe, sp)
282 call move_alloc(this%recv_pe, rp)
283
284 call send_pe%init(max(size(sp), 1))
285 do i = 1, size(sp)
286 pe = sp(i)
287 call send_pe%push(pe)
288 end do
289
290 call recv_pe%init(max(size(rp), 1))
291 do i = 1, size(rp)
292 pe = rp(i)
293 call recv_pe%push(pe)
294 end do
295
296 deallocate(sp, rp)
297
298 call this%init(send_pe, recv_pe)
299
300 call send_pe%free()
301 call recv_pe%free()
302
303 end subroutine init_schedule
304
309 subroutine gs_nbsend_vec(this, u, n, nc, tag, deps, strm)
310 class(gs_comm_t), intent(inout) :: this
311 integer, intent(in) :: n, nc
312 real(kind=rp), dimension(nc*n), intent(inout) :: u
313 integer, intent(in) :: tag
314 type(c_ptr), intent(inout) :: deps
315 type(c_ptr), intent(inout) :: strm
316 call neko_error('Vector gather-scatter not supported by this comm backend')
317 end subroutine gs_nbsend_vec
318
320 subroutine gs_nbrecv_vec(this, tag, nc)
321 class(gs_comm_t), intent(inout) :: this
322 integer, intent(in) :: tag, nc
323 call neko_error('Vector gather-scatter not supported by this comm backend')
324 end subroutine gs_nbrecv_vec
325
327 subroutine gs_nbwait_vec(this, u, n, nc, op, strm)
328 class(gs_comm_t), intent(inout) :: this
329 integer, intent(in) :: n, nc
330 real(kind=rp), dimension(nc*n), intent(inout) :: u
331 integer :: op
332 type(c_ptr), intent(inout) :: strm
333 call neko_error('Vector gather-scatter not supported by this comm backend')
334 end subroutine gs_nbwait_vec
335
336end module gs_comm
Abstract interface for deallocating a Gather-scatter communication method.
Definition gs_comm.f90:102
Abstract interface for initializing a Gather-scatter communication method.
Definition gs_comm.f90:91
Abstract interface for initiating non-blocking recieve operations Posts non-blocking recieve of value...
Definition gs_comm.f90:133
Abstract interface for initiating non-blocking send operations Sends the values in u(send_dof(send_pe...
Definition gs_comm.f90:115
Abstract interface for waiting on non-blocking operations Waits and checks that data is in buffers an...
Definition gs_comm.f90:149
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
subroutine init_schedule(this)
Set up this communication method for the schedule taken over by take_schedule. Collective,...
Definition gs_comm.f90:270
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:310
subroutine init_dofs(this)
Definition gs_comm.f90:166
subroutine gs_nbrecv_vec(this, tag, nc)
Default fused vector receive. Abort unless a backend overrides it.
Definition gs_comm.f90:321
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:49
integer, parameter, public gs_comm_mpigpu
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:249
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:205
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:328
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:182
integer, parameter, public gs_comm_nccl
Definition gs_comm.f90:43
subroutine free_order(this)
Definition gs_comm.f90:228
integer, parameter, public gs_comm_caf
Definition gs_comm.f90:43
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements a dynamic stack ADT.
Definition stack.f90:49
Utilities.
Definition utils.f90:35
Gather-scatter communication method.
Definition gs_comm.f90:52
Integer based stack.
Definition stack.f90:77
#define max(a, b)
Definition tensor.cu:40