Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
ale_routines_device.F90
Go to the documentation of this file.
1! Copyright (c) 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!
33
35 use num_types, only : rp, c_rp
36 use field, only : field_t
37 use coefs, only : coef_t
39 use time_state, only : time_state_t
41 use mesh, only : mesh_t
42 use utils, only : neko_error
43 use device_math, only : device_add2s2
45 use math, only : rzero, glimax, cfill
46 use gather_scatter, only : gs_op_min
50 use comm, only : neko_comm
51 use mpi_f08, only : mpi_wtime, mpi_barrier
52 use logger, only : neko_log, log_size
53 use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_null_ptr
54
55 implicit none
56 private
57
61
62 type, bind(c) :: kinematics_params_t
63 real(c_rp) :: cx, cy, cz
64 real(c_rp) :: vtx, vty, vtz
65 real(c_rp) :: vax, vay, vaz
66 real(c_rp) :: px, py, pz
67 real(c_rp) :: r11, r12, r13
68 real(c_rp) :: r21, r22, r23
69 real(c_rp) :: r31, r32, r33
70 end type kinematics_params_t
71
72#ifdef HAVE_HIP
73 interface
74 subroutine add_kinematics_to_mesh_velocity_hip(wx, wy, wz, &
75 x_ref, y_ref, z_ref, phi, x, y, z, &
76 kin_params, n) &
77 bind(c, name = "add_kinematics_to_mesh_velocity_hip")
78 use, intrinsic :: iso_c_binding
79 import :: kinematics_params_t
80 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
81 type(kinematics_params_t), value :: kin_params
82 integer(c_int), value :: n
84
85 subroutine compute_cheap_dist_hip(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
86 local_iters, nchange_d) &
87 bind(c, name = "compute_cheap_dist_hip")
88 use, intrinsic :: iso_c_binding
89 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
90 integer(c_int), value :: lx, ly, lz, nel, local_iters
91 end subroutine compute_cheap_dist_hip
92 end interface
93#elif HAVE_CUDA
94 interface
95 subroutine add_kinematics_to_mesh_velocity_cuda(wx, wy, wz, &
96 x_ref, y_ref, z_ref, phi, x, y, z, &
97 kin_params, n) &
98 bind(c, name = "add_kinematics_to_mesh_velocity_cuda")
99 use, intrinsic :: iso_c_binding
100 import :: kinematics_params_t
101 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
102 type(kinematics_params_t), value :: kin_params
103 integer(c_int), value :: n
105
106 subroutine compute_cheap_dist_cuda(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
107 local_iters, nchange_d) &
108 bind(c, name = "compute_cheap_dist_cuda")
109 use, intrinsic :: iso_c_binding
110 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
111 integer(c_int), value :: lx, ly, lz, nel, local_iters
112 end subroutine compute_cheap_dist_cuda
113 end interface
114
115#elif HAVE_OPENCL
116 interface
117 subroutine add_kinematics_to_mesh_velocity_opencl(wx, wy, wz, &
118 x_ref, y_ref, z_ref, phi, x, y, z, &
119 kin_params, n) &
120 bind(c, name = "add_kinematics_to_mesh_velocity_opencl")
121 use, intrinsic :: iso_c_binding
122 import :: kinematics_params_t
123 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
124 type(kinematics_params_t), value :: kin_params
125 integer(c_int), value :: n
127
128 subroutine compute_cheap_dist_opencl(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
129 local_iters, nchange_d) &
130 bind(c, name = "compute_cheap_dist_opencl")
131 use, intrinsic :: iso_c_binding
132 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
133 integer(c_int), value :: lx, ly, lz, nel, local_iters
134 end subroutine compute_cheap_dist_opencl
135 end interface
136
137#elif HAVE_METAL
138 interface
139 subroutine add_kinematics_to_mesh_velocity_metal(wx, wy, wz, &
140 x_ref, y_ref, z_ref, phi, x, y, z, &
141 kin_params, n) &
142 bind(c, name = "add_kinematics_to_mesh_velocity_metal")
143 use, intrinsic :: iso_c_binding
144 import :: kinematics_params_t
145 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
146 type(kinematics_params_t), value :: kin_params
147 integer(c_int), value :: n
148 end subroutine add_kinematics_to_mesh_velocity_metal
149
150 subroutine compute_cheap_dist_metal(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
151 local_iters, nchange_d) &
152 bind(c, name = "compute_cheap_dist_metal")
153 use, intrinsic :: iso_c_binding
154 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
155 integer(c_int), value :: lx, ly, lz, nel, local_iters
156 end subroutine compute_cheap_dist_metal
157 end interface
158
159#endif
160
161contains
162
164 subroutine compute_cheap_dist_device(dist_field, coef, msh, zone_indices, &
165 copy_to_host)
166 type(field_t), intent(inout) :: dist_field
167 type(coef_t), intent(in) :: coef
168 type(mesh_t), intent(in) :: msh
169 type(zero_dirichlet_t) :: bc_wall
170 integer, intent(in) :: zone_indices(:)
171 logical, intent(in) :: copy_to_host
172 integer :: i, k, n, m, idx
173 integer :: ipass, max_pass, local_iters
174 integer :: lx, ly, lz, nel, z_idx
175 integer, target :: change_vec(1)
176 logical :: done
177 character(len=LOG_SIZE) :: log_buf
178 type(c_ptr) :: nchange_d
179
180 nchange_d = c_null_ptr
181 lx = coef%dof%Xh%lx
182 ly = coef%dof%Xh%ly
183 lz = coef%dof%Xh%lz
184 nel = msh%nelv
185 n = coef%dof%size()
186 max_pass = 10000
187
188 ! Limit for worst case scenario such that all nodes can propagate
189 ! their values across the element before triggering an MPI call.
190 local_iters = lx + ly + lz
191
192 call cfill(dist_field%x, huge(0.0_rp), n)
193
194 if (size(zone_indices) .gt. 0) then
195 call bc_wall%init_from_components(coef)
196 do k = 1, size(zone_indices)
197 z_idx = zone_indices(k)
198 call bc_wall%mark_zone(msh%labeled_zones(z_idx))
199 end do
200 call bc_wall%finalize()
201 m = bc_wall%msk(0)
202 do i = 1, m
203 idx = bc_wall%msk(i)
204 dist_field%x(idx, 1, 1, 1) = 0.0_rp
205 end do
206 call bc_wall%free()
207 end if
208
209 call device_map(change_vec, nchange_d, 1)
210 call dist_field%copy_from(host_to_device, sync = .true.)
211
212 ipass = 1
213 done = .false.
214
215 do while ((ipass .le. max_pass) .and. .not. done)
216
217 change_vec(1) = 0
218 call device_memcpy(change_vec, nchange_d, 1, host_to_device, .true.)
219
220#ifdef HAVE_HIP
221 call compute_cheap_dist_hip(dist_field%x_d, &
222 coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
223 lx, ly, lz, nel, local_iters, nchange_d)
224#elif HAVE_CUDA
225 call compute_cheap_dist_cuda(dist_field%x_d, &
226 coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
227 lx, ly, lz, nel, local_iters, nchange_d)
228#elif HAVE_OPENCL
229 call compute_cheap_dist_opencl(dist_field%x_d, &
230 coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
231 lx, ly, lz, nel, local_iters, nchange_d)
232#elif HAVE_METAL
233 call compute_cheap_dist_metal(dist_field%x_d, &
234 coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
235 lx, ly, lz, nel, local_iters, nchange_d)
236#endif
237
238 call device_memcpy(change_vec, nchange_d, 1, device_to_host, .true.)
239
240 call coef%gs_h%gs_op_vector(dist_field%x, n, gs_op_min)
241
242 if (glimax(change_vec, 1) .eq. 0) done = .true.
243 ipass = ipass + 1
244 end do
245
246 call device_unmap(change_vec, nchange_d)
247
248 if (copy_to_host) then
249 call dist_field%copy_from(device_to_host, sync = .true.)
250 end if
251
252 if (done) then
253 write(log_buf, '(A, I0, A)') " converged in: ", ipass, " passes"
254 call neko_log%message(log_buf)
255 else
256 write(log_buf, '(A, I0, A)') " reached max passes: ", ipass, &
257 " without convergence"
258 call neko_log%message(log_buf)
259 end if
260 end subroutine compute_cheap_dist_device
261
262
265 x_ref, y_ref, z_ref, phi, coef, kinematics, rot_mat, inital_pivot_loc)
266 type(field_t), intent(inout) :: wx, wy, wz
267 type(field_t), intent(in) :: x_ref, y_ref, z_ref
268 type(field_t), intent(in) :: phi
269 type(coef_t), intent(in) :: coef
270 type(body_kinematics_t), intent(in) :: kinematics
271 real(kind=rp), intent(in) :: inital_pivot_loc(3)
272 real(kind=rp), intent(in) :: rot_mat(3,3)
273 integer(c_int), target :: n
274 type(kinematics_params_t) :: kin_params
275
276 n = phi%dof%size()
277
278 kin_params%cx = kinematics%center(1)
279 kin_params%cy = kinematics%center(2)
280 kin_params%cz = kinematics%center(3)
281 kin_params%vtx = kinematics%vel_trans(1)
282 kin_params%vty = kinematics%vel_trans(2)
283 kin_params%vtz = kinematics%vel_trans(3)
284 kin_params%vax = kinematics%vel_ang(1)
285 kin_params%vay = kinematics%vel_ang(2)
286 kin_params%vaz = kinematics%vel_ang(3)
287 kin_params%px = inital_pivot_loc(1)
288 kin_params%py = inital_pivot_loc(2)
289 kin_params%pz = inital_pivot_loc(3)
290 kin_params%r11 = rot_mat(1,1)
291 kin_params%r12 = rot_mat(1,2)
292 kin_params%r13 = rot_mat(1,3)
293 kin_params%r21 = rot_mat(2,1)
294 kin_params%r22 = rot_mat(2,2)
295 kin_params%r23 = rot_mat(2,3)
296 kin_params%r31 = rot_mat(3,1)
297 kin_params%r32 = rot_mat(3,2)
298 kin_params%r33 = rot_mat(3,3)
299
300#ifdef HAVE_HIP
302 wx%x_d, wy%x_d, wz%x_d, &
303 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
304 phi%x_d, coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
305 kin_params, n)
306#elif HAVE_CUDA
308 wx%x_d, wy%x_d, wz%x_d, &
309 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
310 phi%x_d, coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
311 kin_params, n)
312#elif HAVE_OPENCL
314 wx%x_d, wy%x_d, wz%x_d, &
315 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
316 phi%x_d, coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
317 kin_params, n)
318#elif HAVE_METAL
319 call add_kinematics_to_mesh_velocity_metal( &
320 wx%x_d, wy%x_d, wz%x_d, &
321 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
322 phi%x_d, coef%dof%x%x_d, coef%dof%y%x_d, coef%dof%z%x_d, &
323 kin_params, n)
324#else
325 call neko_error("ALE: no device backend configured")
326#endif
327
329
330
332 subroutine update_ale_mesh_device(c_Xh, wm_x, wm_y, wm_z, wm_x_lag, &
333 wm_y_lag, wm_z_lag, time, nadv, scheme_type)
334
335 type(coef_t), intent(inout) :: c_xh
336 type(field_t), intent(in) :: wm_x, wm_y, wm_z
337 type(field_series_t), intent(in) :: wm_x_lag, wm_y_lag, wm_z_lag
338 type(time_state_t), intent(in) :: time
339 type(ab_time_scheme_t) :: ab_scheme_obj
340 integer, intent(in) :: nadv
341 integer :: j, n
342 character(len=*), intent(in) :: scheme_type
343 real(kind=rp) :: ab_coeffs(4), factor, dt_history(10)
344
345 call rzero(ab_coeffs, 4)
346 if (trim(scheme_type) .eq. 'ab') then
347 dt_history(1) = real(time%dt, kind=rp)
348 dt_history(2) = real(time%dtlag(1), kind=rp)
349 dt_history(3) = real(time%dtlag(2), kind=rp)
350 call ab_scheme_obj%compute_coeffs(ab_coeffs, dt_history, nadv)
351 else
352 call neko_error("ALE: Unknown mesh time-integration scheme")
353 end if
354
355 n = c_xh%dof%size()
356
357 ! Current timestep update
358 factor = time%dt * ab_coeffs(1)
359 call device_add2s2(c_xh%dof%x%x_d, wm_x%x_d, factor, n)
360 call device_add2s2(c_xh%dof%y%x_d, wm_y%x_d, factor, n)
361 call device_add2s2(c_xh%dof%z%x_d, wm_z%x_d, factor, n)
362
363 ! History Terms
364 do j = 2, nadv
365 factor = time%dt * ab_coeffs(j)
366 call device_add2s2(c_xh%dof%x%x_d, wm_x_lag%lf(j - 1)%x_d, factor, n)
367 call device_add2s2(c_xh%dof%y%x_d, wm_y_lag%lf(j - 1)%x_d, factor, n)
368 call device_add2s2(c_xh%dof%z%x_d, wm_z_lag%lf(j - 1)%x_d, factor, n)
369 end do
370 end subroutine update_ale_mesh_device
371
372end module ale_routines_device
void add_kinematics_to_mesh_velocity_opencl(void *wx, void *wy, void *wz, void *x_ref, void *y_ref, void *z_ref, void *phi, void *x, void *y, void *z, kinematics_params_t kin_params, int n)
void compute_cheap_dist_opencl(void *d_d, void *x_d, void *y_d, void *z_d, int lx, int ly, int lz, int nel, int local_iters, void *nchange_d)
void compute_cheap_dist_cuda(void *d_d, void *x_d, void *y_d, void *z_d, int lx, int ly, int lz, int nel, int local_iters, void *nchange_d)
void add_kinematics_to_mesh_velocity_cuda(void *wx, void *wy, void *wz, void *x_ref, void *y_ref, void *z_ref, void *phi, void *x, void *y, void *z, kinematics_params_t kin_params, int n)
double real
Map a Fortran array to a device (allocate and associate)
Definition device.F90:83
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
Adam-Bashforth scheme for time integration.
Defines data structures and algorithms for configuring, calculating, and time-integrating the rigid-b...
subroutine, public add_kinematics_to_mesh_velocity_device(wx, wy, wz, x_ref, y_ref, z_ref, phi, coef, kinematics, rot_mat, inital_pivot_loc)
Add Kinematics to Mesh Velocity.
subroutine, public compute_cheap_dist_device(dist_field, coef, msh, zone_indices, copy_to_host)
Cheap dist device implementation.
subroutine, public update_ale_mesh_device(c_xh, wm_x, wm_y, wm_z, wm_x_lag, wm_y_lag, wm_z_lag, time, nadv, scheme_type)
Update ALE Mesh.
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
subroutine, public device_add2s2(a_d, b_d, c1, n, strm)
Vector addition with scalar multiplication (multiplication on first argument)
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
integer, parameter, public device_to_host
Definition device.F90:48
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Gather-scatter.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:91
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:601
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:239
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition math.f90:693
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public c_rp
Definition num_types.f90:15
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Defines a zero-valued Dirichlet boundary condition.
Explicit Adam-Bashforth scheme for time integration.
Calculated Kinematics for a body at current time.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:135
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
A struct that contains all info about the time, expand as needed.
Zero-valued Dirichlet boundary condition. Used for no-slip walls, but also for various auxillary cond...