39 use num_types,
only: rp
40 use math,
only: subcol3, rzero
41 use space,
only: space_t
42 use field,
only: field_t
43 use coefs,
only: coef_t
44 use scratch_registry,
only: neko_scratch_registry
45 use neko_config,
only: neko_bcknd_device, neko_bcknd_sx, neko_bcknd_xsmm, &
46 neko_bcknd_opencl, neko_bcknd_cuda, neko_bcknd_hip
47 use operators,
only: opgrad, conv1, cdtp
48 use device_math,
only: device_vdot3, device_sub2, device_add4, &
49 device_col3, device_subcol3, device_rzero
50 use device,
only: device_map, device_unmap, device_get_ptr
51 use utils,
only: neko_error
52 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, &
59 real(kind=rp),
allocatable :: temp(:)
60 type(c_ptr) :: temp_d = c_null_ptr
65 procedure, pass(this) :: compute_linear => linear_advection_no_dealias
71 procedure, pass(this) :: compute_adjoint => adjoint_advection_no_dealias
76 procedure, pass(this) :: compute_adjoint_scalar => &
77 compute_adjoint_scalar_advection_no_dealias
85 procedure, pass(this) :: free => free_no_dealias
95 type(coef_t),
intent(in) :: coef
99 allocate(this%temp(coef%dof%size()))
101 if (neko_bcknd_device .eq. 1)
then
102 call device_map(this%temp, this%temp_d, coef%dof%size())
109 subroutine free_no_dealias(this)
112 if (
allocated(this%temp))
then
113 if (c_associated(this%temp_d))
then
114 call device_unmap(this%temp, this%temp_d)
116 deallocate(this%temp)
118 end subroutine free_no_dealias
137 subroutine adjoint_advection_no_dealias(this, vx, vy, vz, vxb, vyb, vzb, fx, &
141 type(space_t),
intent(inout) :: Xh
142 type(coef_t),
intent(inout) :: coef
143 type(field_t),
intent(inout) :: vx, vy, vz
144 type(field_t),
intent(inout) :: vxb, vyb, vzb
145 integer,
intent(in) :: n
146 type(field_t),
intent(inout) :: fx, fy, fz
147 type(c_ptr) :: fx_d, fy_d, fz_d
148 type(c_ptr) :: vx_d, vy_d, vz_d
151 real(kind=rp),
dimension(Xh%lxyz) :: duxb, dvxb, dwxb
152 real(kind=rp),
dimension(Xh%lxyz) :: duyb, dvyb, dwyb
153 real(kind=rp),
dimension(Xh%lxyz) :: duzb, dvzb, dwzb
156 type(field_t),
pointer :: tduxb, tdvxb, tdwxb, tduyb, tdvyb, tdwyb, tduzb, &
158 integer :: temp_indices(9)
160 if (neko_bcknd_device .eq. 1)
then
161 call neko_scratch_registry%request_field(tduxb, temp_indices(1), .false.)
162 call neko_scratch_registry%request_field(tdvxb, temp_indices(2), .false.)
163 call neko_scratch_registry%request_field(tdwxb, temp_indices(3), .false.)
164 call neko_scratch_registry%request_field(tduyb, temp_indices(4), .false.)
165 call neko_scratch_registry%request_field(tdvyb, temp_indices(5), .false.)
166 call neko_scratch_registry%request_field(tdwyb, temp_indices(6), .false.)
167 call neko_scratch_registry%request_field(tduzb, temp_indices(7), .false.)
168 call neko_scratch_registry%request_field(tdvzb, temp_indices(8), .false.)
169 call neko_scratch_registry%request_field(tdwzb, temp_indices(9), .false.)
180 call opgrad(tduxb%x, tduyb%x, tduzb%x, vxb%x, coef)
181 call opgrad(tdvxb%x, tdvyb%x, tdvzb%x, vyb%x, coef)
182 call opgrad(tdwxb%x, tdwyb%x, tdwzb%x, vzb%x, coef)
186 call device_vdot3(this%temp_d, vx_d, vy_d, vz_d, &
187 tduxb%x_d, tdvxb%x_d, tdwxb%x_d, n)
188 call device_sub2(fx_d, this%temp_d, n)
190 call device_vdot3(this%temp_d, vx_d, vy_d, vz_d, &
191 tduyb%x_d, tdvyb%x_d, tdwyb%x_d, n)
192 call device_sub2(fy_d, this%temp_d, n)
194 call device_vdot3(this%temp_d, vx_d, vy_d, vz_d, &
195 tduzb%x_d, tdvzb%x_d, tdwzb%x_d, n)
196 call device_sub2(fz_d, this%temp_d, n)
200 associate(w1 => tduxb, w2 => tdvxb, w3 => tdwxb, &
201 w4 => tduyb, w5 => tdvyb, w6 => tdwyb)
202 call adjoint_weak_no_dealias_device(fx_d, vx_d, &
203 vxb%x, vyb%x, vzb%x, &
205 w1, w2, w3, w4, w5, w6)
207 call adjoint_weak_no_dealias_device(fy_d, vy_d, &
208 vxb%x, vyb%x, vzb%x, &
210 w1, w2, w3, w4, w5, w6)
212 call adjoint_weak_no_dealias_device(fz_d, vz_d, &
213 vxb%x, vyb%x, vzb%x, &
215 w1, w2, w3, w4, w5, w6)
218 call neko_scratch_registry%relinquish_field(temp_indices)
219 else if ((neko_bcknd_sx .eq. 1) .or. (neko_bcknd_xsmm .eq. 1))
then
222 call neko_error(
"Adjoint advection without dealiasing is not " // &
223 "implemented for the SX and XSMM backends")
225 do e = 1, coef%msh%nelv
228 call opgrad(duxb, duyb, duzb, vxb%x(1,1,1,e), coef, e, e)
229 call opgrad(dvxb, dvyb, dvzb, vyb%x(1,1,1,e), coef, e, e)
230 call opgrad(dwxb, dwyb, dwzb, vzb%x(1,1,1,e), coef, e, e)
234 fx%x(i,1,1,e) = fx%x(i,1,1,e) - ( &
235 vx%x(i,1,1,e)*duxb(i) + &
236 vy%x(i,1,1,e)*dvxb(i) + &
237 vz%x(i,1,1,e)*dwxb(i) )
239 fy%x(i,1,1,e) = fy%x(i,1,1,e) - ( &
240 vx%x(i,1,1,e)*duyb(i) + &
241 vy%x(i,1,1,e)*dvyb(i) + &
242 vz%x(i,1,1,e)*dwyb(i))
244 fz%x(i,1,1,e) = fz%x(i,1,1,e) - ( &
245 vx%x(i,1,1,e)*duzb(i) + &
246 vy%x(i,1,1,e)*dvzb(i) + &
247 vz%x(i,1,1,e)*dwzb(i))
253 associate(w1 => duxb, w2 => dvxb, w3 => dwxb, &
254 w4 => duyb, w5 => dvyb, w6 => dwyb)
255 call adjoint_weak_no_dealias_cpu( &
256 fx%x(:,:,:,e), vx%x(1,1,1,e), &
257 vxb%x(1,1,1,e), vyb%x(1,1,1,e), vzb%x(1,1,1,e), &
258 e, coef, xh, xh%lxyz, &
259 w1, w2, w3, w4, w5, w6)
261 call adjoint_weak_no_dealias_cpu( &
262 fy%x(:,:,:,e), vy%x(1,1,1,e), &
263 vxb%x(1,1,1,e), vyb%x(1,1,1,e), vzb%x(1,1,1,e), &
264 e, coef, xh, xh%lxyz, &
265 w1, w2, w3, w4, w5, w6)
267 call adjoint_weak_no_dealias_cpu( &
268 fz%x(:,:,:,e), vz%x(1,1,1,e), &
269 vxb%x(1,1,1,e), vyb%x(1,1,1,e), vzb%x(1,1,1,e), &
270 e, coef, xh, xh%lxyz, &
271 w1, w2, w3, w4, w5, w6)
277 end subroutine adjoint_advection_no_dealias
297 subroutine adjoint_weak_no_dealias_device(f_d, u_i_d, ub, vb, wb, coef, Xh, &
298 n, work1, work2, work3, w1, w2, w3)
299 integer,
intent(in) :: n
300 type(c_ptr),
intent(inout) :: f_d
301 type(c_ptr),
intent(in) :: u_i_d
302 real(kind=rp),
intent(inout),
dimension(n) :: ub, vb, wb
303 type(field_t),
intent(inout) :: w1, w2, w3
304 type(field_t),
intent(inout) :: work1, work2, work3
305 type(space_t),
intent(inout) :: Xh
306 type(coef_t),
intent(inout) :: coef
307 type(c_ptr) :: ub_d, vb_d, wb_d
308 type(c_ptr) :: work1_d, work2_d, work3_d, w1_d, w2_d, w3_d
316 ub_d = device_get_ptr(ub)
317 vb_d = device_get_ptr(vb)
318 wb_d = device_get_ptr(wb)
321 call device_col3(work1_d, u_i_d, ub_d, n)
322 call device_col3(work2_d, u_i_d, vb_d, n)
323 call device_col3(work3_d, u_i_d, wb_d, n)
325 call cdtp(w1%x, work1%x, coef%drdx, coef%dsdx, coef%dtdx, coef)
326 call cdtp(w2%x, work2%x, coef%drdy, coef%dsdy, coef%dtdy, coef)
327 call cdtp(w3%x, work3%x, coef%drdz, coef%dsdz, coef%dtdz, coef)
329 call device_add4(work1_d, w1_d, w2_d, w3_d , n)
330 call device_sub2(f_d, work1_d, n)
331 end subroutine adjoint_weak_no_dealias_device
352 subroutine adjoint_weak_no_dealias_cpu(f, u_i, ub, vb, wb, e, coef, Xh, n, &
353 work1, work2, work3, w1, w2, w3)
355 integer,
intent(in) :: e, n
357 real(kind=rp),
intent(inout),
dimension(n) :: f
358 real(kind=rp),
intent(inout),
dimension(n) :: u_i
359 real(kind=rp),
intent(inout),
dimension(n) :: ub, vb, wb
360 real(kind=rp),
intent(inout),
dimension(n) :: w1, w2, w3
361 real(kind=rp),
intent(inout),
dimension(n) :: work1, work2, work3
362 type(space_t),
intent(inout) :: xh
363 type(coef_t),
intent(inout) :: coef
367 work1(i) = u_i(i)*ub(i)
368 work2(i) = u_i(i)*vb(i)
369 work3(i) = u_i(i)*wb(i)
373 call cdtp(w1, work1, coef%drdx, coef%dsdx, coef%dtdx, coef, e ,e)
374 call cdtp(w2, work2, coef%drdy, coef%dsdy, coef%dtdy, coef, e ,e)
375 call cdtp(w3, work3, coef%drdz, coef%dsdz, coef%dtdz, coef, e, e)
379 f(i) = f(i) - (w1(i) + w2(i) + w3(i))
381 end subroutine adjoint_weak_no_dealias_cpu
401 subroutine linear_advection_no_dealias(this, vx, vy, vz, vxb, vyb, vzb, fx, &
405 type(space_t),
intent(inout) :: Xh
406 type(coef_t),
intent(inout) :: coef
407 type(field_t),
intent(inout) :: vx, vy, vz
408 type(field_t),
intent(inout) :: vxb, vyb, vzb
409 integer,
intent(in) :: n
410 type(field_t),
intent(inout) :: fx, fy, fz
411 type(c_ptr) :: fx_d, fy_d, fz_d
413 if (neko_bcknd_device .eq. 1)
then
419 call conv1(this%temp, vx%x, vxb%x, vyb%x, vzb%x, xh, coef)
420 call device_subcol3 (fx_d, coef%B_d, this%temp_d, n)
421 call conv1(this%temp, vxb%x, vx%x, vy%x, vz%x, xh, coef)
422 call device_subcol3 (fx_d, coef%B_d, this%temp_d, n)
425 call conv1(this%temp, vy%x, vxb%x, vyb%x, vzb%x, xh, coef)
426 call device_subcol3 (fy_d, coef%B_d, this%temp_d, n)
427 call conv1(this%temp, vyb%x, vx%x, vy%x, vz%x, xh, coef)
428 call device_subcol3 (fy_d, coef%B_d, this%temp_d, n)
431 if (coef%Xh%lz .eq. 1)
then
432 call device_rzero (this%temp_d, n)
434 call conv1(this%temp, vz%x, vxb%x, vyb%x, vzb%x, xh, coef)
435 call device_subcol3(fz_d, coef%B_d, this%temp_d, n)
436 call conv1(this%temp, vzb%x, vx%x, vy%x, vz%x, xh, coef)
437 call device_subcol3(fz_d, coef%B_d, this%temp_d, n)
441 call conv1(this%temp, vx%x, vxb%x, vyb%x, vzb%x, xh, coef)
442 call subcol3 (fx%x, coef%B, this%temp, n)
443 call conv1(this%temp, vxb%x, vx%x, vy%x, vz%x, xh, coef)
444 call subcol3 (fx%x, coef%B, this%temp, n)
447 call conv1(this%temp, vy%x, vxb%x, vyb%x, vzb%x, xh, coef)
448 call subcol3 (fy%x, coef%B, this%temp, n)
449 call conv1(this%temp, vyb%x, vx%x, vy%x, vz%x, xh, coef)
450 call subcol3 (fy%x, coef%B, this%temp, n)
453 if (coef%Xh%lz .eq. 1)
then
454 call rzero (this%temp, n)
456 call conv1(this%temp, vz%x, vxb%x, vyb%x, vzb%x, xh, coef)
457 call subcol3(fz%x, coef%B, this%temp, n)
458 call conv1(this%temp, vzb%x, vx%x, vy%x, vz%x, xh, coef)
459 call subcol3(fz%x, coef%B, this%temp, n)
463 end subroutine linear_advection_no_dealias
479 subroutine compute_adjoint_scalar_advection_no_dealias(this, vxb, vyb, vzb, &
480 s, fs, Xh, coef, n, dt)
482 type(field_t),
intent(inout) :: vxb, vyb, vzb
483 type(field_t),
intent(inout) :: s
484 type(field_t),
intent(inout) :: fs
485 type(space_t),
intent(inout) :: Xh
486 type(coef_t),
intent(inout) :: coef
487 integer,
intent(in) :: n
488 real(kind=rp),
intent(in),
optional :: dt
489 real(kind=rp),
dimension(Xh%lxyz) :: w1, w2, w3, w4, w5, w6
491 type(field_t),
pointer :: w1_d, w2_d, w3_d, w4_d, w5_d, w6_d
492 integer :: temp_indices(6)
494 if (neko_bcknd_device .eq. 1)
then
495 call neko_scratch_registry%request_field(w1_d, temp_indices(1), .false.)
496 call neko_scratch_registry%request_field(w2_d, temp_indices(2), .false.)
497 call neko_scratch_registry%request_field(w3_d, temp_indices(3), .false.)
498 call neko_scratch_registry%request_field(w4_d, temp_indices(4), .false.)
499 call neko_scratch_registry%request_field(w5_d, temp_indices(5), .false.)
500 call neko_scratch_registry%request_field(w6_d, temp_indices(6), .false.)
502 call adjoint_weak_no_dealias_device(fs%x_d, s%x_d, &
503 vxb%x, vyb%x, vzb%x, &
505 w1_d, w2_d, w3_d, w4_d, w5_d, w6_d)
507 call neko_scratch_registry%relinquish_field(temp_indices)
509 else if ((neko_bcknd_sx .eq. 1) .or. (neko_bcknd_xsmm .eq. 1))
then
512 call neko_error(
"Adjoint scalar advection without dealiasing is " // &
513 "not implemented for the SX and XSMM backends")
515 do e = 1, coef%msh%nelv
518 call adjoint_weak_no_dealias_cpu( &
519 fs%x(:,:,:,e), s%x(1,1,1,e), &
520 vxb%x(1,1,1,e), vyb%x(1,1,1,e), vzb%x(1,1,1,e), &
521 e, coef, xh, xh%lxyz, &
522 w1, w2, w3, w4, w5, w6)
526 end subroutine compute_adjoint_scalar_advection_no_dealias
Subroutines to add perturbed advection terms to the RHS of a transport equation.
subroutine init_no_dealias(this, coef)
Constructor.
Subroutines to add advection terms to the RHS of a transport equation.
Type encapsulating advection routines with no dealiasing applied.
Base abstract type for computing the advection operator.