Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
global_interpolation.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2025, 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!
36 use num_types, only : rp, dp, xp
38 use space, only : space_t
39 use stack, only : stack_i4_t
40 use dofmap, only : dofmap_t
41 use logger, only : neko_log, log_size
43 use json_module, only : json_file
44 use utils, only : neko_error
54 use el_finder, only : el_finder_t
55 use pe_finder, only : pe_finder_t
56 use comm, only : neko_comm
57 use mpi_f08, only : mpi_sum, mpi_comm, mpi_comm_rank, &
58 mpi_comm_size, mpi_wtime, mpi_allreduce, mpi_in_place, mpi_integer, &
59 mpi_min, mpi_barrier, mpi_reduce_scatter_block, mpi_alltoall, &
60 mpi_isend, mpi_irecv
62 use vector, only : vector_t
64 use matrix, only : matrix_t
65 use math, only : copy, neko_eps
66 use mask, only : mask_t
67 use structs, only : array_ptr_t
68 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_associated
69 implicit none
70 private
71
72 integer, public, parameter :: glob_map_size = 4096
73 real(kind=dp), public, parameter :: glob_interp_tol = neko_eps*1e3_dp
74 real(kind=dp), public, parameter :: glob_interp_pad = 1e-2_dp
75
81 real(kind=dp) :: tolerance = glob_interp_tol
83 real(kind=dp) :: padding = glob_interp_pad
85
87 type, public :: global_interpolation_t
89 type(vector_t) :: x
91 type(vector_t) :: y
93 type(vector_t) :: z
95 integer :: gdim
97 integer :: nelv
99 integer :: glb_nelv
101 type(mpi_comm) :: comm
103 integer :: pe_rank
105 integer :: pe_size
107 type(space_t) :: xh
110 integer :: n_points
112 real(kind=rp), allocatable :: xyz(:,:)
114 real(kind=rp), allocatable :: rst(:,:)
116 integer, allocatable :: pe_owner(:)
118 type(stack_i4_t), allocatable :: points_at_pe(:)
121 integer, allocatable :: el_owner0(:)
122 type(c_ptr) :: el_owner0_d = c_null_ptr
123
125 integer :: n_points_local
126 integer, allocatable :: el_owner0_local(:)
127 type(c_ptr) :: el_owner0_local_d = c_null_ptr
128 real(kind=rp), allocatable :: rst_local(:,:)
129 real(kind=rp), allocatable :: xyz_local(:,:)
131 type(local_interpolator_t) :: local_interp
134 logical :: all_points_local = .false.
136 real(kind=dp) :: tolerance = glob_interp_tol
138 real(kind=dp) :: padding = glob_interp_pad
139
143 integer, allocatable :: n_points_pe(:)
144 integer, allocatable :: n_points_offset_pe(:)
147 integer, allocatable :: n_points_pe_local(:)
148 integer, allocatable :: n_points_offset_pe_local(:)
151 class(pe_finder_t), allocatable :: pe_finder
153 class(el_finder_t), allocatable :: el_finder
155 type(legendre_rst_finder_t) :: rst_finder
160 type(vector_t) :: temp_local, temp
161 integer :: n_dof = -1
162 type(vector_t) :: masked_field
163
164 contains
167 procedure, pass(this) :: init_json_xyz => &
171 procedure, pass(this) :: init_json_dof => &
175 procedure, pass(this) :: init_xyz => global_interpolation_init_xyz
177 procedure, pass(this) :: init_dof => global_interpolation_init_dof
179 procedure, pass(this) :: free => global_interpolation_free
181 procedure, pass(this) :: free_points => global_interpolation_free_points
182 procedure, pass(this) :: free_points_local => &
184 procedure, pass(this) :: find_points_and_redist => &
189 procedure, pass(this) :: find_points_coords => &
191 procedure, pass(this) :: find_points_coords1d => &
194 procedure, pass(this) :: check_points => &
196 procedure, pass(this) :: find_points_xyz => global_interpolation_find_xyz
197 generic :: find_points => find_points_xyz, find_points_coords, &
198 find_points_coords1d
200 procedure, pass(this) :: evaluate => global_interpolation_evaluate
201 procedure, pass(this) :: evaluate_masked => &
203 procedure, pass(this) :: init_redist_comm => &
205
207 generic :: init => init_dof, init_xyz, init_json_xyz, init_json_dof
208
210
211contains
212
226 subroutine global_interpolation_init_json_xyz(this, x, y, z, gdim, nelv, Xh, &
227 params_subdict, comm)
228 class(global_interpolation_t), target, intent(inout) :: this
229 real(kind=rp), intent(in) :: x(:)
230 real(kind=rp), intent(in) :: y(:)
231 real(kind=rp), intent(in) :: z(:)
232 integer, intent(in) :: gdim
233 integer, intent(in) :: nelv
234 type(space_t), intent(in) :: Xh
235 type(json_file), intent(inout) :: params_subdict
236 type(mpi_comm), intent(in), optional :: comm
237
238 real(kind=dp) :: tol, pad
239
240 call json_get_or_lookup_or_default(params_subdict, 'tolerance', &
241 tol, glob_interp_tol)
242 call json_get_or_lookup_or_default(params_subdict, 'padding', &
243 pad, glob_interp_pad)
244
245 call this%init_xyz(x, y, z, gdim, nelv, xh, comm = comm, tol = tol, &
246 pad = pad)
247
249
257 subroutine global_interpolation_init_json_dof(this, dof, params_subdict, &
258 comm, mask)
259 class(global_interpolation_t), target, intent(inout) :: this
260 type(dofmap_t) :: dof
261 type(json_file), intent(inout) :: params_subdict
262 type(mpi_comm), optional, intent(in) :: comm
263 type(mask_t), intent(in), optional :: mask
264
265 real(kind=dp) :: tol, pad
266
267 call json_get_or_lookup_or_default(params_subdict, 'tolerance', &
268 tol, glob_interp_tol)
269 call json_get_or_lookup_or_default(params_subdict, 'padding', &
270 pad, glob_interp_pad)
271
272 call this%init_dof(dof, comm = comm, tol = tol, pad = pad, mask = mask)
273
275
282 subroutine global_interpolation_init_dof(this, dof, comm, tol, pad, mask)
283 class(global_interpolation_t), target, intent(inout) :: this
284 type(dofmap_t) :: dof
285 type(mpi_comm), optional, intent(in) :: comm
286 real(kind=dp), optional :: tol
287 real(kind=dp), optional :: pad
288 type(mask_t), intent(in), optional :: mask
289
290 integer :: temp_nelv
291
292 ! Store the number of dofs
293 this%n_dof = dof%size()
294 ! NOTE: Passing dof%x(:,1,1,1), etc in init_xyz passes down the entire
295 ! dof%x array and not a slice. It is done this way for
296 ! to get the right dimension (see global_interpolation_init_xyz).
297 if (.not. present(mask)) then
298 call this%init_xyz(dof%x(:,1,1,1), dof%y(:,1,1,1), dof%z(:,1,1,1), &
299 dof%msh%gdim, dof%msh%nelv, dof%Xh, comm = comm, &
300 tol = tol, pad = pad)
301 else
302
303 ! Initialize a helper field with the size of the mask
304 call this%masked_field%init(mask%size())
305 ! Verify that the mask size is compatible with the dofmap
306 temp_nelv = mask%size() / (dof%Xh%lx*dof%Xh%ly*dof%Xh%lz)
307 if (mod(mask%size(), dof%Xh%lx*dof%Xh%ly*dof%Xh%lz) /= 0) then
308 call neko_error("Mask size must be a multiple of the number of" // &
309 " elements in the mesh.")
310 end if
311 ! Initialize with the masked coordinates
312 call this%init_xyz(dof%x(mask%get(),1,1,1), dof%y(mask%get(),1,1,1), &
313 dof%z(mask%get(),1,1,1), dof%msh%gdim, temp_nelv, dof%Xh, &
314 comm = comm, tol = tol, pad = pad)
315 end if
316
317 end subroutine global_interpolation_init_dof
318
329 subroutine global_interpolation_init_xyz(this, x, y, z, gdim, nelv, Xh, &
330 comm, tol, pad)
331 class(global_interpolation_t), target, intent(inout) :: this
332 real(kind=rp), intent(in) :: x(:)
333 real(kind=rp), intent(in) :: y(:)
334 real(kind=rp), intent(in) :: z(:)
335 integer, intent(in) :: gdim
336 integer, intent(in) :: nelv
337 type(space_t), intent(in) :: Xh
338 type(mpi_comm), intent(in), optional :: comm
339 real(kind=dp), intent(in), optional :: tol
340 real(kind=dp), intent(in), optional :: pad
341
342 integer :: lx, ly, lz, ierr, i, n
343 character(len=8000) :: log_buf
344 !real(kind=dp) :: padding ! <-- note that this padding is in dp
345 real(kind=rp) :: time1, time_start
346 character(len=255) :: mode_str
347 integer :: boxdim, envvar_len
348
349 call neko_log%section('Global Interpolation')
350 call neko_log%message('Initializing global interpolation')
351
352 call this%free()
353
354 ! Set communicator
355 if (present(comm)) then
356 this%comm = comm
357 else
358 this%comm = neko_comm
359 end if
360
361 ! Set point search parameters
362 this%padding = glob_interp_pad
363 if (present(pad)) this%padding = pad
364
365 this%tolerance = glob_interp_tol
366 if (present(tol)) this%tolerance = tol
367
368 write(log_buf, '(A,E15.7)') &
369 'Tolerance: ', this%tolerance
370 call neko_log%message(log_buf)
371 write(log_buf, '(A,E15.7)') &
372 'Padding : ', this%padding
373 call neko_log%message(log_buf)
374
375 time_start = mpi_wtime()
376 call mpi_barrier(this%comm)
377
378 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
379 call mpi_comm_size(this%comm, this%pe_size, ierr)
380
381 this%gdim = gdim
382 this%nelv = nelv
383
384 call mpi_allreduce(nelv, this%glb_nelv, 1, mpi_integer, &
385 mpi_sum, this%comm, ierr)
386 lx = xh%lx
387 ly = xh%ly
388 lz = xh%lz
389 n = nelv * lx*ly*lz
390 call this%x%init(n)
391 call this%y%init(n)
392 call this%z%init(n)
393 call copy(this%x%x, x, n)
394 call this%x%copy_from(host_to_device,.false.)
395 call copy(this%y%x, y, n)
396 call this%y%copy_from(host_to_device,.false.)
397 call copy(this%z%x, z, n)
398 call this%z%copy_from(host_to_device,.false.)
399 call this%Xh%init(xh%t, lx, ly, lz)
400
401 ! Initialize n_dof if it was not started with a dof-based constructor
402 if (this%n_dof == -1) then
403 this%n_dof = n
404 end if
405
406
407 call get_environment_variable("NEKO_GLOBAL_INTERP_EL_FINDER", &
408 mode_str, envvar_len)
409
410 if (envvar_len .gt. 0) then
411 if (mode_str(1:envvar_len) == 'AABB') then
412 allocate(aabb_el_finder_t :: this%el_finder)
413 end if
414 end if
415 call get_environment_variable("NEKO_GLOBAL_INTERP_PE_FINDER", &
416 mode_str, envvar_len)
417
418 if (envvar_len .gt. 0) then
419 if (mode_str(1:envvar_len) == 'AABB') then
420 allocate(aabb_pe_finder_t :: this%pe_finder)
421 end if
422 end if
423
424 if (.not. allocated(this%el_finder)) then
425 allocate(cartesian_el_finder_t :: this%el_finder)
426 end if
427 if (.not. allocated(this%pe_finder)) then
428 allocate(cartesian_pe_finder_t :: this%pe_finder)
429 end if
430 select type (el_find => this%el_finder)
431 type is (aabb_el_finder_t)
432 call neko_log%message('Using AABB element finder')
433 call el_find%init(x, y, z, nelv, xh, this%padding)
434 type is (cartesian_el_finder_t)
435 call neko_log%message('Using Cartesian element finder')
436 boxdim = max(lx*int(real(nelv, xp)**(1.0_xp / 3.0_xp)), 2)
437 boxdim = min(boxdim, 300)
438 call el_find%init(x, y, z, nelv, xh, boxdim, this%padding)
439 class default
440 call neko_error('Unknown element finder type')
441 end select
442
443 select type (pe_find => this%pe_finder)
444 type is (aabb_pe_finder_t)
445 call neko_log%message('Using AABB PE finder')
446 call pe_find%init(this%x%x, this%y%x, this%z%x, &
447 nelv, xh, this%comm, this%padding)
448 type is (cartesian_pe_finder_t)
449 call neko_log%message('Using Cartesian PE finder')
450 boxdim = lx*int(real(this%glb_nelv, xp)**(1.0_xp / 3.0_xp))
451 boxdim = max(boxdim, 32)
452 boxdim = min(boxdim, &
453 int(8.0_xp*(30000.0_xp * this%pe_size)**(1.0_xp / 3.0_xp)))
454 call pe_find%init(this%x%x, this%y%x, this%z%x, &
455 nelv, xh, this%comm, boxdim, this%padding)
456 class default
457 call neko_error('Unknown PE finder type')
458 end select
459
460 call this%rst_finder%init(this%x%x, this%y%x, this%z%x, nelv, xh, &
461 this%tolerance)
462 if (allocated(this%n_points_pe)) deallocate(this%n_points_pe)
463 if (allocated(this%n_points_pe_local)) deallocate(this%n_points_pe_local)
464 if (allocated(this%n_points_offset_pe_local)) &
465 deallocate(this%n_points_offset_pe_local)
466 if (allocated(this%n_points_offset_pe)) deallocate(this%n_points_offset_pe)
467 allocate(this%n_points_pe(0:(this%pe_size-1)))
468 allocate(this%n_points_offset_pe(0:(this%pe_size-1)))
469 allocate(this%n_points_pe_local(0:(this%pe_size-1)))
470 allocate(this%n_points_offset_pe_local(0:(this%pe_size-1)))
471 allocate(this%points_at_pe(0:(this%pe_size-1)))
472 do i = 0, this%pe_size-1
473 call this%points_at_pe(i)%init()
474 end do
475 call mpi_barrier(this%comm)
476 time1 = mpi_wtime()
477 write(log_buf, '(A,E15.7)') &
478 'Global interpolation initialized (s):', time1-time_start
479 call neko_log%message(log_buf)
480 call neko_log%end_section()
481 end subroutine global_interpolation_init_xyz
482
483
486 class(global_interpolation_t), target, intent(inout) :: this
487 integer :: i
488
489 call this%x%free()
490 call this%y%free()
491 call this%z%free()
492 call this%Xh%free()
493
494 this%nelv = 0
495 this%gdim = 0
496
497 call this%free_points()
498 call this%free_points_local()
499 call this%local_interp%free()
500 if (allocated(this%el_finder)) then
501 call this%el_finder%free()
502 deallocate(this%el_finder)
503 end if
504 if (allocated(this%pe_finder)) then
505 call this%pe_finder%free()
506 deallocate(this%pe_finder)
507 end if
508 call this%rst_finder%free()
509
510 call this%temp_local%free()
511 call this%temp%free()
512 if (allocated(this%points_at_pe)) then
513 do i = 0, this%pe_size-1
514 call this%points_at_pe(i)%free()
515 end do
516 deallocate(this%points_at_pe)
517 end if
518 if (allocated(this%n_points_pe)) deallocate(this%n_points_pe)
519 if (allocated(this%n_points_pe_local)) deallocate(this%n_points_pe_local)
520 if (allocated(this%n_points_offset_pe_local)) &
521 deallocate(this%n_points_offset_pe_local)
522 if (allocated(this%n_points_offset_pe)) deallocate(this%n_points_offset_pe)
523
524
525
526 end subroutine global_interpolation_free
527
530 class(global_interpolation_t), target, intent(inout) :: this
531
532 this%n_points = 0
533 this%all_points_local = .false.
534
535 if (allocated(this%xyz)) deallocate(this%xyz)
536 if (allocated(this%rst)) deallocate(this%rst)
537 if (allocated(this%pe_owner)) deallocate(this%pe_owner)
538 if (allocated(this%el_owner0)) then
539 if (neko_bcknd_device .eq. 1) then
540 call device_unmap(this%el_owner0, this%el_owner0_d)
541 end if
542 deallocate(this%el_owner0)
543 end if
544
545 call this%glb_intrp_comm%free()
546
547
549
550
552 class(global_interpolation_t), target, intent(inout) :: this
553
554 this%n_points_local = 0
555 this%all_points_local = .false.
556
557 if (allocated(this%xyz_local)) deallocate(this%xyz_local)
558 if (allocated(this%rst_local)) deallocate(this%rst_local)
559 if (allocated(this%el_owner0_local)) then
560 if (neko_bcknd_device .eq. 1) then
561 call device_unmap(this%el_owner0_local, this%el_owner0_local_d)
562 end if
563 deallocate(this%el_owner0_local)
564 end if
565
567
568
571 class(global_interpolation_t), target, intent(inout) :: this
572 character(len=8000) :: log_buf
573 type(vector_t) :: x_t
574 type(vector_t) :: y_t
575 type(vector_t) :: z_t
576 type(matrix_t) :: rst_local_cand
577 type(vector_t) :: resx
578 type(vector_t) :: resy
579 type(vector_t) :: resz
580 type(c_ptr) :: el_cands_d
581 type(matrix_t) :: res
582 integer :: i, j, stupid_intent
583 type(stack_i4_t), target :: all_el_candidates
584 integer, allocatable :: n_el_cands(:)
585 integer, contiguous, pointer :: el_cands(:), point_ids(:), send_recv(:)
586 real(kind=rp), allocatable :: res_results(:,:)
587 real(kind=rp), allocatable :: rst_results(:,:)
588 integer, allocatable :: el_owner_results(:)
589 integer :: ierr, ii, n_point_cand, n_glb_point_cand, point_id, rank
590 real(kind=rp) :: time1, time2, time_start
591 !Temp stuff for glb_intrp_comm
592 type(stack_i4_t) :: send_pe, recv_pe
593 type(glb_intrp_comm_t) :: glb_intrp_find, glb_intrp_find_back
594 type(stack_i4_t) :: send_pe_find, recv_pe_find
595
596 el_cands_d = c_null_ptr
597 call neko_log%section('Global Interpolation')
598 call glb_intrp_find%init_dofs(this%pe_size)
599 call send_pe_find%init()
600 call recv_pe_find%init()
601 call mpi_barrier(this%comm)
602 time_start = mpi_wtime()
603 write(log_buf, '(A)') 'Global interpolation, finding points'
604 call neko_log%message(log_buf)
605 ! Find pe candidates that the points i want may be at
606 ! Add number to n_points_pe_local
607 !Working arrays
608 this%n_points_pe = 0
609 call this%pe_finder%find_batch(this%xyz, this%n_points, &
610 this%points_at_pe, this%n_points_pe)
611 call mpi_barrier(this%comm)
612 time1 = mpi_wtime()
613 write(log_buf, '(A,E15.7)') &
614 'Found PE candidates time since start of findpts (s):', &
615 time1 - time_start
616 call neko_log%message(log_buf)
617
618 !Send number of points I want to candidates
619 ! n_points_local -> how many points might be at this rank
620 ! n_points_pe_local -> how many points local on this rank that other pes
621 ! might want
622 this%n_points_pe_local = 0
623 this%n_points_local = 0
624 call mpi_reduce_scatter_block(this%n_points_pe, this%n_points_local, &
625 1, mpi_integer, mpi_sum, this%comm, ierr)
626 call mpi_alltoall(this%n_points_pe, 1, mpi_integer,&
627 this%n_points_pe_local, 1, mpi_integer, this%comm, ierr)
628
629 !Set up offset arrays
630 this%n_points_offset_pe_local(0) = 0
631 this%n_points_offset_pe(0) = 0
632 do i = 1, (this%pe_size - 1)
633 this%n_points_offset_pe_local(i) = this%n_points_pe_local(i-1)&
634 + this%n_points_offset_pe_local(i-1)
635 this%n_points_offset_pe(i) = this%n_points_pe(i-1)&
636 + this%n_points_offset_pe(i-1)
637 end do
638 do i = 0, (this%pe_size-1)
639 if (this%n_points_pe(i) .gt. 0) then
640 call send_pe_find%push(i)
641 point_ids => this%points_at_pe(i)%array()
642 do j = 1, this%n_points_pe(i)
643 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+1)
644 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+2)
645 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+3)
646 end do
647 end if
648 if (this%n_points_pe_local(i) .gt. 0) then
649 call recv_pe_find%push(i)
650 do j = 1, this%n_points_pe_local(i)
651 call glb_intrp_find%recv_dof(i)%push(3*(j + &
652 this%n_points_offset_pe_local(i) - 1) + 1)
653 call glb_intrp_find%recv_dof(i)%push(3*(j + &
654 this%n_points_offset_pe_local(i) - 1) + 2)
655 call glb_intrp_find%recv_dof(i)%push(3*(j + &
656 this%n_points_offset_pe_local(i) - 1) + 3)
657 end do
658 end if
659 end do
660
661
662
663 call glb_intrp_find%init(send_pe_find, recv_pe_find, this%comm)
664
665 call glb_intrp_find_back%init_dofs(this%pe_size)
666 ii = 0
667 do i = 0, (this%pe_size-1)
668 send_recv => glb_intrp_find%recv_dof(i)%array()
669 do j = 1, glb_intrp_find%recv_dof(i)%size()
670 call glb_intrp_find_back%send_dof(i)%push(send_recv(j))
671 end do
672 send_recv => glb_intrp_find%send_dof(i)%array()
673 do j = 1, glb_intrp_find%send_dof(i)%size()
674 ii = ii + 1
675 call glb_intrp_find_back%recv_dof(i)%push(ii)
676 end do
677 end do
678
679 call glb_intrp_find_back%init(recv_pe_find, send_pe_find, this%comm)
680
681
682 if (allocated(this%xyz_local)) then
683 deallocate(this%xyz_local)
684 end if
685 allocate(this%xyz_local(3, this%n_points_local))
686 call glb_intrp_find%sendrecv(this%xyz, this%xyz_local, this%n_points*3, &
687 this%n_points_local*3)
688
689 call mpi_barrier(this%comm)
690 time1 = mpi_wtime()
691 write(log_buf, '(A,E15.7)') &
692 'Sent to points to PE candidates, time since start of ' &
693 // 'find_points (s):', time1 - time_start
694 call neko_log%message(log_buf)
695
696 !Okay, now we need to find the rst...
697 call all_el_candidates%init()
698
699 if (allocated(n_el_cands)) then
700 deallocate(n_el_cands)
701 end if
702
703 allocate(n_el_cands(this%n_points_local))
705 call this%el_finder%find_batch(this%xyz_local, this%n_points_local, &
706 all_el_candidates, n_el_cands)
707
708 n_point_cand = all_el_candidates%size()
709 if (n_point_cand .gt. 1e8) then
710 print *, 'Warning, many point candidates on rank', this%pe_rank, &
711 'cands:', n_point_cand, &
712 'Consider increasing number of ranks'
713 end if
714 call x_t%init(n_point_cand)
715 call y_t%init(n_point_cand)
716 call z_t%init(n_point_cand)
717 ii = 0
719 do i = 1 , this%n_points_local
720 do j = 1, n_el_cands(i)
721 ii = ii + 1
722 x_t%x(ii) = this%xyz_local(1,i)
723 y_t%x(ii) = this%xyz_local(2,i)
724 z_t%x(ii) = this%xyz_local(3,i)
725 end do
726 end do
727
728 call mpi_barrier(this%comm)
729 time1 = mpi_wtime()
730 write(log_buf, '(A,E15.7)') &
731 'Element candidates found, now time for finding rst, time ' // &
732 'since start of find_points (s):', time1 - time_start
733 call neko_log%message(log_buf)
734 call rst_local_cand%init(3, n_point_cand)
735 call resx%init(n_point_cand)
736 call resy%init(n_point_cand)
737 call resz%init(n_point_cand)
738
739 ! Find rst within all element candidates for target xyz (x_t, y_t, z_t)
740 call mpi_barrier(this%comm)
741 time1 = mpi_wtime()
742 el_cands => all_el_candidates%array()
743 if (neko_bcknd_device .eq. 1) then
744 call x_t%copy_from(host_to_device,.false.)
745
746 call y_t%copy_from(host_to_device,.false.)
747
748 call z_t%copy_from(host_to_device,.false.)
749 call device_map(el_cands, el_cands_d, n_point_cand)
750 call device_memcpy(el_cands, el_cands_d, n_point_cand, &
751 host_to_device, .true.)
752 end if
753
754 call this%rst_finder%find(rst_local_cand, &
755 x_t, y_t, z_t, &
756 el_cands, n_point_cand, &
757 resx, resy, resz)
758 if (neko_bcknd_device .eq. 1) then
759 call rst_local_cand%copy_from(device_to_host,.false.)
760 call resx%copy_from(device_to_host,.false.)
761 call resy%copy_from(device_to_host,.false.)
762 call resz%copy_from(device_to_host,.true.)
763 call device_unmap(el_cands, el_cands_d)
764 end if
765 call mpi_barrier(this%comm)
766
767 time2 = mpi_wtime()
768 write(log_buf, '(A,E15.7)') &
769 'Found rst with Newton iteration, time (s):', time2-time1
770 call neko_log%message(log_buf)
771
772 write(log_buf, '(A)') &
773 'Checking validity of points and choosing best candidates.'
774 call neko_log%message(log_buf)
775 call mpi_barrier(this%comm, ierr)
776
777 if (allocated(this%rst_local)) deallocate(this%rst_local)
778 if (allocated(this%el_owner0_local)) deallocate(this%el_owner0_local)
779 allocate(this%rst_local(3, this%n_points_local))
780 allocate(this%el_owner0_local(this%n_points_local))
781 ! Choose the best candidate at this rank
782 ii = 0
783 do i = 1 , this%n_points_local
784 this%xyz_local(1,i) = 10.0
785 this%xyz_local(2,i) = 10.0
786 this%xyz_local(3,i) = 10.0
787 this%rst_local(1,i) = 10.0
788 this%rst_local(2,i) = 10.0
789 this%rst_local(3,i) = 10.0
790 this%el_owner0_local(i) = -1
791 do j = 1, n_el_cands(i)
792 ii = ii + 1
793 if (rst_cmp(this%rst_local(:, i), rst_local_cand%x(:, ii), &
794 this%xyz_local(:, i), [resx%x(ii), resy%x(ii), resz%x(ii)], &
795 this%padding)) then
796 this%rst_local(1, i) = rst_local_cand%x(1, ii)
797 this%rst_local(2, i) = rst_local_cand%x(2, ii)
798
799 this%rst_local(3, i) = rst_local_cand%x(3, ii)
800 this%xyz_local(1,i) = resx%x(ii)
801 this%xyz_local(2,i) = resy%x(ii)
802 this%xyz_local(3,i) = resz%x(ii)
803 this%el_owner0_local(i) = el_cands(ii)
804 end if
805 ! if (this%pe_rank .eq. 0) print *,i, this%rst_local(:,i), &
806 ! this%xyz_local(:,i), this%el_owner0_local(i)
807 end do
808 end do
809 call res%init(3, this%n_points)
810 n_glb_point_cand = sum(this%n_points_pe)
811 if (allocated(rst_results)) deallocate(rst_results)
812 if (allocated(res_results)) deallocate(res_results)
813 if (allocated(el_owner_results)) deallocate(el_owner_results)
814 allocate(rst_results(3, n_glb_point_cand))
815 allocate(res_results(3, n_glb_point_cand))
816 allocate(el_owner_results(n_glb_point_cand))
817 res = 1e2_rp
818 this%rst = 1e2
819 this%pe_owner = -1
820 this%el_owner0 = -1
821 call glb_intrp_find_back%sendrecv(this%xyz_local, res_results, &
822 this%n_points_local*3, n_glb_point_cand*3)
823 call glb_intrp_find_back%sendrecv(this%rst_local, rst_results, &
824 this%n_points_local*3, n_glb_point_cand*3)
825 do i = 1, size(glb_intrp_find_back%send_pe)
826 rank = glb_intrp_find_back%send_pe(i)
827 call mpi_isend(this%el_owner0_local( &
828 this%n_points_offset_pe_local(rank) + 1), &
829 this%n_points_pe_local(rank), &
830 mpi_integer, rank, 0, &
831 this%comm, glb_intrp_find_back%send_buf(i)%request, ierr)
832 glb_intrp_find_back%send_buf(i)%flag = .false.
833 end do
834 do i = 1, size(glb_intrp_find_back%recv_pe)
835 rank = glb_intrp_find_back%recv_pe(i)
836 call mpi_irecv(el_owner_results(this%n_points_offset_pe(rank)+1),&
837 this%n_points_pe(rank), &
838 mpi_integer, rank, 0, &
839 this%comm, glb_intrp_find_back%recv_buf(i)%request, ierr)
840 glb_intrp_find_back%recv_buf(i)%flag = .false.
841 end do
842 call glb_intrp_find_back%nbwait_no_op()
843 ii = 0
844 do i = 1, size(glb_intrp_find_back%recv_pe)
845 point_ids => this%points_at_pe(glb_intrp_find_back%recv_pe(i))%array()
846 do j = 1, this%n_points_pe(glb_intrp_find_back%recv_pe(i))
847 point_id = point_ids(j)
848 ii = ii + 1
849 if (rst_cmp(this%rst(:, point_id), rst_results(:, ii), &
850 res%x(:, point_id), res_results(:, ii), this%padding) .or. &
851 this%pe_owner(point_ids(j)) .eq. -1 ) then
852 this%rst(:, point_ids(j)) = rst_results(:, ii)
853 res%x(:, point_ids(j)) = res_results(:, ii)
854 this%pe_owner(point_ids(j)) = glb_intrp_find_back%recv_pe(i)
855 this%el_owner0(point_ids(j)) = el_owner_results(ii)
856 end if
857 ! if (this%pe_rank .eq. 0) print *,point_id, &
858 !this%rst(:,point_ids(j)),res%x(:,point_ids(j)),
859 ! this%el_owner0(point_ids(j))
860 end do
861 end do
862
863 !OK, now I know the correct rst values of the points I want We now
864 !send the correct rsts to the correct rank (so a point only
865 !belongs to one rank)
866 do i = 0, this%pe_size-1
867 call this%points_at_pe(i)%clear()
868 this%n_points_pe(i) = 0
869 end do
870
871 do i = 1, this%n_points
872 stupid_intent = i
873 if (this%pe_owner(i) .eq. -1 .or. this%el_owner0(i) .eq. -1) then
874 print *, 'No owning rank found for',&
875 ' point ', stupid_intent, ' with coords', this%xyz(:,i), &
876 ' Interpolation will always yield 0.0. Try increase padding.'
877 else
878 call this%points_at_pe(this%pe_owner(i))%push(stupid_intent)
879 this%n_points_pe(this%pe_owner(i)) = &
880 this%n_points_pe(this%pe_owner(i)) + 1
881 end if
882 end do
883 call mpi_reduce_scatter_block(this%n_points_pe, this%n_points_local, 1, &
884 mpi_integer, mpi_sum, this%comm, ierr)
885 call mpi_alltoall(this%n_points_pe, 1, mpi_integer, &
886 this%n_points_pe_local, 1, mpi_integer, this%comm, ierr)
887 this%n_points_offset_pe_local(0) = 0
888 this%n_points_offset_pe(0) = 0
889 do i = 1, (this%pe_size - 1)
890 this%n_points_offset_pe_local(i) = this%n_points_pe_local(i-1)&
891 + this%n_points_offset_pe_local(i-1)
892 this%n_points_offset_pe(i) = this%n_points_pe(i-1)&
893 + this%n_points_offset_pe(i-1)
894 end do
895 call send_pe_find%free()
896 call recv_pe_find%free()
897 call glb_intrp_find%free()
898 call send_pe_find%init()
899 call recv_pe_find%init()
900 call glb_intrp_find%init_dofs(this%pe_size)
901 !setup comm to send xyz and rst to chosen ranks
902 do i = 0, (this%pe_size-1)
903 if (this%n_points_pe(i) .gt. 0) then
904 call send_pe_find%push(i)
905 point_ids => this%points_at_pe(i)%array()
906 do j = 1, this%n_points_pe(i)
907 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 1)
908 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 2)
909 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 3)
910 end do
911 end if
912 if (this%n_points_pe_local(i) .gt. 0) then
913 call recv_pe_find%push(i)
914 do j = 1, this%n_points_pe_local(i)
915 call glb_intrp_find%recv_dof(i)%push(3*(j + &
916 this%n_points_offset_pe_local(i) - 1) + 1)
917 call glb_intrp_find%recv_dof(i)%push(3*(j + &
918 this%n_points_offset_pe_local(i) - 1) + 2)
919 call glb_intrp_find%recv_dof(i)%push(3*(j + &
920 this%n_points_offset_pe_local(i) - 1) + 3)
921 end do
922 end if
923 end do
924
925
926 call glb_intrp_find%init(send_pe_find, recv_pe_find, this%comm)
927 call glb_intrp_find%sendrecv(this%xyz, this%xyz_local, this%n_points*3, &
928 this%n_points_local*3)
929 call glb_intrp_find%sendrecv(this%rst, this%rst_local, this%n_points*3, &
930 this%n_points_local*3)
931 ii = 0
932 do i = 1, size(glb_intrp_find%send_pe)
933 rank = glb_intrp_find%send_pe(i)
934 point_ids => this%points_at_pe(rank)%array()
935 do j = 1, this%n_points_pe(rank)
936 ii = ii + 1
937 el_owner_results(ii) = this%el_owner0(point_ids(j))
938 end do
939 call mpi_isend(el_owner_results(this%n_points_offset_pe(rank) + 1),&
940 this%n_points_pe(rank), &
941 mpi_integer, rank, 0, &
942 this%comm, glb_intrp_find%send_buf(i)%request, ierr)
943 glb_intrp_find%send_buf(i)%flag = .false.
944 end do
945 do i = 1, size(glb_intrp_find%recv_pe)
946 rank = glb_intrp_find%recv_pe(i)
947 call mpi_irecv(this%el_owner0_local( &
948 this%n_points_offset_pe_local(rank) + 1), &
949 this%n_points_pe_local(rank), &
950 mpi_integer, rank, 0, &
951 this%comm, glb_intrp_find%recv_buf(i)%request, ierr)
952 glb_intrp_find%recv_buf(i)%flag = .false.
953 end do
954 call glb_intrp_find%nbwait_no_op()
955
956 call glb_intrp_find%free()
957
958 !Set up final way of doing communication
959 call send_pe%init()
960 call recv_pe%init()
961 call this%glb_intrp_comm%init_dofs(this%pe_size)
962 do i = 0, (this%pe_size-1)
963 if (this%n_points_pe(i) .gt. 0) then
964 call recv_pe%push(i)
965 point_ids => this%points_at_pe(i)%array()
966 do j = 1, this%n_points_pe(i)
967 call this%glb_intrp_comm%recv_dof(i)%push(point_ids(j))
968 end do
969 end if
970 if (this%n_points_pe_local(i) .gt. 0) then
971 call send_pe%push(i)
972 do j = 1, this%n_points_pe_local(i)
973 call this%glb_intrp_comm%send_dof(i)%push(j + &
974 this%n_points_offset_pe_local(i))
975 end do
976 end if
977 end do
978 call this%glb_intrp_comm%init(send_pe, recv_pe, this%comm)
979
980 !Initialize working arrays for evaluation
981 call this%temp_local%init(this%n_points_local)
982 call this%temp%init(this%n_points)
983
984 !Initialize interpolator for local interpolation
985 call this%local_interp%init(this%Xh, this%rst_local, &
986 this%n_points_local)
987
988
989 if (neko_bcknd_device .eq. 1) then
990 call device_memcpy(this%el_owner0, this%el_owner0_d, &
991 this%n_points, host_to_device, sync = .true.)
992 call device_map(this%el_owner0_local, this%el_owner0_local_d, &
993 this%n_points_local)
994 call device_memcpy(this%el_owner0_local, this%el_owner0_local_d, &
995 this%n_points_local, host_to_device, sync = .true.)
996 end if
997
998 call this%check_points(this%x%x, this%y%x, this%z%x)
999
1000 !Free stuff
1001 call send_pe%free()
1002 call recv_pe%free()
1003 call glb_intrp_find_back%free()
1004 call send_pe_find%free()
1005 call recv_pe_find%free()
1006 call x_t%free()
1007 call y_t%free()
1008 call z_t%free()
1009 call rst_local_cand%free()
1010 call resx%free()
1011 call resy%free()
1012 call resz%free()
1013 call res%free()
1014 call all_el_candidates%free()
1015
1016 if (allocated(n_el_cands)) deallocate(n_el_cands)
1017 if (allocated(rst_results)) deallocate(rst_results)
1018 if (allocated(res_results)) deallocate(res_results)
1019 if (allocated(el_owner_results)) deallocate(el_owner_results)
1020 call mpi_barrier(this%comm, ierr)
1021 time2 = mpi_wtime()
1022 write(log_buf, '(A,E15.7)') 'Global interpolation find points ' // &
1023 'done, time (s):', time2-time_start
1024 call neko_log%message(log_buf)
1025 call neko_log%end_section()
1026 call neko_log%newline()
1028
1032 subroutine global_interpolation_check_points(this, x, y, z)
1033 class(global_interpolation_t), target, intent(inout) :: this
1034 real(kind=rp), intent(inout) :: x(:)
1035 real(kind=rp), intent(inout) :: y(:)
1036 real(kind=rp), intent(inout) :: z(:)
1037 integer :: i, j
1038 character(len=8000) :: log_buf
1039 real(kind=rp) :: xdiff, ydiff, zdiff
1040 logical :: isdiff
1041 type(vector_t) :: x_check, y_check, z_check
1042
1043 call x_check%init(this%n_points)
1044 call y_check%init(this%n_points)
1045 call z_check%init(this%n_points)
1046 call this%evaluate(x_check%x, x, on_host = .true.)
1047 call this%evaluate(y_check%x, y, on_host = .true.)
1048 call this%evaluate(z_check%x, z, on_host = .true.)
1049 write(log_buf, '(A)') 'Checking validity of points.'
1050 call neko_log%message(log_buf)
1051 j = 0
1052 do i = 1 , this%n_points
1053 ! Check validity of points
1054 isdiff = .false.
1055 xdiff = x_check%x(i)-this%xyz(1,i)
1056 ydiff = y_check%x(i)-this%xyz(2,i)
1057 zdiff = z_check%x(i)-this%xyz(3,i)
1058 isdiff = norm2(real([xdiff, ydiff, zdiff], xp)) > this%tolerance
1059 if (isdiff) then
1060 write(*, *) 'Point ', i, 'at rank ', this%pe_rank, &
1061 'with coordinates: ', &
1062 this%xyz(1, i), this%xyz(2, i), this%xyz(3, i), &
1063 'Differ from interpolated coords: ', &
1064 x_check%x(i), y_check%x(i), z_check%x(i), &
1065 'Actual difference: ', &
1066 xdiff, ydiff, zdiff, norm2(real([xdiff, ydiff, zdiff], xp)), &
1067 'Process, element: ', &
1068 this%pe_owner(i), this%el_owner0(i)+1, &
1069 'Calculated rst: ', &
1070 this%rst(1,i), this%rst(2,i), this%rst(3,i)
1071 j = j + 1
1072 end if
1073 end do
1074 call x_check%free()
1075 call y_check%free()
1076 call z_check%free()
1077
1079
1087 subroutine global_interpolation_find_coords(this, x, y, z, n_points)
1088 class(global_interpolation_t), intent(inout) :: this
1089 integer :: n_points
1090 !!Perhaps this should be kind dp
1091 !!this is to get around that x,y,z often is 4 dimensional...
1092 !!Should maybe add interface for 1d aswell
1093 real(kind=rp) :: x(n_points,1,1,1)
1094 real(kind=rp) :: y(n_points,1,1,1)
1095 real(kind=rp) :: z(n_points,1,1,1)
1096 integer :: i
1097
1098 call this%free_points()
1099 call this%free_points_local()
1100
1101 this%n_points = n_points
1102
1104
1105 !Deepcopy of coordinates
1106 do i = 1, n_points
1107 this%xyz(1, i) = x(i,1,1,1)
1108 this%xyz(2, i) = y(i,1,1,1)
1109 this%xyz(3, i) = z(i,1,1,1)
1110 end do
1111
1113
1122 subroutine global_interpolation_find_coords1d(this, x, y, z, n_points)
1123 class(global_interpolation_t), intent(inout) :: this
1124 integer :: n_points
1125 real(kind=rp) :: x(n_points)
1126 real(kind=rp) :: y(n_points)
1127 real(kind=rp) :: z(n_points)
1128 integer :: i
1129
1130 call this%free_points()
1131 call this%free_points_local()
1132
1133 this%n_points = n_points
1134
1136
1137 !Deepcopy of coordinates
1138 do i = 1, n_points
1139 this%xyz(1, i) = x(i)
1140 this%xyz(2, i) = y(i)
1141 this%xyz(3, i) = z(i)
1142 end do
1143
1145
1147
1148
1150 class(global_interpolation_t) :: this
1151
1152 if (allocated(this%xyz)) deallocate(this%xyz)
1153 if (allocated(this%rst)) deallocate(this%rst)
1154 if (allocated(this%pe_owner)) deallocate(this%pe_owner)
1155 if (allocated(this%el_owner0)) deallocate(this%el_owner0)
1156
1157 allocate(this%pe_owner(this%n_points))
1158 allocate(this%el_owner0(this%n_points))
1159 allocate(this%xyz(3, this%n_points))
1160 allocate(this%rst(3, this%n_points))
1161 if (neko_bcknd_device .eq. 1) then
1162 call device_map(this%el_owner0, this%el_owner0_d, this%n_points)
1163 end if
1164
1166
1173 subroutine global_interpolation_find_xyz(this, xyz, n_points)
1174 class(global_interpolation_t), intent(inout) :: this
1175 integer, intent(in) :: n_points
1176 !!Perhaps this should be kind dp
1177 real(kind=rp), intent(inout) :: xyz(3, n_points)
1178
1179
1180 call this%free_points()
1181 call this%free_points_local()
1182
1183 this%n_points = n_points
1184
1186
1188 call copy(this%xyz, xyz, 3 * n_points)
1189
1191
1192 end subroutine global_interpolation_find_xyz
1193
1202 subroutine global_interpolation_find_and_redist(this, xyz, n_points)
1203 class(global_interpolation_t), intent(inout) :: this
1204 integer, intent(inout) :: n_points
1205 !!Perhaps this should be kind dp
1206 real(kind=rp), allocatable, intent(inout) :: xyz(:,:)
1207
1208
1209 call this%free_points()
1210 call this%free_points_local()
1211
1212
1213 this%n_points = n_points
1215
1217 call copy(this%xyz, xyz, 3 * n_points)
1218
1220 call this%free_points()
1221 this%n_points = this%n_points_local
1222 n_points = this%n_points_local
1224 if (allocated(xyz)) then
1225 deallocate(xyz)
1226 end if
1227 allocate(xyz(3, n_points))
1228
1229 call copy(xyz, this%xyz_local, 3*n_points)
1230 call copy(this%rst, this%rst_local, 3*n_points)
1231 call copy(this%xyz, this%xyz_local, 3*n_points)
1232 this%pe_owner = this%pe_rank
1233 this%el_owner0 = this%el_owner0_local
1234 if (neko_bcknd_device .eq. 1) then
1235 call device_memcpy(this%el_owner0, this%el_owner0_d, &
1236 this%n_points, host_to_device, sync = .true.)
1237 end if
1238 this%all_points_local = .true.
1239
1241
1245 subroutine global_interpolation_init_redist_comm(this, redist_comm)
1246 class(global_interpolation_t), intent(inout) :: this
1247 type(glb_intrp_comm_t), intent(inout) :: redist_comm
1248 type(stack_i4_t) :: send_pe
1249 type(stack_i4_t) :: recv_pe
1250 integer, pointer :: point_ids(:) => null()
1251 integer :: rank
1252 integer :: i
1253
1254 call send_pe%init()
1255 call recv_pe%init()
1256 call redist_comm%init_dofs(this%pe_size)
1257
1258 do rank = 0, this%pe_size - 1
1259 if (this%n_points_pe(rank) .gt. 0) then
1260 call send_pe%push(rank)
1261 point_ids => this%points_at_pe(rank)%array()
1262 do i = 1, this%n_points_pe(rank)
1263 call redist_comm%send_dof(rank)%push(point_ids(i))
1264 end do
1265 end if
1266 if (this%n_points_pe_local(rank) .gt. 0) then
1267 call recv_pe%push(rank)
1268 do i = 1, this%n_points_pe_local(rank)
1269 call redist_comm%recv_dof(rank)%push( &
1270 this%n_points_offset_pe_local(rank) + i)
1271 end do
1272 end if
1273 end do
1274
1275 call redist_comm%init(send_pe, recv_pe, this%comm)
1276 nullify(point_ids)
1277 call send_pe%free()
1278 call recv_pe%free()
1280
1287 subroutine global_interpolation_evaluate_masked(this, interp_values, &
1288 field, mask, on_host)
1289 class(global_interpolation_t), target, intent(inout) :: this
1290 real(kind=rp), intent(inout), target :: interp_values(this%n_points)
1291 real(kind=rp), intent(inout), target :: field(this%n_dof)
1292 type(mask_t), intent(in) :: mask
1293 logical, intent(in) :: on_host
1294
1295 call vector_masked_gather_copy(this%masked_field, field, mask, this%n_dof)
1296 call this%evaluate(interp_values, this%masked_field%x, on_host)
1297
1299
1304 subroutine global_interpolation_evaluate(this, interp_values, field, on_host)
1305 class(global_interpolation_t), target, intent(inout) :: this
1306 real(kind=rp), intent(inout), target :: interp_values(this%n_points)
1307 real(kind=rp), intent(inout), target :: field(this%nelv*this%Xh%lxyz)
1308 logical, intent(in) :: on_host
1309 type(c_ptr) :: interp_d
1310
1311 if (.not. this%all_points_local) then
1312 call this%local_interp%evaluate(this%temp_local%x, &
1313 this%el_owner0_local, field, this%nelv, on_host)
1314 if (neko_bcknd_device .eq. 1 .and. .not. on_host) then
1315 call device_memcpy(this%temp_local%x, this%temp_local%x_d, &
1316 this%n_points_local, device_to_host, .true.)
1317 end if
1318 interp_values = 0.0_rp
1319 call this%glb_intrp_comm%sendrecv(this%temp_local%x, interp_values, &
1320 this%n_points_local, this%n_points)
1321 if (neko_bcknd_device .eq. 1 .and. .not. on_host .and. &
1322 this%n_points .gt. 0) then
1323 interp_d = device_get_ptr(interp_values)
1324 call device_memcpy(interp_values, interp_d, &
1325 this%n_points, host_to_device, .false.)
1326 end if
1327 else
1328 call this%local_interp%evaluate(interp_values, this%el_owner0_local, &
1329 field, this%nelv, on_host)
1330 end if
1331
1332 end subroutine global_interpolation_evaluate
1333
1334
1345 function rst_cmp(rst1, rst2, res1, res2, tol) result(rst2_better)
1346 real(kind=rp) :: rst1(3), res1(3)
1347 real(kind=rp) :: rst2(3), res2(3)
1348 real(kind=dp) :: tol
1349 logical :: rst2_better
1350 !If rst1 is invalid and rst2 is valid, take rst2
1351 ! If both invalidl, take smallest residual
1352 if (abs(rst1(1)) .gt. 1.0_xp+tol .or. &
1353 abs(rst1(2)) .gt. 1.0_xp+tol .or. &
1354 abs(rst1(3)) .gt. 1.0_xp+tol) then
1355 if (abs(rst2(1)) .le. 1.0_xp+tol .and. &
1356 abs(rst2(2)) .le. 1.0_xp+tol .and. &
1357 abs(rst2(3)) .le. 1.0_xp+tol) then
1358 rst2_better = .true.
1359 else
1360 rst2_better = (norm2(real(res2, xp)) .lt. norm2(real(res1, xp)))
1361 end if
1362 else
1364 rst2_better = (norm2(real(res2, xp)) .lt. norm2(real(res1, xp)) .and. &
1365 abs(rst2(1)) .le. 1.0_xp+tol .and. &
1366 abs(rst2(2)) .le. 1.0_xp+tol .and. &
1367 abs(rst2(3)) .le. 1.0_xp+tol)
1368 end if
1369 end function rst_cmp
1370
1371end module global_interpolation
double real
Return the device pointer for an associated Fortran array.
Definition device.F90:108
Map a Fortran array to a device (allocate and associate)
Definition device.F90:78
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:84
Implements aabb_pe_finder given a dofmap.
integer, parameter, public glob_map_size
Minimum number of total boxes in the aabb tree.
Implements cartesian_pe_finder given a dofmap.
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
integer, public pe_rank
MPI rank.
Definition comm.F90:59
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 host_to_device
Definition device.F90:48
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition device.F90:238
integer, parameter, public device_to_host
Definition device.F90:48
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
Defines global interpolation communication Based on the MPI based gather-scatter kernel.
Implements global_interpolation given a dofmap.
subroutine global_interpolation_free(this)
Destructor.
subroutine global_interpolation_find_coords1d(this, x, y, z, n_points)
Finds the corresponding r,s,t coordinates in the correct global element as well as which process that...
subroutine global_interpolation_init_json_dof(this, dof, params_subdict, comm, mask)
Initialize the global interpolation object on a dofmap.
subroutine global_interpolation_free_points(this)
Destructor for point arrays.
real(kind=dp), parameter, public glob_interp_tol
subroutine global_interpolation_init_point_arrays(this)
subroutine global_interpolation_init_redist_comm(this, redist_comm)
Build a communicator that redistributes point-wise payloads from the original point ordering to the l...
subroutine global_interpolation_evaluate(this, interp_values, field, on_host)
Evalute the interpolated value in the points given a field.
subroutine global_interpolation_free_points_local(this)
subroutine global_interpolation_init_dof(this, dof, comm, tol, pad, mask)
Initialize the global interpolation object on a dofmap.
subroutine global_interpolation_find_coords(this, x, y, z, n_points)
Finds the corresponding r,s,t coordinates in the correct global element as well as which process that...
logical function rst_cmp(rst1, rst2, res1, res2, tol)
Compares two sets of rst coordinates and checks whether rst2 is better than rst1 given a tolerance re...
real(kind=dp), parameter, public glob_interp_pad
subroutine global_interpolation_init_xyz(this, x, y, z, gdim, nelv, xh, comm, tol, pad)
Initialize the global interpolation object on a set of coordinates.
subroutine global_interpolation_find_xyz(this, xyz, n_points)
Finds the corresponding r,s,t coordinates in the correct global element as well as which process that...
subroutine global_interpolation_init_json_xyz(this, x, y, z, gdim, nelv, xh, params_subdict, comm)
Initialize the global interpolation object on a set of coordinates, with configuration parameters giv...
subroutine global_interpolation_find_and_redist(this, xyz, n_points)
Finds the corresponding r,s,t coordinates and redistributes the points to the owning rank in the corr...
subroutine global_interpolation_find_common(this)
Common routine for finding the points.
subroutine global_interpolation_check_points(this, x, y, z)
Check the points for validity This is used to check that the points are valid and that the interpolat...
subroutine global_interpolation_evaluate_masked(this, interp_values, field, mask, on_host)
Evaluate the interpolated value in a masked field.
Utilities for retrieving parameters from the case files.
Routines to obtain interpolated values on a set of points with known rst coordinates in elements loca...
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.f90:60
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:291
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.f90:70
Defines a matrix.
Definition matrix.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public xp
Definition num_types.f90:14
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements pe_finder given a dofmap.
Definition pe_finder.f90:35
Defines a function space.
Definition space.f90:34
Implements a dynamic stack ADT.
Definition stack.f90:49
Defines structs that are used... Dont know if we should keep it though.
Definition structs.f90:2
Utilities.
Definition utils.f90:35
subroutine, public vector_masked_gather_copy(a, b, mask, n)
Gather a vector to reduced contigous array .
Defines a vector.
Definition vector.f90:34
Implements global interpolation for arbitrary points in the domain.
Implements global interpolation for arbitrary points in the domain.
Implements global interpolation for arbitrary points in the domain.
Base type for element finder providing element candidates for a given point in the domain.
Definition el_finder.f90:43
Global interpolation communication method.
Implements the settings helper data container for global interpolation.
Implements global interpolation for arbitrary points in the domain.
Type to compute local element (rst) coordinates for a gives set points in physical (xyz) space on a S...
Interpolation on a set of points with known rst coordinates in elements local to this process....
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51
Implements global interpolation for arbitrary points in the domain.
Definition pe_finder.f90:44
The function space for the SEM solution fields.
Definition space.f90:64
Integer based stack.
Definition stack.f90:77
Pointer to array.
Definition structs.f90:14
#define max(a, b)
Definition tensor.cu:40