Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
lpt_periodic_bc_cpu.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
36 use vector, only : vector_t
37 implicit none
38 private
39
40 real(kind=rp), parameter :: lpt_periodic_tol = 1.0e-8_rp
41
44
45contains
46
55 subroutine lpt_periodic_bc_wrap_rotational_cpu(x, y, z, n, theta_min, &
56 theta_max, theta_len, u, v, w, u_lag, v_lag, w_lag, u_laglag, &
57 v_laglag, w_laglag, acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, &
58 acc_ylaglag, acc_zlaglag)
59 type(vector_t), intent(inout) :: x, y, z
60 integer, intent(in) :: n
61 real(kind=rp), intent(in) :: theta_min
62 real(kind=rp), intent(in) :: theta_max
63 real(kind=rp), intent(in) :: theta_len
64 type(vector_t), intent(inout), optional :: u, v, w
65 type(vector_t), intent(inout), optional :: u_lag, v_lag, w_lag
66 type(vector_t), intent(inout), optional :: u_laglag, v_laglag, w_laglag
67 type(vector_t), intent(inout), optional :: acc_xlag, acc_ylag, acc_zlag
68 type(vector_t), intent(inout), optional :: acc_xlaglag
69 type(vector_t), intent(inout), optional :: acc_ylaglag
70 type(vector_t), intent(inout), optional :: acc_zlaglag
71 integer :: i
72 real(kind=rp) :: radius
73 real(kind=rp) :: theta_old
74 real(kind=rp) :: theta
75 real(kind=rp) :: dtheta
76 real(kind=rp) :: pi
77
78 pi = acos(-1.0_rp)
79 do i = 1, n
80 radius = sqrt(x%x(i) * x%x(i) + y%x(i) * y%x(i))
81 theta_old = modulo(atan2(y%x(i), x%x(i)) + 2.0_rp * pi, &
82 2.0_rp * pi)
83 theta = theta_old
84
85 do while (theta .lt. theta_min - lpt_periodic_tol)
86 theta = theta + theta_len
87 end do
88
89 do while (theta .gt. theta_max + lpt_periodic_tol)
90 theta = theta - theta_len
91 end do
92
93 dtheta = theta - theta_old
94 x%x(i) = radius * cos(theta)
95 y%x(i) = radius * sin(theta)
96 if (abs(dtheta) .le. lpt_periodic_tol) cycle
97
98 if (present(u) .and. present(v)) &
99 call lpt_rotate_xy(u%x(i), v%x(i), dtheta)
100 if (present(u_lag) .and. present(v_lag)) &
101 call lpt_rotate_xy(u_lag%x(i), v_lag%x(i), dtheta)
102 if (present(u_laglag) .and. present(v_laglag)) &
103 call lpt_rotate_xy(u_laglag%x(i), v_laglag%x(i), dtheta)
104 if (present(acc_xlag) .and. present(acc_ylag)) &
105 call lpt_rotate_xy(acc_xlag%x(i), acc_ylag%x(i), dtheta)
106 if (present(acc_xlaglag) .and. present(acc_ylaglag)) &
107 call lpt_rotate_xy(acc_xlaglag%x(i), acc_ylaglag%x(i), dtheta)
108 end do
110
117 periodic_enabled, n_periodic_dirs, periodic_dir_x1, periodic_dir_y1, &
118 periodic_dir_z1, periodic_dir_x2, periodic_dir_y2, periodic_dir_z2, &
119 periodic_dir_x3, periodic_dir_y3, periodic_dir_z3, periodic_min1, &
120 periodic_min2, periodic_min3, periodic_max1, periodic_max2, &
121 periodic_max3, periodic_shift_x1, periodic_shift_y1, &
122 periodic_shift_z1, periodic_shift_x2, periodic_shift_y2, &
123 periodic_shift_z2, periodic_shift_x3, periodic_shift_y3, &
124 periodic_shift_z3, periodic_len1, periodic_len2, periodic_len3)
125 type(vector_t), intent(inout) :: x, y, z
126 integer, intent(in) :: n
127 logical, intent(in) :: periodic_enabled
128 integer, intent(in) :: n_periodic_dirs
129 real(kind=rp), intent(in) :: periodic_dir_x1, periodic_dir_y1
130 real(kind=rp), intent(in) :: periodic_dir_z1, periodic_dir_x2
131 real(kind=rp), intent(in) :: periodic_dir_y2, periodic_dir_z2
132 real(kind=rp), intent(in) :: periodic_dir_x3, periodic_dir_y3
133 real(kind=rp), intent(in) :: periodic_dir_z3
134 real(kind=rp), intent(in) :: periodic_min1, periodic_min2, periodic_min3
135 real(kind=rp), intent(in) :: periodic_max1, periodic_max2, periodic_max3
136 real(kind=rp), intent(in) :: periodic_shift_x1, periodic_shift_y1
137 real(kind=rp), intent(in) :: periodic_shift_z1, periodic_shift_x2
138 real(kind=rp), intent(in) :: periodic_shift_y2, periodic_shift_z2
139 real(kind=rp), intent(in) :: periodic_shift_x3, periodic_shift_y3
140 real(kind=rp), intent(in) :: periodic_shift_z3
141 real(kind=rp), intent(in) :: periodic_len1, periodic_len2, periodic_len3
142 integer :: i
143 integer :: j
144 real(kind=rp) :: point(3)
145 real(kind=rp) :: dir(3)
146 real(kind=rp) :: shift(3)
147 real(kind=rp) :: coord
148 real(kind=rp) :: periodic_min
149 real(kind=rp) :: periodic_max
150 real(kind=rp) :: periodic_len
151
152 if (.not. periodic_enabled) return
153
154 do i = 1, n
155 point = [x%x(i), y%x(i), z%x(i)]
156 do j = 1, n_periodic_dirs
158 periodic_dir_x1, periodic_dir_y1, periodic_dir_z1, &
159 periodic_dir_x2, periodic_dir_y2, periodic_dir_z2, &
160 periodic_dir_x3, periodic_dir_y3, periodic_dir_z3, &
161 periodic_min1, periodic_min2, periodic_min3, periodic_max1, &
162 periodic_max2, periodic_max3, periodic_shift_x1, &
163 periodic_shift_y1, periodic_shift_z1, periodic_shift_x2, &
164 periodic_shift_y2, periodic_shift_z2, periodic_shift_x3, &
165 periodic_shift_y3, periodic_shift_z3, periodic_len1, &
166 periodic_len2, periodic_len3, dir, periodic_min, &
167 periodic_max, shift, periodic_len)
168
169 coord = dot_product(point, dir)
170
171 do while (coord .lt. periodic_min - lpt_periodic_tol)
172 point = point + shift
173 coord = coord + periodic_len
174 end do
175
176 do while (coord .gt. periodic_max + lpt_periodic_tol)
177 point = point - shift
178 coord = coord - periodic_len
179 end do
180 end do
181 x%x(i) = point(1)
182 y%x(i) = point(2)
183 z%x(i) = point(3)
184 end do
186
191 subroutine lpt_rotate_xy(x, y, theta)
192 real(kind=rp), intent(inout) :: x
193 real(kind=rp), intent(inout) :: y
194 real(kind=rp), intent(in) :: theta
195 real(kind=rp) :: x_old
196 real(kind=rp) :: y_old
197 real(kind=rp) :: cos_theta
198 real(kind=rp) :: sin_theta
199
200 x_old = x
201 y_old = y
202 cos_theta = cos(theta)
203 sin_theta = sin(theta)
204
205 x = cos_theta * x_old - sin_theta * y_old
206 y = sin_theta * x_old + cos_theta * y_old
207 end subroutine lpt_rotate_xy
208
217 periodic_dir_x1, periodic_dir_y1, periodic_dir_z1, periodic_dir_x2, &
218 periodic_dir_y2, periodic_dir_z2, periodic_dir_x3, periodic_dir_y3, &
219 periodic_dir_z3, periodic_min1, periodic_min2, periodic_min3, &
220 periodic_max1, periodic_max2, periodic_max3, periodic_shift_x1, &
221 periodic_shift_y1, periodic_shift_z1, periodic_shift_x2, &
222 periodic_shift_y2, periodic_shift_z2, periodic_shift_x3, &
223 periodic_shift_y3, periodic_shift_z3, periodic_len1, periodic_len2, &
224 periodic_len3, dir, periodic_min, periodic_max, shift, periodic_len)
225 integer, intent(in) :: idx
226 real(kind=rp), intent(in) :: periodic_dir_x1, periodic_dir_y1
227 real(kind=rp), intent(in) :: periodic_dir_z1, periodic_dir_x2
228 real(kind=rp), intent(in) :: periodic_dir_y2, periodic_dir_z2
229 real(kind=rp), intent(in) :: periodic_dir_x3, periodic_dir_y3
230 real(kind=rp), intent(in) :: periodic_dir_z3
231 real(kind=rp), intent(in) :: periodic_min1, periodic_min2, periodic_min3
232 real(kind=rp), intent(in) :: periodic_max1, periodic_max2, periodic_max3
233 real(kind=rp), intent(in) :: periodic_shift_x1, periodic_shift_y1
234 real(kind=rp), intent(in) :: periodic_shift_z1, periodic_shift_x2
235 real(kind=rp), intent(in) :: periodic_shift_y2, periodic_shift_z2
236 real(kind=rp), intent(in) :: periodic_shift_x3, periodic_shift_y3
237 real(kind=rp), intent(in) :: periodic_shift_z3
238 real(kind=rp), intent(in) :: periodic_len1, periodic_len2, periodic_len3
239 real(kind=rp), intent(out) :: dir(3)
240 real(kind=rp), intent(out) :: periodic_min
241 real(kind=rp), intent(out) :: periodic_max
242 real(kind=rp), intent(out) :: shift(3)
243 real(kind=rp), intent(out) :: periodic_len
244
245 select case (idx)
246 case (1)
247 dir = [periodic_dir_x1, periodic_dir_y1, periodic_dir_z1]
248 periodic_min = periodic_min1
249 periodic_max = periodic_max1
250 shift = [periodic_shift_x1, periodic_shift_y1, periodic_shift_z1]
251 periodic_len = periodic_len1
252 case (2)
253 dir = [periodic_dir_x2, periodic_dir_y2, periodic_dir_z2]
254 periodic_min = periodic_min2
255 periodic_max = periodic_max2
256 shift = [periodic_shift_x2, periodic_shift_y2, periodic_shift_z2]
257 periodic_len = periodic_len2
258 case (3)
259 dir = [periodic_dir_x3, periodic_dir_y3, periodic_dir_z3]
260 periodic_min = periodic_min3
261 periodic_max = periodic_max3
262 shift = [periodic_shift_x3, periodic_shift_y3, periodic_shift_z3]
263 periodic_len = periodic_len3
264 case default
265 dir = 0.0_rp
266 periodic_min = 0.0_rp
267 periodic_max = 0.0_rp
268 shift = 0.0_rp
269 periodic_len = 0.0_rp
270 end select
272
273end module lpt_periodic_bc_cpu
CPU kernels for LPT periodic boundary-condition wrapping.
pure subroutine lpt_periodic_bc_get_translational_slot(idx, 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, dir, periodic_min, periodic_max, shift, periodic_len)
Extract one translational periodic slot from scalar storage.
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.
subroutine lpt_rotate_xy(x, y, theta)
Rotate a two-component vector in the x-y plane.
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements a point.
Definition point.f90:35
Defines a vector.
Definition vector.f90:34