Neko 1.99.6
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_math, only : device_rzero
45 implicit none
46 private
47
54 type, public :: point_interpolator_t
56 type(space_t), pointer :: xh => null()
57 contains
59 procedure, pass(this) :: init => point_interpolator_init
61 procedure, pass(this) :: free => point_interpolator_free
64 procedure, pass(this) :: compute_weights => &
75 generic :: interpolate => point_interpolator_interpolate_scalar, &
80
82
83contains
84
87 subroutine point_interpolator_init(this, Xh)
88 class(point_interpolator_t), intent(inout), target :: this
89 type(space_t), intent(in), target :: Xh
90
91 if ((xh%t .eq. gl) .or. (xh%t .eq. gll)) then
92 else
93 call neko_error('Unsupported interpolation')
94 end if
95
96 this%Xh => xh
97
98 end subroutine point_interpolator_init
99
101 subroutine point_interpolator_free(this)
102 class(point_interpolator_t), intent(inout) :: this
103
104 if (associated(this%Xh)) this%Xh => null()
105
106 end subroutine point_interpolator_free
107
118 subroutine point_interpolator_compute_weights(this, r, s, t, wr, ws, wt)
119 class(point_interpolator_t), intent(inout) :: this
120 real(kind=rp), intent(in) :: r(:), s(:), t(:)
121 real(kind=rp), intent(inout) :: wr(:,:), ws(:,:), wt(:,:)
122
123 integer :: N, i, lx
124 lx = this%Xh%lx
125 n = size(r)
126
127 do i = 1, n
128 call fd_weights_full(r(i), this%Xh%zg(:,1), lx-1, 0, wr(:,i))
129 call fd_weights_full(s(i), this%Xh%zg(:,2), lx-1, 0, ws(:,i))
130 call fd_weights_full(t(i), this%Xh%zg(:,3), lx-1, 0, wt(:,i))
131 end do
132
134
140 function point_interpolator_interpolate_scalar(this, rst, X) result(res)
141 class(point_interpolator_t), intent(in) :: this
142 type(point_t), intent(in) :: rst(:)
143 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
144 real(kind=rp), allocatable :: res(:)
145
146 real(kind=rp) :: hr(this%Xh%lx), hs(this%Xh%ly), ht(this%Xh%lz)
147 integer :: lx, ly, lz, i
148 integer :: n
149 lx = this%Xh%lx
150 ly = this%Xh%ly
151 lz = this%Xh%lz
152
153 n = size(rst)
154 allocate(res(n))
155
156 !
157 ! Compute weights and perform interpolation for the first point
158 !
159 call fd_weights_full(real(rst(1)%x(1), rp), this%Xh%zg(:,1), lx-1, 0, hr)
160 call fd_weights_full(real(rst(1)%x(2), rp), this%Xh%zg(:,2), ly-1, 0, hs)
161 call fd_weights_full(real(rst(1)%x(3), rp), this%Xh%zg(:,3), lz-1, 0, ht)
162
163 ! And interpolate!
164 call triple_tensor_product(res(1),x,lx,hr,hs,ht)
165
166 if (n .eq. 1) return
167
168 !
169 ! Loop through the rest of the points
170 !
171 do i = 2, n
172
173 ! If the coordinates are different, then recompute weights
174 if ( .not. abscmp(rst(i)%x(1), rst(i-1)%x(1)) ) then
175 call fd_weights_full(real(rst(i)%x(1), rp), &
176 this%Xh%zg(:,1), lx-1, 0, hr)
177 end if
178 if ( .not. abscmp(rst(i)%x(2), rst(i-1)%x(2)) ) then
179 call fd_weights_full(real(rst(i)%x(2), rp), &
180 this%Xh%zg(:,2), ly-1, 0, hs)
181 end if
182 if ( .not. abscmp(rst(i)%x(3), rst(i-1)%x(3)) ) then
183 call fd_weights_full(real(rst(i)%x(3), rp), &
184 this%Xh%zg(:,3), lz-1, 0, ht)
185 end if
186
187 ! And interpolate!
188 call triple_tensor_product(res(i), x, lx, hr, hs, ht)
189
190 end do
191
193
202 function point_interpolator_interpolate_vector(this, rst, X, Y, Z) result(res)
203 class(point_interpolator_t), intent(in) :: this
204 type(point_t), intent(in) :: rst(:)
205 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
206 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
207 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
208
209 type(point_t), allocatable :: res(:)
210 real(kind=rp), allocatable :: tmp(:,:)
211 real(kind=rp) :: hr(this%Xh%lx), hs(this%Xh%ly), ht(this%Xh%lz)
212 integer :: lx,ly,lz, i
213 integer :: n
214 lx = this%Xh%lx
215 ly = this%Xh%ly
216 lz = this%Xh%lz
217
218 n = size(rst)
219 allocate(res(n))
220 allocate(tmp(3, n))
221
222 !
223 ! Compute weights and perform interpolation for the first point
224 !
225 call fd_weights_full(real(rst(1)%x(1), rp), this%Xh%zg(:,1), lx-1, 0, hr)
226 call fd_weights_full(real(rst(1)%x(2), rp), this%Xh%zg(:,2), ly-1, 0, hs)
227 call fd_weights_full(real(rst(1)%x(3), rp), this%Xh%zg(:,3), lz-1, 0, ht)
228
229 ! And interpolate!
230 call triple_tensor_product(tmp(:,1), x, y, z, lx, hr, hs, ht)
231
232 if (n .eq. 1) then
233 res(1)%x = tmp(:, 1)
234 return
235 end if
236
237
238 !
239 ! Loop through the rest of the points
240 !
241 do i = 2, n
242
243 ! If the coordinates are different, then recompute weights
244 if ( .not. abscmp(rst(i)%x(1), rst(i-1)%x(1)) ) then
245 call fd_weights_full(real(rst(i)%x(1), rp), &
246 this%Xh%zg(:,1), lx-1, 0, hr)
247 end if
248 if ( .not. abscmp(rst(i)%x(2), rst(i-1)%x(2)) ) then
249 call fd_weights_full(real(rst(i)%x(2), rp), &
250 this%Xh%zg(:,2), ly-1, 0, hs)
251 end if
252 if ( .not. abscmp(rst(i)%x(3), rst(i-1)%x(3)) ) then
253 call fd_weights_full(real(rst(i)%x(3), rp), &
254 this%Xh%zg(:,3), lz-1, 0, ht)
255 end if
256
257 ! And interpolate!
258 call triple_tensor_product(tmp(:,i), x, y, z, lx, hr, hs, ht)
259 end do
260
261 ! Cast result to point_t dp
262 do i = 1, n
263 res(i)%x = tmp(:,i)
264 end do
265
267
278 rst, X, Y, Z) result(res)
279 class(point_interpolator_t), intent(in) :: this
280 real(kind=rp), intent(inout) :: jac(3,3)
281 type(point_t), intent(in) :: rst
282 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
283 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
284 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
285
286 real(kind=rp) :: hr(this%Xh%lx, 2), hs(this%Xh%ly, 2), ht(this%Xh%lz, 2)
287 type(point_t) :: res
288 real(kind=rp) :: tmp(3)
289
290 integer :: lx,ly,lz, i
291 lx = this%Xh%lx
292 ly = this%Xh%ly
293 lz = this%Xh%lz
294
295 !
296 ! Compute weights
297 !
298 call fd_weights_full(real(rst%x(1), rp), this%Xh%zg(:,1), lx-1, 1, hr)
299 call fd_weights_full(real(rst%x(2), rp), this%Xh%zg(:,2), ly-1, 1, hs)
300 call fd_weights_full(real(rst%x(3), rp),this%Xh%zg(:,3), lz-1, 1, ht)
301
302 !
303 ! Interpolate
304 !
305 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,1), ht(:,1))
306 res%x = dble(tmp)! Cast from rp -> point_t dp
307
308 !
309 ! Build jacobian
310 !
311
312 ! d(x,y,z)/dr
313 call triple_tensor_product(tmp, x,y,z, lx, hr(:,2), hs(:,1), ht(:,1))
314 jac(1,:) = tmp
315
316 ! d(x,y,z)/ds
317 call triple_tensor_product(tmp, x,y,z, lx, hr(:,1), hs(:,2), ht(:,1))
318 jac(2,:) = tmp
319
320 ! d(x,y,z)/dt
321 call triple_tensor_product(tmp, x,y,z, lx, hr(:,1), hs(:,1), ht(:,2))
322 jac(3,:) = tmp
323
325
332 function point_interpolator_interpolate_jacobian(this, rst, X,Y,Z) result(jac)
333 class(point_interpolator_t), intent(in) :: this
334 type(point_t), intent(in) :: rst
335 real(kind=rp), intent(inout) :: x(this%Xh%lx, this%Xh%ly, this%Xh%lz)
336 real(kind=rp), intent(inout) :: y(this%Xh%lx, this%Xh%ly, this%Xh%lz)
337 real(kind=rp), intent(inout) :: z(this%Xh%lx, this%Xh%ly, this%Xh%lz)
338
339 real(kind=rp) :: jac(3,3)
340 real(kind=rp) :: tmp(3)
341
342 real(kind=rp) :: hr(this%Xh%lx, 2), hs(this%Xh%ly, 2), ht(this%Xh%lz, 2)
343 integer :: lx, ly, lz
344 lx = this%Xh%lx
345 ly = this%Xh%ly
346 lz = this%Xh%lz
347
348 ! Weights
349 call fd_weights_full(real(rst%x(1), rp), this%Xh%zg(:,1), lx-1, 1, hr)
350 call fd_weights_full(real(rst%x(2), rp), this%Xh%zg(:,2), ly-1, 1, hs)
351 call fd_weights_full(real(rst%x(3), rp), this%Xh%zg(:,3), lz-1, 1, ht)
352
353 ! d(x,y,z)/dr
354 call triple_tensor_product(tmp, x, y, z, lx, hr(:,2), hs(:,1), ht(:,1))
355 jac(1,:) = tmp
356
357 ! d(x,y,z)/ds
358 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,2), ht(:,1))
359 jac(2,:) = tmp
360
361 ! d(x,y,z)/dt
362 call triple_tensor_product(tmp, x, y, z, lx, hr(:,1), hs(:,1), ht(:,2))
363 jac(3,:) = tmp
364
366
367end module point_interpolator
double real
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
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:50
integer, parameter, public gl
Definition space.f90:50
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:64