Neko 1.99.5
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) bind(c, name="add_kinematics_to_mesh_velocity_hip")
77 use, intrinsic :: iso_c_binding
78 import :: kinematics_params_t
79 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
80 type(kinematics_params_t), value :: kin_params
81 integer(c_int), value :: n
83
84 subroutine compute_cheap_dist_hip(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
85 local_iters, nchange_d) bind(c, name="compute_cheap_dist_hip")
86 use, intrinsic :: iso_c_binding
87 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
88 integer(c_int), value :: lx, ly, lz, nel, local_iters
89 end subroutine compute_cheap_dist_hip
90 end interface
91#elif HAVE_CUDA
92 interface
93 subroutine add_kinematics_to_mesh_velocity_cuda(wx, wy, wz, &
94 x_ref, y_ref, z_ref, phi, x, y, z, &
95 kin_params, n) bind(c, name="add_kinematics_to_mesh_velocity_cuda")
96 use, intrinsic :: iso_c_binding
97 import :: kinematics_params_t
98 type(c_ptr), value :: wx, wy, wz, x_ref, y_ref, z_ref, phi, x, y, z
99 type(kinematics_params_t), value :: kin_params
100 integer(c_int), value :: n
102
103 subroutine compute_cheap_dist_cuda(d_d, x_d, y_d, z_d, lx, ly, lz, nel, &
104 local_iters, nchange_d) bind(c, name="compute_cheap_dist_cuda")
105 use, intrinsic :: iso_c_binding
106 type(c_ptr), value :: d_d, x_d, y_d, z_d, nchange_d
107 integer(c_int), value :: lx, ly, lz, nel, local_iters
108 end subroutine compute_cheap_dist_cuda
109 end interface
110
111#endif
112
113contains
114
116 subroutine compute_cheap_dist_device(dist_field, coef, msh, zone_indices, copy_to_host)
117 type(field_t), intent(inout) :: dist_field
118 type(coef_t), intent(in) :: coef
119 type(mesh_t), intent(in) :: msh
120 type(zero_dirichlet_t) :: bc_wall
121 integer, intent(in) :: zone_indices(:)
122 logical, intent(in) :: copy_to_host
123 integer :: i, k, n, m, idx
124 integer :: ipass, max_pass, local_iters
125 integer :: lx, ly, lz, nel, z_idx
126 integer, target :: change_vec(1)
127 logical :: done
128 character(len=LOG_SIZE) :: log_buf
129 type(c_ptr) :: nchange_d
130
131 nchange_d = c_null_ptr
132 lx = coef%dof%Xh%lx
133 ly = coef%dof%Xh%ly
134 lz = coef%dof%Xh%lz
135 nel = msh%nelv
136 n = coef%dof%size()
137 max_pass = 10000
138
139 ! Limit for worst case scenario such that all nodes can propagate
140 ! their values across the element before triggering an MPI call.
141 local_iters = lx + ly + lz
142
143 call cfill(dist_field%x, huge(0.0_rp), n)
144
145 if (size(zone_indices) .gt. 0) then
146 call bc_wall%init_from_components(coef)
147 do k = 1, size(zone_indices)
148 z_idx = zone_indices(k)
149 call bc_wall%mark_zone(msh%labeled_zones(z_idx))
150 end do
151 call bc_wall%finalize()
152 m = bc_wall%msk(0)
153 do i = 1, m
154 idx = bc_wall%msk(i)
155 dist_field%x(idx, 1, 1, 1) = 0.0_rp
156 end do
157 call bc_wall%free()
158 end if
159
160 call device_map(change_vec, nchange_d, 1)
161 call dist_field%copy_from(host_to_device, sync = .true.)
162
163 ipass = 1
164 done = .false.
165
166 do while ((ipass .le. max_pass) .and. .not. done)
167
168 change_vec(1) = 0
169 call device_memcpy(change_vec, nchange_d, 1, host_to_device, .true.)
170
171#ifdef HAVE_HIP
172 call compute_cheap_dist_hip(dist_field%x_d, &
173 coef%dof%x_d, coef%dof%y_d, coef%dof%z_d, &
174 lx, ly, lz, nel, local_iters, nchange_d)
175#elif HAVE_CUDA
176 call compute_cheap_dist_cuda(dist_field%x_d, &
177 coef%dof%x_d, coef%dof%y_d, coef%dof%z_d, &
178 lx, ly, lz, nel, local_iters, nchange_d)
179#endif
180
181 call device_memcpy(change_vec, nchange_d, 1, device_to_host, .true.)
182
183 call coef%gs_h%gs_op_vector(dist_field%x, n, gs_op_min)
184
185 if (glimax(change_vec, 1) .eq. 0) done = .true.
186 ipass = ipass + 1
187 end do
188
189 call device_unmap(change_vec, nchange_d)
190
191 if (copy_to_host) then
192 call dist_field%copy_from(device_to_host, sync = .true.)
193 end if
194
195 if (done) then
196 write(log_buf, '(A, I0, A)') " converged in: ", ipass, " passes"
197 call neko_log%message(log_buf)
198 else
199 write(log_buf, '(A, I0, A)') " reached max passes: ", ipass, &
200 " without convergence"
201 call neko_log%message(log_buf)
202 end if
203 end subroutine compute_cheap_dist_device
204
205
208 x_ref, y_ref, z_ref, phi, coef, kinematics, rot_mat, inital_pivot_loc)
209 type(field_t), intent(inout) :: wx, wy, wz
210 type(field_t), intent(in) :: x_ref, y_ref, z_ref
211 type(field_t), intent(in) :: phi
212 type(coef_t), intent(in) :: coef
213 type(body_kinematics_t), intent(in) :: kinematics
214 real(kind=rp), intent(in) :: inital_pivot_loc(3)
215 real(kind=rp), intent(in) :: rot_mat(3,3)
216 integer(c_int), target :: n
217 type(kinematics_params_t) :: kin_params
218
219 n = phi%dof%size()
220
221 kin_params%cx = kinematics%center(1)
222 kin_params%cy = kinematics%center(2)
223 kin_params%cz = kinematics%center(3)
224 kin_params%vtx = kinematics%vel_trans(1)
225 kin_params%vty = kinematics%vel_trans(2)
226 kin_params%vtz = kinematics%vel_trans(3)
227 kin_params%vax = kinematics%vel_ang(1)
228 kin_params%vay = kinematics%vel_ang(2)
229 kin_params%vaz = kinematics%vel_ang(3)
230 kin_params%px = inital_pivot_loc(1)
231 kin_params%py = inital_pivot_loc(2)
232 kin_params%pz = inital_pivot_loc(3)
233 kin_params%r11 = rot_mat(1,1)
234 kin_params%r12 = rot_mat(1,2)
235 kin_params%r13 = rot_mat(1,3)
236 kin_params%r21 = rot_mat(2,1)
237 kin_params%r22 = rot_mat(2,2)
238 kin_params%r23 = rot_mat(2,3)
239 kin_params%r31 = rot_mat(3,1)
240 kin_params%r32 = rot_mat(3,2)
241 kin_params%r33 = rot_mat(3,3)
242
243#ifdef HAVE_HIP
245 wx%x_d, wy%x_d, wz%x_d, &
246 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
247 phi%x_d, coef%dof%x_d, coef%dof%y_d, coef%dof%z_d, &
248 kin_params, n)
249#elif HAVE_CUDA
251 wx%x_d, wy%x_d, wz%x_d, &
252 x_ref%x_d, y_ref%x_d, z_ref%x_d, &
253 phi%x_d, coef%dof%x_d, coef%dof%y_d, coef%dof%z_d, &
254 kin_params, n)
255#else
256 call neko_error("ALE: add_kinematics_to_mesh_velocity_device " // &
257 "supports only HIP or CUDA backends")
258#endif
259
261
262
264 subroutine update_ale_mesh_device(c_Xh, wm_x, wm_y, wm_z, wm_x_lag, &
265 wm_y_lag, wm_z_lag, time, nadv, scheme_type)
266
267 type(coef_t), intent(inout) :: c_xh
268 type(field_t), intent(in) :: wm_x, wm_y, wm_z
269 type(field_series_t), intent(in) :: wm_x_lag, wm_y_lag, wm_z_lag
270 type(time_state_t), intent(in) :: time
271 type(ab_time_scheme_t) :: ab_scheme_obj
272 integer, intent(in) :: nadv
273 integer :: j, n
274 character(len=*), intent(in) :: scheme_type
275 real(kind=rp) :: ab_coeffs(4), dt_history(10), factor
276
277 call rzero(ab_coeffs, 4)
278 if (trim(scheme_type) .eq. 'ab') then
279 dt_history(1) = time%dt
280 dt_history(2) = time%dtlag(1)
281 dt_history(3) = time%dtlag(2)
282 call ab_scheme_obj%compute_coeffs(ab_coeffs, dt_history, nadv)
283 else
284 call neko_error("ALE: Unknown mesh time-integration scheme")
285 end if
286
287 n = c_xh%dof%size()
288
289 ! Current timestep update
290 factor = time%dt * ab_coeffs(1)
291 call device_add2s2(c_xh%dof%x_d, wm_x%x_d, factor, n)
292 call device_add2s2(c_xh%dof%y_d, wm_y%x_d, factor, n)
293 call device_add2s2(c_xh%dof%z_d, wm_z%x_d, factor, n)
294
295 ! History Terms
296 do j = 2, nadv
297 factor = time%dt * ab_coeffs(j)
298 call device_add2s2(c_xh%dof%x_d, wm_x_lag%lf(j - 1)%x_d, factor, n)
299 call device_add2s2(c_xh%dof%y_d, wm_y_lag%lf(j - 1)%x_d, factor, n)
300 call device_add2s2(c_xh%dof%z_d, wm_z_lag%lf(j - 1)%x_d, factor, n)
301 end do
302 end subroutine update_ale_mesh_device
303
304end module ale_routines_device
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)
Map a Fortran array to a device (allocate and associate)
Definition device.F90:78
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:84
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:45
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:80
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:597
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:235
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition math.f90:669
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public c_rp
Definition num_types.f90:13
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
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:62
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...