Neko 1.99.5
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
point_interpolator.f90
Go to the documentation of this file.
1! Copyright (c) 2021-2023, 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!
37 use space, only: space_t, gl, gll
38 use num_types, only: rp
39 use point, only: point_t
40 use math, only: abscmp
41 use fast3d, only: fd_weights_full
42 use utils, only: neko_error
43 use device
44 use device_math, only: device_rzero
46 implicit none
47 private
48
55 type, public :: point_interpolator_t
57 type(space_t), pointer :: xh => null()
58 contains
60 procedure, pass(this) :: init => point_interpolator_init
62 procedure, pass(this) :: free => point_interpolator_free
65 procedure, pass(this) :: compute_weights => &
76 generic :: interpolate => point_interpolator_interpolate_scalar, &
81
83
84contains
85
88 subroutine point_interpolator_init(this, Xh)
89 class(point_interpolator_t), intent(inout), target :: this
90 type(space_t), intent(in), target :: Xh
91
92 if ((xh%t .eq. gl) .or. (xh%t .eq. gll)) then
93 else
94 call neko_error('Unsupported interpolation')
95 end if
96
97 this%Xh => xh
98
99 end subroutine point_interpolator_init
100
102 subroutine point_interpolator_free(this)
103 class(point_interpolator_t), intent(inout) :: this
104
105 if (associated(this%Xh)) this%Xh => null()
106
107 end subroutine point_interpolator_free
108
119 subroutine point_interpolator_compute_weights(this, r, s, t, wr, ws, wt)
120 class(point_interpolator_t), intent(inout) :: this
121 real(kind=rp), intent(in) :: r(:), s(:), t(:)
122 real(kind=rp), intent(inout) :: wr(:,:), ws(:,:), wt(:,:)
123
124 integer :: N, i, lx
125 lx = this%Xh%lx
126 n = size(r)
127
128 do i = 1, n
129 call fd_weights_full(r(i), this%Xh%zg(:,1), lx-1, 0, wr(:,i))
130 call fd_weights_full(s(i), this%Xh%zg(:,2), lx-1, 0, ws(:,i))
131 call fd_weights_full(t(i), this%Xh%zg(:,3), lx-1, 0, wt(:,i))
132 end do
133
135
141 function point_interpolator_interpolate_scalar(this, rst, X) result(res)
142 class(point_interpolator_t), intent(in) :: this
143 type(point_t), intent(in) :: rst(:)
144 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
145 real(kind=rp), allocatable :: res(:)
146
147 real(kind=rp) :: hr(this%Xh%lx), hs(this%Xh%ly), ht(this%Xh%lz)
148 integer :: lx,ly,lz, i
149 integer :: n
150 lx = this%Xh%lx
151 ly = this%Xh%ly
152 lz = this%Xh%lz
153
154 n = size(rst)
155 allocate(res(n))
156
157 !
158 ! Compute weights and perform interpolation for the first point
159 !
160 call fd_weights_full(real(rst(1)%x(1), rp), this%Xh%zg(:,1), lx-1, 0, hr)
161 call fd_weights_full(real(rst(1)%x(2), rp), this%Xh%zg(:,2), ly-1, 0, hs)
162 call fd_weights_full(real(rst(1)%x(3), rp), this%Xh%zg(:,3), lz-1, 0, ht)
163
164 ! And interpolate!
165 call triple_tensor_product(res(1),x,lx,hr,hs,ht)
166
167 if (n .eq. 1) return
168
169 !
170 ! Loop through the rest of the points
171 !
172 do i = 2, n
173
174 ! If the coordinates are different, then recompute weights
175 if ( .not. abscmp(rst(i)%x(1), rst(i-1)%x(1)) ) then
176 call fd_weights_full(real(rst(i)%x(1), rp), &
177 this%Xh%zg(:,1), lx-1, 0, hr)
178 end if
179 if ( .not. abscmp(rst(i)%x(2), rst(i-1)%x(2)) ) then
180 call fd_weights_full(real(rst(i)%x(2), rp), &
181 this%Xh%zg(:,2), ly-1, 0, hs)
182 end if
183 if ( .not. abscmp(rst(i)%x(3), rst(i-1)%x(3)) ) then
184 call fd_weights_full(real(rst(i)%x(3), rp), &
185 this%Xh%zg(:,3), lz-1, 0, ht)
186 end if
187
188 ! And interpolate!
189 call triple_tensor_product(res(i), x, lx, hr, hs, ht)
190
191 end do
192
194
203 function point_interpolator_interpolate_vector(this, rst, X, Y, Z) result(res)
204 class(point_interpolator_t), intent(in) :: this
205 type(point_t), intent(in) :: rst(:)
206 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
207 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
208 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
209
210 type(point_t), allocatable :: res(:)
211 real(kind=rp), allocatable :: tmp(:,:)
212 real(kind=rp) :: hr(this%Xh%lx), hs(this%Xh%ly), ht(this%Xh%lz)
213 integer :: lx,ly,lz, i
214 integer :: n
215 lx = this%Xh%lx
216 ly = this%Xh%ly
217 lz = this%Xh%lz
218
219 n = size(rst)
220 allocate(res(n))
221 allocate(tmp(3, n))
222
223 !
224 ! Compute weights and perform interpolation for the first point
225 !
226 call fd_weights_full(real(rst(1)%x(1), rp), this%Xh%zg(:,1), lx-1, 0, hr)
227 call fd_weights_full(real(rst(1)%x(2), rp), this%Xh%zg(:,2), ly-1, 0, hs)
228 call fd_weights_full(real(rst(1)%x(3), rp), this%Xh%zg(:,3), lz-1, 0, ht)
229
230 ! And interpolate!
231 call triple_tensor_product(tmp(:,1), x, y, z, lx, hr, hs, ht)
232
233 if (n .eq. 1) then
234 res(1)%x = tmp(:, 1)
235 return
236 end if
237
238
239 !
240 ! Loop through the rest of the points
241 !
242 do i = 2, n
243
244 ! If the coordinates are different, then recompute weights
245 if ( .not. abscmp(rst(i)%x(1), rst(i-1)%x(1)) ) then
246 call fd_weights_full(real(rst(i)%x(1), rp), &
247 this%Xh%zg(:,1), lx-1, 0, hr)
248 end if
249 if ( .not. abscmp(rst(i)%x(2), rst(i-1)%x(2)) ) then
250 call fd_weights_full(real(rst(i)%x(2), rp), &
251 this%Xh%zg(:,2), ly-1, 0, hs)
252 end if
253 if ( .not. abscmp(rst(i)%x(3), rst(i-1)%x(3)) ) then
254 call fd_weights_full(real(rst(i)%x(3), rp), &
255 this%Xh%zg(:,3), lz-1, 0, ht)
256 end if
257
258 ! And interpolate!
259 call triple_tensor_product(tmp(:,i), x, y, z, lx, hr, hs, ht)
260 end do
261
262 ! Cast result to point_t dp
263 do i = 1, n
264 res(i)%x = tmp(:,i)
265 end do
266
268
279 rst, X, Y, Z) result(res)
280 class(point_interpolator_t), intent(in) :: this
281 real(kind=rp), intent(inout) :: jac(3,3)
282 type(point_t), intent(in) :: rst
283 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
284 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
285 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
286
287 real(kind=rp) :: hr(this%Xh%lx, 2), hs(this%Xh%ly, 2), ht(this%Xh%lz, 2)
288 type(point_t) :: res
289 real(kind=rp) :: tmp(3)
290
291 integer :: lx,ly,lz, i
292 lx = this%Xh%lx
293 ly = this%Xh%ly
294 lz = this%Xh%lz
295
296 !
297 ! Compute weights
298 !
299 call fd_weights_full(real(rst%x(1), rp), this%Xh%zg(:,1), lx-1, 1, hr)
300 call fd_weights_full(real(rst%x(2), rp), this%Xh%zg(:,2), ly-1, 1, hs)
301 call fd_weights_full(real(rst%x(3), rp),this%Xh%zg(:,3), lz-1, 1, ht)
302
303 !
304 ! Interpolate
305 !
306 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,1), ht(:,1))
307 res%x = dble(tmp)! Cast from rp -> point_t dp
308
309 !
310 ! Build jacobian
311 !
312
313 ! d(x,y,z)/dr
314 call triple_tensor_product(tmp, x,y,z, lx, hr(:,2), hs(:,1), ht(:,1))
315 jac(1,:) = tmp
316
317 ! d(x,y,z)/ds
318 call triple_tensor_product(tmp, x,y,z, lx, hr(:,1), hs(:,2), ht(:,1))
319 jac(2,:) = tmp
320
321 ! d(x,y,z)/dt
322 call triple_tensor_product(tmp, x,y,z, lx, hr(:,1), hs(:,1), ht(:,2))
323 jac(3,:) = tmp
324
326
333 function point_interpolator_interpolate_jacobian(this, rst, X,Y,Z) result(jac)
334 class(point_interpolator_t), intent(in) :: this
335 type(point_t), intent(in) :: rst
336 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
337 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
338 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
339
340 real(kind=rp) :: jac(3,3)
341 real(kind=rp) :: tmp(3)
342
343 real(kind=rp) :: hr(this%Xh%lx, 2), hs(this%Xh%ly, 2), ht(this%Xh%lz, 2)
344 integer :: lx, ly, lz
345 lx = this%Xh%lx
346 ly = this%Xh%ly
347 lz = this%Xh%lz
348
349 ! Weights
350 call fd_weights_full(real(rst%x(1), rp), this%Xh%zg(:,1), lx-1, 1, hr)
351 call fd_weights_full(real(rst%x(2), rp), this%Xh%zg(:,2), ly-1, 1, hs)
352 call fd_weights_full(real(rst%x(3), rp), this%Xh%zg(:,3), lz-1, 1, ht)
353
354 ! d(x,y,z)/dr
355 call triple_tensor_product(tmp, x, y, z, lx, hr(:,2), hs(:,1), ht(:,1))
356 jac(1,:) = tmp
357
358 ! d(x,y,z)/ds
359 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,2), ht(:,1))
360 jac(2,:) = tmp
361
362 ! d(x,y,z)/dt
363 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,1), ht(:,2))
364 jac(3,:) = tmp
365
367
368end module point_interpolator
double real
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
Device abstraction, common interface for various accelerators.
Definition device.F90:34
Fast diagonalization methods from NEKTON.
Definition fast3d.f90:61
subroutine, public fd_weights_full(xi, x, n, m, c)
Compute finite-difference stencil weights for evaluating derivatives up to order at a point.
Definition fast3d.f90:106
Definition math.f90:60
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Routines to interpolate fields on a given element on a point in that element with given r,...
real(kind=rp) function, dimension(:), allocatable point_interpolator_interpolate_scalar(this, rst, x)
Interpolates a scalar field on a set of points . Returns a vector of N coordinates .
subroutine point_interpolator_free(this)
Free pointers.
real(kind=rp) function, dimension(3, 3) point_interpolator_interpolate_jacobian(this, rst, x, y, z)
Constructs the Jacobian, returns a 3-by-3 array where .
type(point_t) function point_interpolator_interpolate_vector_jacobian(this, jac, rst, x, y, z)
Interpolates a vector field and constructs the Jacobian at a point . Returns a vector .
subroutine point_interpolator_init(this, xh)
Initialization of point interpolation.
type(point_t) function, dimension(:), allocatable point_interpolator_interpolate_vector(this, rst, x, y, z)
Interpolates a vector field on a set of points . Returns an array of N points .
subroutine point_interpolator_compute_weights(this, r, s, t, wr, ws, wt)
Computes interpolation weights for a list of points.
Implements a point.
Definition point.f90:35
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:49
integer, parameter, public gl
Definition space.f90:49
Tensor operations.
Definition tensor.f90:61
Utilities.
Definition utils.f90:35
A point in with coordinates .
Definition point.f90:43
Field interpolator to arbitrary points within an element. Tailored for experimentation,...
The function space for the SEM solution fields.
Definition space.f90:63