Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
lpt_periodic_bc.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!
35 use num_types, only : rp
37 use coefs, only : coef_t
38 use dofmap, only : dofmap_t
39 use mesh, only : mesh_t
41 use mpi_f08, only : mpi_allreduce, mpi_allgather, mpi_integer, &
42 mpi_min, mpi_max
43 use vector, only : vector_t
49 implicit none
50 private
51
52 real(kind=rp), parameter :: lpt_periodic_tol = 1.0e-8_rp
53
54 type, public :: lpt_periodic_bc_t
55 logical :: periodic_enabled = .false.
56 logical :: rotational_periodic_enabled = .false.
57 integer :: n_periodic_dirs = 0
58 real(kind=rp) :: periodic_shift_x1 = 0.0_rp
59 real(kind=rp) :: periodic_shift_y1 = 0.0_rp
60 real(kind=rp) :: periodic_shift_z1 = 0.0_rp
61 real(kind=rp) :: periodic_shift_x2 = 0.0_rp
62 real(kind=rp) :: periodic_shift_y2 = 0.0_rp
63 real(kind=rp) :: periodic_shift_z2 = 0.0_rp
64 real(kind=rp) :: periodic_shift_x3 = 0.0_rp
65 real(kind=rp) :: periodic_shift_y3 = 0.0_rp
66 real(kind=rp) :: periodic_shift_z3 = 0.0_rp
67 real(kind=rp) :: periodic_dir_x1 = 0.0_rp
68 real(kind=rp) :: periodic_dir_y1 = 0.0_rp
69 real(kind=rp) :: periodic_dir_z1 = 0.0_rp
70 real(kind=rp) :: periodic_dir_x2 = 0.0_rp
71 real(kind=rp) :: periodic_dir_y2 = 0.0_rp
72 real(kind=rp) :: periodic_dir_z2 = 0.0_rp
73 real(kind=rp) :: periodic_dir_x3 = 0.0_rp
74 real(kind=rp) :: periodic_dir_y3 = 0.0_rp
75 real(kind=rp) :: periodic_dir_z3 = 0.0_rp
76 real(kind=rp) :: periodic_min1 = 0.0_rp
77 real(kind=rp) :: periodic_min2 = 0.0_rp
78 real(kind=rp) :: periodic_min3 = 0.0_rp
79 real(kind=rp) :: periodic_max1 = 0.0_rp
80 real(kind=rp) :: periodic_max2 = 0.0_rp
81 real(kind=rp) :: periodic_max3 = 0.0_rp
82 real(kind=rp) :: periodic_len1 = 0.0_rp
83 real(kind=rp) :: periodic_len2 = 0.0_rp
84 real(kind=rp) :: periodic_len3 = 0.0_rp
85 real(kind=rp) :: rotational_theta_min = 0.0_rp
86 real(kind=rp) :: rotational_theta_max = 0.0_rp
87 real(kind=rp) :: rotational_theta_len = 0.0_rp
88 contains
89 procedure, pass(this) :: free => lpt_periodic_bc_free
90 procedure, pass(this) :: init => lpt_periodic_bc_init
91 procedure, pass(this) :: wrap => lpt_periodic_bc_wrap
92 procedure, private, pass(this) :: reset => lpt_periodic_bc_reset
93 procedure, private, pass(this) :: init_rotational => &
95 procedure, private, pass(this) :: init_translational => &
97 end type lpt_periodic_bc_t
98
99contains
100
102 subroutine lpt_periodic_bc_free(this)
103 class(lpt_periodic_bc_t), intent(inout) :: this
104
105 call this%reset()
106 end subroutine lpt_periodic_bc_free
107
112 subroutine lpt_periodic_bc_init(this, msh, dm_Xh, coef)
113 class(lpt_periodic_bc_t), intent(inout) :: this
114 type(mesh_t), intent(in), target :: msh
115 type(dofmap_t), intent(in) :: dm_Xh
116 type(coef_t), intent(in) :: coef
117
118 call this%reset()
119
120 if (msh%periodic%size .eq. 0) return
121
122 call this%init_rotational(msh, dm_xh, coef)
123 if (this%rotational_periodic_enabled) return
124
125 call this%init_translational(msh)
126 end subroutine lpt_periodic_bc_init
127
133 subroutine lpt_periodic_bc_wrap(this, x, y, z, n, u, v, w, u_lag, v_lag, &
134 w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, &
135 acc_xlaglag, acc_ylaglag, acc_zlaglag)
136 class(lpt_periodic_bc_t), intent(inout) :: this
137 type(vector_t), intent(inout) :: x, y, z
138 integer, intent(in) :: n
139 type(vector_t), intent(inout), optional :: u, v, w
140 type(vector_t), intent(inout), optional :: u_lag, v_lag, w_lag
141 type(vector_t), intent(inout), optional :: u_laglag, v_laglag, w_laglag
142 type(vector_t), intent(inout), optional :: acc_xlag, acc_ylag, acc_zlag
143 type(vector_t), intent(inout), optional :: acc_xlaglag
144 type(vector_t), intent(inout), optional :: acc_ylaglag
145 type(vector_t), intent(inout), optional :: acc_zlaglag
146
147 if (n .eq. 0) return
148 if (.not. this%periodic_enabled .and. &
149 .not. this%rotational_periodic_enabled) return
150
151 if (neko_bcknd_device .eq. 1) then
152 if (this%rotational_periodic_enabled) then
154 this%rotational_theta_min, this%rotational_theta_max, &
155 this%rotational_theta_len, u, v, w, u_lag, v_lag, w_lag, &
156 u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, &
157 acc_xlaglag, acc_ylaglag, acc_zlaglag)
158 else
160 this%n_periodic_dirs, this%periodic_dir_x1, &
161 this%periodic_dir_y1, this%periodic_dir_z1, &
162 this%periodic_dir_x2, this%periodic_dir_y2, &
163 this%periodic_dir_z2, this%periodic_dir_x3, &
164 this%periodic_dir_y3, this%periodic_dir_z3, &
165 this%periodic_min1, this%periodic_min2, this%periodic_min3, &
166 this%periodic_max1, this%periodic_max2, this%periodic_max3, &
167 this%periodic_shift_x1, this%periodic_shift_y1, &
168 this%periodic_shift_z1, this%periodic_shift_x2, &
169 this%periodic_shift_y2, this%periodic_shift_z2, &
170 this%periodic_shift_x3, this%periodic_shift_y3, &
171 this%periodic_shift_z3, this%periodic_len1, &
172 this%periodic_len2, this%periodic_len3)
173 end if
174 call lpt_periodic_bc_sync_from_device(x, y, z, u, v, w, u_lag, v_lag, &
175 w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, &
176 acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag)
177 return
178 end if
179
180 if (this%rotational_periodic_enabled) then
181 call lpt_periodic_bc_wrap_rotational_cpu(x, y, z, n, &
182 this%rotational_theta_min, this%rotational_theta_max, &
183 this%rotational_theta_len, u, v, w, u_lag, v_lag, w_lag, &
184 u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, &
185 acc_xlaglag, acc_ylaglag, acc_zlaglag)
186 return
187 end if
188
190 this%periodic_enabled, this%n_periodic_dirs, this%periodic_dir_x1, &
191 this%periodic_dir_y1, this%periodic_dir_z1, this%periodic_dir_x2, &
192 this%periodic_dir_y2, this%periodic_dir_z2, this%periodic_dir_x3, &
193 this%periodic_dir_y3, this%periodic_dir_z3, this%periodic_min1, &
194 this%periodic_min2, this%periodic_min3, this%periodic_max1, &
195 this%periodic_max2, this%periodic_max3, this%periodic_shift_x1, &
196 this%periodic_shift_y1, this%periodic_shift_z1, &
197 this%periodic_shift_x2, this%periodic_shift_y2, &
198 this%periodic_shift_z2, this%periodic_shift_x3, &
199 this%periodic_shift_y3, this%periodic_shift_z3, &
200 this%periodic_len1, this%periodic_len2, this%periodic_len3)
201 end subroutine lpt_periodic_bc_wrap
202
204 subroutine lpt_periodic_bc_sync_from_device(x, y, z, u, v, w, u_lag, &
205 v_lag, w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, &
206 acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag)
207 type(vector_t), intent(inout) :: x, y, z
208 type(vector_t), intent(inout), optional :: u, v, w
209 type(vector_t), intent(inout), optional :: u_lag, v_lag, w_lag
210 type(vector_t), intent(inout), optional :: u_laglag, v_laglag, w_laglag
211 type(vector_t), intent(inout), optional :: acc_xlag, acc_ylag, acc_zlag
212 type(vector_t), intent(inout), optional :: acc_xlaglag
213 type(vector_t), intent(inout), optional :: acc_ylaglag
214 type(vector_t), intent(inout), optional :: acc_zlaglag
215
216 call x%copy_from(device_to_host, .false.)
217 call y%copy_from(device_to_host, .false.)
218 call z%copy_from(device_to_host, .false.)
219 if (present(u)) call u%copy_from(device_to_host, .false.)
220 if (present(v)) call v%copy_from(device_to_host, .false.)
221 if (present(w)) call w%copy_from(device_to_host, .false.)
222 if (present(u_lag)) call u_lag%copy_from(device_to_host, .false.)
223 if (present(v_lag)) call v_lag%copy_from(device_to_host, .false.)
224 if (present(w_lag)) call w_lag%copy_from(device_to_host, .false.)
225 if (present(u_laglag)) call u_laglag%copy_from(device_to_host, .false.)
226 if (present(v_laglag)) call v_laglag%copy_from(device_to_host, .false.)
227 if (present(w_laglag)) call w_laglag%copy_from(device_to_host, .false.)
228 if (present(acc_xlag)) call acc_xlag%copy_from(device_to_host, .false.)
229 if (present(acc_ylag)) call acc_ylag%copy_from(device_to_host, .false.)
230 if (present(acc_zlag)) call acc_zlag%copy_from(device_to_host, .false.)
231 if (present(acc_xlaglag)) then
232 call acc_xlaglag%copy_from(device_to_host, .false.)
233 end if
234 if (present(acc_ylaglag)) then
235 call acc_ylaglag%copy_from(device_to_host, .false.)
236 end if
237 if (present(acc_zlaglag)) then
238 call acc_zlaglag%copy_from(device_to_host, .false.)
239 end if
240 call device_sync()
242
244 subroutine lpt_periodic_bc_reset(this)
245 class(lpt_periodic_bc_t), intent(inout) :: this
246
247 this%periodic_enabled = .false.
248 this%rotational_periodic_enabled = .false.
249 this%n_periodic_dirs = 0
251 this%rotational_theta_min = 0.0_rp
252 this%rotational_theta_max = 0.0_rp
253 this%rotational_theta_len = 0.0_rp
254 end subroutine lpt_periodic_bc_reset
255
260 subroutine lpt_periodic_bc_init_rotational(this, msh, dm_Xh, coef)
261 class(lpt_periodic_bc_t), intent(inout) :: this
262 type(mesh_t), intent(in) :: msh
263 type(dofmap_t), intent(in) :: dm_Xh
264 type(coef_t), intent(in) :: coef
265 real(kind=rp) :: theta_min
266 real(kind=rp) :: theta_max
267 real(kind=rp) :: pi
268 integer :: ierr
269
270 if (.not. coef%cyclic .or. msh%gdim .lt. 2) return
271
272 pi = acos(-1.0_rp)
273 if (msh%nelv .gt. 0) then
274 theta_min = minval(modulo(atan2(dm_xh%y, dm_xh%x) + &
275 2.0_rp * pi, 2.0_rp * pi))
276 theta_max = maxval(modulo(atan2(dm_xh%y, dm_xh%x) + &
277 2.0_rp * pi, 2.0_rp * pi))
278 else
279 theta_min = huge(0.0_rp)
280 theta_max = -huge(0.0_rp)
281 end if
282
283 call mpi_allreduce(theta_min, this%rotational_theta_min, 1, &
284 mpi_real_precision, mpi_min, neko_comm, ierr)
285 call mpi_allreduce(theta_max, this%rotational_theta_max, 1, &
286 mpi_real_precision, mpi_max, neko_comm, ierr)
287
288 this%rotational_theta_len = this%rotational_theta_max - &
289 this%rotational_theta_min
290 this%rotational_periodic_enabled = &
291 this%rotational_theta_len .gt. lpt_periodic_tol
293
297 class(lpt_periodic_bc_t), intent(inout) :: this
298 type(mesh_t), intent(in) :: msh
299 integer :: i
300 integer :: j
301 integer :: idx
302 integer :: ierr
303 integer :: n_local
304 integer :: n_global
305 integer :: max_local
306 integer :: match_idx
307 integer, allocatable :: counts(:)
308 integer, allocatable :: padded_meta(:)
309 integer, allocatable :: gathered_meta(:)
310 integer, allocatable :: global_meta(:)
311 real(kind=rp), allocatable :: padded_center(:)
312 real(kind=rp), allocatable :: gathered_center(:)
313 real(kind=rp), allocatable :: global_center(:)
314 real(kind=rp) :: src_center(3)
315 real(kind=rp) :: tgt_center(3)
316 real(kind=rp) :: shift(3)
317 real(kind=rp) :: proj_src
318 real(kind=rp) :: proj_tgt
319 real(kind=rp) :: dir(3)
320
321 if (msh%periodic%size .eq. 0) return
322
323 n_local = msh%periodic%size
324 allocate(counts(pe_size))
325 call mpi_allgather(n_local, 1, mpi_integer, counts, 1, mpi_integer, &
326 neko_comm, ierr)
327 n_global = sum(counts)
328 max_local = max(1, maxval(counts))
329
330 allocate(padded_meta(2 * max_local))
331 allocate(padded_center(3 * max_local))
332 padded_meta = 0
333 padded_center = 0.0_rp
334
335 ! collect meta data from periodic facets
336 do i = 1, n_local
337 call lpt_get_periodic_center(msh, i, src_center)
338
339 padded_meta(2 * (i - 1) + 1) = msh%periodic%facet_el(i)%x(1)
340 padded_meta(2 * (i - 1) + 2) = msh%elements( &
341 msh%periodic%facet_el(i)%x(2))%e%id()
342 padded_center(3 * (i - 1) + 1:3 * i) = src_center
343 end do
344
345 ! broadcast meta data to all ranks
346 allocate(gathered_meta(2 * max_local * pe_size))
347 allocate(gathered_center(3 * max_local * pe_size))
348 call mpi_allgather(padded_meta, 2 * max_local, mpi_integer, gathered_meta, &
349 2 * max_local, mpi_integer, neko_comm, ierr)
350 call mpi_allgather(padded_center, 3 * max_local, mpi_real_precision, &
351 gathered_center, 3 * max_local, mpi_real_precision, neko_comm, ierr)
352
353 ! reorganise the data to global arrays of size n_global
354 allocate(global_meta(2 * n_global))
355 allocate(global_center(3 * n_global))
356 idx = 0
357 do i = 1, pe_size
358 if (counts(i) .gt. 0) then
359 global_meta(2 * idx + 1:2 * (idx + counts(i))) = &
360 gathered_meta(2 * max_local * (i - 1) + 1: &
361 2 * max_local * (i - 1) + 2 * counts(i))
362 global_center(3 * idx + 1:3 * (idx + counts(i))) = &
363 gathered_center(3 * max_local * (i - 1) + 1: &
364 3 * max_local * (i - 1) + 3 * counts(i))
365 idx = idx + counts(i)
366 end if
367 end do
368
369 ! cycle through the periodic facets and identify unique periodic directions
370 ! and their extents by matching the facet pairs and comparing their centers
371 do i = 1, msh%periodic%size
372 ! get the center of the facet (averaged over the pair)
373 call lpt_get_periodic_center(msh, i, src_center)
374
375 ! find whether there is a match facet from the global list
376 match_idx = 0
377 do j = 1, n_global
378 if (global_meta(2 * (j - 1) + 1) .eq. msh%periodic%p_facet_el(i)%x(1)&
379 .and. global_meta(2 * (j - 1) + 2) .eq. &
380 msh%periodic%p_facet_el(i)%x(2)) then
381 match_idx = j
382 exit
383 end if
384 end do
385 if (match_idx .eq. 0) cycle
386
387 ! fetch the target facet center and compute the shift
388 tgt_center = global_center(3 * (match_idx - 1) + 1:3 * match_idx)
389 shift = tgt_center - src_center
390 if (norm2(shift) .le. lpt_periodic_tol) cycle
391
392 ! compute the direction and projection
393 dir = shift
394 call lpt_normalize(dir)
395 proj_src = dot_product(src_center, dir)
396 proj_tgt = dot_product(tgt_center, dir)
397 idx = 0
398
399 ! identfy whether the direction is a unique one
400 do j = 1, this%n_periodic_dirs
401 if (abs(dot_product(dir, &
402 lpt_periodic_bc_get_dir(this, j))) .gt. &
403 1.0_rp - 1.0e-6_rp) then
404 idx = j
405 exit
406 end if
407 end do
408
409 if (idx .ne. 0) cycle
410
411 ! if unique, add it to the list of periodic directions
412 ! with its extent and shift
413 if (this%n_periodic_dirs .ge. 3) cycle
414 idx = this%n_periodic_dirs + 1
415 this%n_periodic_dirs = idx
416 call lpt_periodic_bc_set_translational(this, idx, dir, &
417 min(proj_src, proj_tgt), max(proj_src, proj_tgt), shift, &
418 norm2(shift))
419 end do
420
421 deallocate(global_center)
422 deallocate(global_meta)
423 deallocate(gathered_center)
424 deallocate(gathered_meta)
425 deallocate(padded_center)
426 deallocate(padded_meta)
427 deallocate(counts)
428
429 this%periodic_enabled = this%n_periodic_dirs .gt. 0
431
437 subroutine lpt_get_facet_points(msh, el, facet, pts)
438 type(mesh_t), intent(in) :: msh
439 integer, intent(in) :: el
440 integer, intent(in) :: facet
441 real(kind=rp), intent(out) :: pts(3, 4)
442 integer, dimension(4, 6) :: face_nodes = reshape([ &
443 1,5,7,3, &
444 2,6,8,4, &
445 1,2,6,5, &
446 3,4,8,7, &
447 1,2,4,3, &
448 5,6,8,7], [4, 6])
449 integer, dimension(2, 4) :: edge_nodes = reshape([ &
450 1,3, &
451 2,4, &
452 1,2, &
453 3,4], [2, 4])
454 integer :: i
455
456 pts = 0.0_rp
457 if (msh%gdim .eq. 3) then
458 do i = 1, 4
459 pts(:, i) = real(msh%elements(el)%e%pts(face_nodes(i, facet))%p%x, rp)
460 end do
461 else
462 do i = 1, 2
463 pts(:, i) = real(msh%elements(el)%e%pts(edge_nodes(i, facet))%p%x, rp)
464 end do
465 end if
466 end subroutine lpt_get_facet_points
467
472 subroutine lpt_get_periodic_center(msh, i_periodic, pt)
473 type(mesh_t), intent(in) :: msh
474 integer, intent(in) :: i_periodic
475 real(kind=rp), intent(out) :: pt(3)
476 integer :: npts
477 real(kind=rp) :: pts(3, 4)
478
479 npts = merge(4, 2, msh%gdim .eq. 3)
480 call lpt_get_facet_points(msh, msh%periodic%facet_el(i_periodic)%x(2), &
481 msh%periodic%facet_el(i_periodic)%x(1), pts)
482 pt = sum(pts(:, 1:npts), dim = 2) / real(npts, rp)
483 end subroutine lpt_get_periodic_center
484
487 subroutine lpt_normalize(v)
488 real(kind=rp), intent(inout) :: v(3)
489 real(kind=rp) :: vnorm
490
491 vnorm = norm2(v)
492 if (vnorm .gt. lpt_periodic_tol) v = v / vnorm
493 end subroutine lpt_normalize
494
497 class(lpt_periodic_bc_t), intent(inout) :: this
498
499 this%periodic_shift_x1 = 0.0_rp
500 this%periodic_shift_y1 = 0.0_rp
501 this%periodic_shift_z1 = 0.0_rp
502 this%periodic_shift_x2 = 0.0_rp
503 this%periodic_shift_y2 = 0.0_rp
504 this%periodic_shift_z2 = 0.0_rp
505 this%periodic_shift_x3 = 0.0_rp
506 this%periodic_shift_y3 = 0.0_rp
507 this%periodic_shift_z3 = 0.0_rp
508 this%periodic_dir_x1 = 0.0_rp
509 this%periodic_dir_y1 = 0.0_rp
510 this%periodic_dir_z1 = 0.0_rp
511 this%periodic_dir_x2 = 0.0_rp
512 this%periodic_dir_y2 = 0.0_rp
513 this%periodic_dir_z2 = 0.0_rp
514 this%periodic_dir_x3 = 0.0_rp
515 this%periodic_dir_y3 = 0.0_rp
516 this%periodic_dir_z3 = 0.0_rp
517 this%periodic_min1 = 0.0_rp
518 this%periodic_min2 = 0.0_rp
519 this%periodic_min3 = 0.0_rp
520 this%periodic_max1 = 0.0_rp
521 this%periodic_max2 = 0.0_rp
522 this%periodic_max3 = 0.0_rp
523 this%periodic_len1 = 0.0_rp
524 this%periodic_len2 = 0.0_rp
525 this%periodic_len3 = 0.0_rp
527
528 pure function lpt_periodic_bc_get_dir(this, idx) result(dir)
529 class(lpt_periodic_bc_t), intent(in) :: this
530 integer, intent(in) :: idx
531 real(kind=rp) :: dir(3)
532
533 select case (idx)
534 case (1)
535 dir = [this%periodic_dir_x1, this%periodic_dir_y1, &
536 this%periodic_dir_z1]
537 case (2)
538 dir = [this%periodic_dir_x2, this%periodic_dir_y2, &
539 this%periodic_dir_z2]
540 case (3)
541 dir = [this%periodic_dir_x3, this%periodic_dir_y3, &
542 this%periodic_dir_z3]
543 case default
544 dir = 0.0_rp
545 end select
546 end function lpt_periodic_bc_get_dir
547
555 subroutine lpt_periodic_bc_set_translational(this, idx, dir, periodic_min, &
556 periodic_max, shift, periodic_len)
557 class(lpt_periodic_bc_t), intent(inout) :: this
558 integer, intent(in) :: idx
559 real(kind=rp), intent(in) :: dir(3)
560 real(kind=rp), intent(in) :: periodic_min
561 real(kind=rp), intent(in) :: periodic_max
562 real(kind=rp), intent(in) :: shift(3)
563 real(kind=rp), intent(in) :: periodic_len
564
565 select case (idx)
566 case (1)
567 this%periodic_dir_x1 = dir(1)
568 this%periodic_dir_y1 = dir(2)
569 this%periodic_dir_z1 = dir(3)
570 this%periodic_min1 = periodic_min
571 this%periodic_max1 = periodic_max
572 this%periodic_shift_x1 = shift(1)
573 this%periodic_shift_y1 = shift(2)
574 this%periodic_shift_z1 = shift(3)
575 this%periodic_len1 = periodic_len
576 case (2)
577 this%periodic_dir_x2 = dir(1)
578 this%periodic_dir_y2 = dir(2)
579 this%periodic_dir_z2 = dir(3)
580 this%periodic_min2 = periodic_min
581 this%periodic_max2 = periodic_max
582 this%periodic_shift_x2 = shift(1)
583 this%periodic_shift_y2 = shift(2)
584 this%periodic_shift_z2 = shift(3)
585 this%periodic_len2 = periodic_len
586 case (3)
587 this%periodic_dir_x3 = dir(1)
588 this%periodic_dir_y3 = dir(2)
589 this%periodic_dir_z3 = dir(3)
590 this%periodic_min3 = periodic_min
591 this%periodic_max3 = periodic_max
592 this%periodic_shift_x3 = shift(1)
593 this%periodic_shift_y3 = shift(2)
594 this%periodic_shift_z3 = shift(3)
595 this%periodic_len3 = periodic_len
596 end select
598
599end module lpt_periodic_bc
double real
Synchronize a device or stream.
Definition device.F90:119
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:54
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public device_to_host
Definition device.F90:48
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
CPU kernels for LPT periodic boundary-condition wrapping.
subroutine, public lpt_periodic_bc_wrap_translational_cpu(x, y, z, n, periodic_enabled, n_periodic_dirs, periodic_dir_x1, periodic_dir_y1, periodic_dir_z1, periodic_dir_x2, periodic_dir_y2, periodic_dir_z2, periodic_dir_x3, periodic_dir_y3, periodic_dir_z3, periodic_min1, periodic_min2, periodic_min3, periodic_max1, periodic_max2, periodic_max3, periodic_shift_x1, periodic_shift_y1, periodic_shift_z1, periodic_shift_x2, periodic_shift_y2, periodic_shift_z2, periodic_shift_x3, periodic_shift_y3, periodic_shift_z3, periodic_len1, periodic_len2, periodic_len3)
Wrap particle coordinates through translational periodic directions.
real(kind=rp), parameter lpt_periodic_tol
subroutine, public lpt_periodic_bc_wrap_rotational_cpu(x, y, z, n, theta_min, theta_max, theta_len, u, v, w, u_lag, v_lag, w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag)
Wrap particles through a rotational periodic sector on the CPU.
Device dispatch for LPT periodic boundary-condition wrapping.
subroutine, public lpt_periodic_bc_wrap_rotational_device(x, y, z, n, theta_min, theta_max, theta_len, u, v, w, u_lag, v_lag, w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag, strm)
Launch device kernel for rotational periodic wrapping.
subroutine, public lpt_periodic_bc_wrap_translational_device(x, y, z, n, n_periodic_dirs, periodic_dir_x1, periodic_dir_y1, periodic_dir_z1, periodic_dir_x2, periodic_dir_y2, periodic_dir_z2, periodic_dir_x3, periodic_dir_y3, periodic_dir_z3, periodic_min1, periodic_min2, periodic_min3, periodic_max1, periodic_max2, periodic_max3, periodic_shift_x1, periodic_shift_y1, periodic_shift_z1, periodic_shift_x2, periodic_shift_y2, periodic_shift_z2, periodic_shift_x3, periodic_shift_y3, periodic_shift_z3, periodic_len1, periodic_len2, periodic_len3, strm)
Launch device kernel for translational periodic wrapping.
Periodic and cyclic boundary-condition support for LPT.
subroutine lpt_periodic_bc_wrap(this, x, y, z, n, u, v, w, u_lag, v_lag, w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag)
Wrap particle positions and optional vector histories across boundaries.
subroutine lpt_periodic_bc_init_translational(this, msh)
Detect unique translational periodic directions from facet pairs.
subroutine lpt_periodic_bc_set_translational(this, idx, dir, periodic_min, periodic_max, shift, periodic_len)
Store one translational periodic wrapping direction.
subroutine lpt_periodic_bc_reset(this)
Reset all periodic wrapping flags, directions, and extents.
subroutine lpt_periodic_bc_sync_from_device(x, y, z, u, v, w, u_lag, v_lag, w_lag, u_laglag, v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, acc_ylaglag, acc_zlaglag)
Copy wrapped particle coordinates and optional histories back to host.
subroutine lpt_get_periodic_center(msh, i_periodic, pt)
Compute the geometric center of a periodic source facet.
subroutine lpt_get_facet_points(msh, el, facet, pts)
Gather the corner points of a mesh facet.
subroutine lpt_periodic_bc_init_rotational(this, msh, dm_xh, coef)
Detect and initialise rotational periodic wrapping.
pure real(kind=rp) function, dimension(3) lpt_periodic_bc_get_dir(this, idx)
subroutine lpt_periodic_bc_free(this)
Free periodic-boundary wrapping metadata.
subroutine lpt_normalize(v)
Normalise a 3-vector when its norm is above LPT periodic tolerance.
subroutine lpt_periodic_bc_init(this, msh, dm_xh, coef)
Initialise rotational or translational periodic wrapping from the mesh.
subroutine lpt_periodic_bc_clear_translational(this)
Clear translational periodic direction, extent, and shift storage.
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a vector.
Definition vector.f90:34
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
#define max(a, b)
Definition tensor.cu:40