70 logical :: all_points_local = .false.
74 logical :: gs_init = .false.
80 real(kind=
rp),
allocatable :: xyz(:,:)
82 integer,
allocatable :: proc_owner(:)
84 integer,
allocatable :: el_owner(:)
85 type(c_ptr) :: el_owner_d = c_null_ptr
88 real(kind=
rp),
allocatable :: rst(:,:)
91 real(kind=
rp),
allocatable :: dist2(:)
93 integer,
allocatable :: error_code(:)
95 real(kind=
rp) :: tol = 5d-13
104 procedure, pass(this) :: find_points_and_redist => &
109 procedure, pass(this) :: find_points_coords => &
112 generic :: find_points => find_points_xyz, find_points_coords
117 generic :: init => init_dof, init_xyz
150 real(kind=
rp),
intent(in),
target :: x(:)
151 real(kind=
rp),
intent(in),
target :: y(:)
152 real(kind=
rp),
intent(in),
target :: z(:)
153 integer,
intent(in) :: gdim
154 integer,
intent(in) :: nelv
155 type(
space_t),
intent(in),
target :: Xh
156 real(kind=
rp),
intent(in),
optional :: tol
157 integer :: lx, ly, lz, max_pts_per_iter
167 if (
present(tol)) this%tol = tol
170 max_pts_per_iter = 128
175 call fgslib_findpts_setup(this%gs_handle, &
178 this%x%ptr, this%y%ptr, this%z%ptr, &
182 lx*ly*lz*nelv, lx*ly*lz*nelv, &
183 max_pts_per_iter, this%tol)
184 this%gs_init = .true.
186 call neko_error(
'Neko needs to be built with GSLIB support')
239 real(kind=
rp) :: xdiff, ydiff, zdiff
240 character(len=8000) :: log_buf
241 real(kind=
rp),
allocatable :: x_check(:)
242 real(kind=
rp),
allocatable :: y_check(:)
243 real(kind=
rp),
allocatable :: z_check(:)
251 call fgslib_findpts(this%gs_handle, &
252 this%error_code, 1, &
253 this%proc_owner, 1, &
255 this%rst, this%gdim, &
257 this%xyz(1,1), this%gdim, &
258 this%xyz(2,1), this%gdim, &
259 this%xyz(3,1), this%gdim, this%n_points)
261 do i = 1 , this%n_points
266 if (this%error_code(i) .eq. 1)
then
267 if (this%dist2(i) .gt. this%tol)
then
268 write(*,*)
'Point with coords: ',&
272 'Did not converge to tol. Absolute differences squared: ',&
273 this%dist2(i),
'PE rank',
pe_rank
277 if (this%error_code(i) .eq. 2) &
278 write(*,*)
'Point with coords: ',&
279 this%xyz(1,i), this%xyz(2,i), this%xyz(3,i),&
280 'Outside the mesh!',&
281 ' Interpolation on these points will return 0.0. dist2: ', &
283 'el_owner, rst coords, pe: ',&
284 this%el_owner(i), this%rst(1,i), this%rst(2,i), &
289 allocate(x_check(this%n_points))
290 allocate(y_check(this%n_points))
291 allocate(z_check(this%n_points))
293 call fgslib_findpts_eval(this%gs_handle, x_check, &
294 1, this%error_code, 1, &
295 this%proc_owner, 1, this%el_owner, 1, &
296 this%rst, this%gdim, &
297 this%n_points, this%x%ptr)
299 call fgslib_findpts_eval(this%gs_handle, y_check, &
300 1, this%error_code, 1, &
301 this%proc_owner, 1, this%el_owner, 1, &
302 this%rst, this%gdim, &
303 this%n_points, this%y%ptr)
305 call fgslib_findpts_eval(this%gs_handle, z_check, &
306 1, this%error_code, 1, &
307 this%proc_owner, 1, this%el_owner, 1, &
308 this%rst, this%gdim, &
309 this%n_points, this%z%ptr)
311 do i = 1 , this%n_points
317 xdiff = (x_check(i)-this%xyz(1,i))**2
318 if ( xdiff .gt. this%tol) isdiff = .true.
319 ydiff = (y_check(i)-this%xyz(2,i))**2
320 if ( ydiff .gt. this%tol) isdiff = .true.
321 zdiff = (z_check(i)-this%xyz(3,i))**2
322 if ( zdiff .gt. this%tol) isdiff = .true.
325 write(*,*)
'Points with coords: ', &
326 this%xyz(1, i), this%xyz(2, i), this%xyz(3, i), &
327 'Differ from interpolated coords: ', &
328 x_check(i), y_check(i), z_check(i), &
329 'Distance squared: ', &
339 if (neko_bcknd_device .eq. 1)
then
340 call device_memcpy(this%el_owner, this%el_owner_d, &
341 this%n_points, host_to_device, sync = .true.)
344 call neko_error(
'Neko needs to be built with GSLIB support')
366 real(kind=
rp) :: x(n_points,1,1,1)
367 real(kind=
rp) :: y(n_points,1,1,1)
368 real(kind=
rp) :: z(n_points,1,1,1)
371 call this%free_points()
373 this%n_points = n_points
378 this%xyz(1, i) = x(i,1,1,1)
379 this%xyz(2, i) = y(i,1,1,1)
380 this%xyz(3, i) = z(i,1,1,1)
390 allocate(this%xyz(3, this%n_points))
391 allocate(this%rst(3, this%n_points))
392 allocate(this%proc_owner(this%n_points))
393 allocate(this%el_owner(this%n_points))
394 allocate(this%dist2(this%n_points))
395 allocate(this%error_code(this%n_points))
397 if (neko_bcknd_device .eq. 1) &
398 call device_map(this%el_owner, this%el_owner_d, this%n_points)
445 integer,
intent(inout) :: n_points
447 real(kind=
rp),
allocatable,
intent(inout) :: xyz(:,:)
451 call this%free_points()
453 this%n_points = n_points
457 call copy(this%xyz, xyz, 3 * n_points)
464 do i = 1, this%n_points
465 if (this%proc_owner(i) .ne.
pe_rank)
then
466 write(*,*)
'Redistribution failed on rank: ',
pe_rank, &
467 'for point with coord: ', &
468 this%xyz(1, i), this%xyz(2, i), this%xyz(3, i)
473 n_points = this%n_points
474 if (
allocated(xyz))
then
477 allocate(xyz(3, n_points))
478 call copy(xyz, this%xyz, 3*n_points)
480 call this%local_interp%init(this%Xh, this%rst(1,:),&
481 this%rst(2,:), this%rst(3,:), n_points)
482 this%all_points_local = .true.
489 integer,
allocatable :: n_points_per_pe(:)
490 integer,
allocatable :: n_points_from_pe(:)
491 integer,
allocatable :: n_point_offset_from_pe(:)
492 real(kind=
rp),
allocatable :: xyz_send_to_pe(:,:)
493 real(kind=
rp),
allocatable :: new_xyz(:,:)
494 integer :: i, j, k, ierr, n_new_points, max_n_points_to_send
498 allocate(n_points_per_pe(0:(
pe_size-1)))
499 allocate(n_points_from_pe(0:(
pe_size-1)))
503 do i = 1, this%n_points
504 n_points_per_pe(this%proc_owner(i)) = &
505 n_points_per_pe(this%proc_owner(i)) + 1
510 call mpi_reduce(n_points_per_pe(i), n_new_points, 1, mpi_integer, &
512 call mpi_gather(n_points_per_pe(i), 1, mpi_integer,&
513 n_points_from_pe, 1, mpi_integer, i,
neko_comm, ierr)
516 allocate(n_point_offset_from_pe(0:(
pe_size-1)))
517 n_point_offset_from_pe(0) = 0
519 n_point_offset_from_pe(i) = n_points_from_pe(i-1)&
520 + n_point_offset_from_pe(i-1)
523 allocate(new_xyz(3, n_new_points))
524 max_n_points_to_send = maxval(n_points_per_pe)
525 allocate(xyz_send_to_pe(3, max_n_points_to_send))
529 do j = 1, this%n_points
530 if (this%proc_owner(j) .eq. i)
then
532 xyz_send_to_pe(:,k) = this%xyz(:,j)
535 if (k .ne. n_points_per_pe(i))
then
536 write(*,*)
'PE: ',
pe_rank,
' has k= ', k, &
537 'points for PE:', i,
' but should have: ', &
539 call neko_error(
'Error in redistribution of points')
541 call mpi_gatherv(xyz_send_to_pe,3*n_points_per_pe(i), &
542 mpi_double_precision, new_xyz,3*n_points_from_pe, &
543 3*n_point_offset_from_pe, &
544 mpi_double_precision, i,
neko_comm, ierr)
548 call this%free_points()
550 this%n_points = n_new_points
552 call copy(this%xyz, new_xyz, 3 * n_new_points)
554 deallocate(n_point_offset_from_pe)
555 deallocate(n_points_from_pe)
556 deallocate(n_points_per_pe)
557 deallocate(xyz_send_to_pe)
568 real(kind=
rp),
intent(inout) :: interp_values(this%n_points)
569 real(kind=
rp),
intent(inout) ::
field(this%nelv*this%Xh%lxyz)
573 if (.not. this%all_points_local)
then
574 call fgslib_findpts_eval(this%gs_handle, interp_values, &
575 1, this%error_code, 1, &
576 this%proc_owner, 1, this%el_owner, 1, &
577 this%rst, this%gdim, &
578 this%n_points,
field)
580 if (this%n_points .gt. 0) &
581 call this%local_interp%evaluate(interp_values, this%el_owner, &
585 call neko_error(
'Neko needs to be built with GSLIB support')