333 real(kind=
rp),
intent(in) :: x(:)
334 real(kind=
rp),
intent(in) :: y(:)
335 real(kind=
rp),
intent(in) :: z(:)
336 integer,
intent(in) :: gdim
337 integer,
intent(in) :: nelv
338 type(
space_t),
intent(in) :: Xh
339 type(mpi_comm),
intent(in),
optional :: comm
340 real(kind=
dp),
intent(in),
optional :: tol
341 real(kind=
dp),
intent(in),
optional :: pad
343 integer :: lx, ly, lz, ierr, i, n
344 character(len=8000) :: log_buf
346 real(kind=
rp) :: time1, time_start
347 character(len=255) :: mode_str
348 integer :: boxdim, envvar_len
350 call neko_log%section(
'Global Interpolation')
351 call neko_log%message(
'Initializing global interpolation')
356 if (
present(
comm))
then
364 if (
present(pad)) this%padding = pad
367 if (
present(tol)) this%tolerance = tol
369 write(log_buf,
'(A,E15.7)') &
370 'Tolerance: ', this%tolerance
372 write(log_buf,
'(A,E15.7)') &
373 'Padding : ', this%padding
376 time_start = mpi_wtime()
377 call mpi_barrier(this%comm)
379 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
380 call mpi_comm_size(this%comm, this%pe_size, ierr)
385 call mpi_allreduce(nelv, this%glb_nelv, 1, mpi_integer, &
386 mpi_sum, this%comm, ierr)
394 call copy(this%x%x, x, n)
396 call copy(this%y%x, y, n)
398 call copy(this%z%x, z, n)
400 call this%Xh%init(xh%t, lx, ly, lz)
403 if (this%n_dof == -1)
then
408 call get_environment_variable(
"NEKO_GLOBAL_INTERP_EL_FINDER", &
409 mode_str, envvar_len)
411 if (envvar_len .gt. 0)
then
412 if (mode_str(1:envvar_len) ==
'AABB')
then
416 call get_environment_variable(
"NEKO_GLOBAL_INTERP_PE_FINDER", &
417 mode_str, envvar_len)
419 if (envvar_len .gt. 0)
then
420 if (mode_str(1:envvar_len) ==
'AABB')
then
425 if (.not.
allocated(this%el_finder))
then
428 if (.not.
allocated(this%pe_finder))
then
431 select type (el_find => this%el_finder)
433 call neko_log%message(
'Using AABB element finder')
434 call el_find%init(x, y, z, nelv, xh, this%padding)
436 call neko_log%message(
'Using Cartesian element finder')
437 boxdim =
max(lx*int(
real(nelv,
xp)**(1.0_xp / 3.0_xp)), 2)
438 boxdim = min(boxdim, 300)
439 call el_find%init(x, y, z, nelv, xh, boxdim, this%padding)
441 call neko_error(
'Unknown element finder type')
444 select type (pe_find => this%pe_finder)
446 call neko_log%message(
'Using AABB PE finder')
447 call pe_find%init(this%x%x, this%y%x, this%z%x, &
448 nelv, xh, this%comm, this%padding)
450 call neko_log%message(
'Using Cartesian PE finder')
451 boxdim = lx*int(
real(this%glb_nelv,
xp)**(1.0_xp / 3.0_xp))
452 boxdim =
max(boxdim, 32)
453 boxdim = min(boxdim, &
454 int(8.0_xp*(30000.0_xp * this%pe_size)**(1.0_xp / 3.0_xp)))
455 call pe_find%init(this%x%x, this%y%x, this%z%x, &
456 nelv, xh, this%comm, boxdim, this%padding)
461 call this%rst_finder%init(this%x%x, this%y%x, this%z%x, nelv, xh, &
463 if (
allocated(this%n_points_pe))
deallocate(this%n_points_pe)
464 if (
allocated(this%n_points_pe_local))
deallocate(this%n_points_pe_local)
465 if (
allocated(this%n_points_offset_pe_local)) &
466 deallocate(this%n_points_offset_pe_local)
467 if (
allocated(this%n_points_offset_pe))
deallocate(this%n_points_offset_pe)
468 allocate(this%n_points_pe(0:(this%pe_size-1)))
469 allocate(this%n_points_offset_pe(0:(this%pe_size-1)))
470 allocate(this%n_points_pe_local(0:(this%pe_size-1)))
471 allocate(this%n_points_offset_pe_local(0:(this%pe_size-1)))
472 allocate(this%points_at_pe(0:(this%pe_size-1)))
473 do i = 0, this%pe_size-1
474 call this%points_at_pe(i)%init()
476 call mpi_barrier(this%comm)
478 write(log_buf,
'(A,E15.7)') &
479 'Global interpolation initialized (s):', time1-time_start
574 character(len=8000) :: log_buf
582 type(c_ptr) :: el_cands_d
584 integer :: i, j, stupid_intent
586 integer,
allocatable :: n_el_cands(:)
587 integer,
contiguous,
pointer :: el_cands(:), point_ids(:), send_recv(:)
588 real(kind=
rp),
allocatable :: res_results(:,:)
589 real(kind=
rp),
allocatable :: rst_results(:,:)
590 integer,
allocatable :: el_owner_results(:)
591 integer :: ierr, ii, n_point_cand, n_glb_point_cand, point_id, rank
592 real(kind=
rp) :: time1, time2, time_start
596 type(
stack_i4_t) :: send_pe_find, recv_pe_find
598 el_cands_d = c_null_ptr
599 call neko_log%section(
'Global Interpolation')
600 call glb_intrp_find%init_dofs(this%pe_size)
601 call send_pe_find%init()
602 call recv_pe_find%init()
603 call mpi_barrier(this%comm)
604 time_start = mpi_wtime()
605 write(log_buf,
'(A)')
'Global interpolation, finding points'
611 call this%pe_finder%find_batch(this%xyz, this%n_points, &
612 this%points_at_pe, this%n_points_pe)
613 call mpi_barrier(this%comm)
615 write(log_buf,
'(A,E15.7)') &
616 'Found PE candidates time since start of findpts (s):', &
624 this%n_points_pe_local = 0
625 this%n_points_local = 0
626 call mpi_reduce_scatter_block(this%n_points_pe, this%n_points_local, &
627 1, mpi_integer, mpi_sum, this%comm, ierr)
628 call mpi_alltoall(this%n_points_pe, 1, mpi_integer,&
629 this%n_points_pe_local, 1, mpi_integer, this%comm, ierr)
632 this%n_points_offset_pe_local(0) = 0
633 this%n_points_offset_pe(0) = 0
634 do i = 1, (this%pe_size - 1)
635 this%n_points_offset_pe_local(i) = this%n_points_pe_local(i-1)&
636 + this%n_points_offset_pe_local(i-1)
637 this%n_points_offset_pe(i) = this%n_points_pe(i-1)&
638 + this%n_points_offset_pe(i-1)
640 do i = 0, (this%pe_size-1)
641 if (this%n_points_pe(i) .gt. 0)
then
642 call send_pe_find%push(i)
643 point_ids => this%points_at_pe(i)%array()
644 do j = 1, this%n_points_pe(i)
645 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+1)
646 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+2)
647 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j)-1)+3)
650 if (this%n_points_pe_local(i) .gt. 0)
then
651 call recv_pe_find%push(i)
652 do j = 1, this%n_points_pe_local(i)
653 call glb_intrp_find%recv_dof(i)%push(3*(j + &
654 this%n_points_offset_pe_local(i) - 1) + 1)
655 call glb_intrp_find%recv_dof(i)%push(3*(j + &
656 this%n_points_offset_pe_local(i) - 1) + 2)
657 call glb_intrp_find%recv_dof(i)%push(3*(j + &
658 this%n_points_offset_pe_local(i) - 1) + 3)
665 call glb_intrp_find%init(send_pe_find, recv_pe_find, this%comm)
667 call glb_intrp_find_back%init_dofs(this%pe_size)
669 do i = 0, (this%pe_size-1)
670 send_recv => glb_intrp_find%recv_dof(i)%array()
671 do j = 1, glb_intrp_find%recv_dof(i)%size()
672 call glb_intrp_find_back%send_dof(i)%push(send_recv(j))
674 send_recv => glb_intrp_find%send_dof(i)%array()
675 do j = 1, glb_intrp_find%send_dof(i)%size()
677 call glb_intrp_find_back%recv_dof(i)%push(ii)
681 call glb_intrp_find_back%init(recv_pe_find, send_pe_find, this%comm)
684 if (
allocated(this%xyz_local))
then
685 deallocate(this%xyz_local)
687 allocate(this%xyz_local(3, this%n_points_local))
688 call glb_intrp_find%sendrecv(this%xyz, this%xyz_local, this%n_points*3, &
689 this%n_points_local*3)
691 call mpi_barrier(this%comm)
693 write(log_buf,
'(A,E15.7)') &
694 'Sent to points to PE candidates, time since start of ' &
695 //
'find_points (s):', time1 - time_start
699 call all_el_candidates%init()
701 if (
allocated(n_el_cands))
then
702 deallocate(n_el_cands)
705 allocate(n_el_cands(this%n_points_local))
707 call this%el_finder%find_batch(this%xyz_local, this%n_points_local, &
708 all_el_candidates, n_el_cands)
710 n_point_cand = all_el_candidates%size()
711 if (n_point_cand .gt. 1e8)
then
712 print *,
'Warning, many point candidates on rank', this%pe_rank, &
713 'cands:', n_point_cand, &
714 'Consider increasing number of ranks'
716 call x_t%init(n_point_cand)
717 call y_t%init(n_point_cand)
718 call z_t%init(n_point_cand)
721 do i = 1 , this%n_points_local
722 do j = 1, n_el_cands(i)
724 x_t%x(ii) = this%xyz_local(1,i)
725 y_t%x(ii) = this%xyz_local(2,i)
726 z_t%x(ii) = this%xyz_local(3,i)
730 call mpi_barrier(this%comm)
732 write(log_buf,
'(A,E15.7)') &
733 'Element candidates found, now time for finding rst, time ' // &
734 'since start of find_points (s):', time1 - time_start
736 call rst_local_cand%init(3, n_point_cand)
737 call resx%init(n_point_cand)
738 call resy%init(n_point_cand)
739 call resz%init(n_point_cand)
742 call mpi_barrier(this%comm)
744 el_cands => all_el_candidates%array()
751 call device_map(el_cands, el_cands_d, n_point_cand)
756 call this%rst_finder%find(rst_local_cand, &
758 el_cands, n_point_cand, &
767 call mpi_barrier(this%comm)
770 write(log_buf,
'(A,E15.7)') &
771 'Found rst with Newton iteration, time (s):', time2-time1
774 write(log_buf,
'(A)') &
775 'Checking validity of points and choosing best candidates.'
777 call mpi_barrier(this%comm, ierr)
779 if (
allocated(this%rst_local))
deallocate(this%rst_local)
780 if (
allocated(this%el_owner0_local))
deallocate(this%el_owner0_local)
781 allocate(this%rst_local(3, this%n_points_local))
782 allocate(this%el_owner0_local(this%n_points_local))
785 do i = 1 , this%n_points_local
786 this%xyz_local(1,i) = 10.0
787 this%xyz_local(2,i) = 10.0
788 this%xyz_local(3,i) = 10.0
789 this%rst_local(1,i) = 10.0
790 this%rst_local(2,i) = 10.0
791 this%rst_local(3,i) = 10.0
792 this%el_owner0_local(i) = -1
793 do j = 1, n_el_cands(i)
795 if (
rst_cmp(this%rst_local(:, i), rst_local_cand%x(:, ii), &
796 this%xyz_local(:, i), [resx%x(ii), resy%x(ii), resz%x(ii)], &
798 this%rst_local(1, i) = rst_local_cand%x(1, ii)
799 this%rst_local(2, i) = rst_local_cand%x(2, ii)
801 this%rst_local(3, i) = rst_local_cand%x(3, ii)
802 this%xyz_local(1,i) = resx%x(ii)
803 this%xyz_local(2,i) = resy%x(ii)
804 this%xyz_local(3,i) = resz%x(ii)
805 this%el_owner0_local(i) = el_cands(ii)
811 call res%init(3, this%n_points)
812 n_glb_point_cand = sum(this%n_points_pe)
813 if (
allocated(rst_results))
deallocate(rst_results)
814 if (
allocated(res_results))
deallocate(res_results)
815 if (
allocated(el_owner_results))
deallocate(el_owner_results)
816 allocate(rst_results(3, n_glb_point_cand))
817 allocate(res_results(3, n_glb_point_cand))
818 allocate(el_owner_results(n_glb_point_cand))
823 call glb_intrp_find_back%sendrecv(this%xyz_local, res_results, &
824 this%n_points_local*3, n_glb_point_cand*3)
825 call glb_intrp_find_back%sendrecv(this%rst_local, rst_results, &
826 this%n_points_local*3, n_glb_point_cand*3)
827 do i = 1,
size(glb_intrp_find_back%send_pe)
828 rank = glb_intrp_find_back%send_pe(i)
829 call mpi_isend(this%el_owner0_local( &
830 this%n_points_offset_pe_local(rank) + 1), &
831 this%n_points_pe_local(rank), &
832 mpi_integer, rank, 0, &
833 this%comm, glb_intrp_find_back%send_buf(i)%request, ierr)
834 glb_intrp_find_back%send_buf(i)%flag = .false.
836 do i = 1,
size(glb_intrp_find_back%recv_pe)
837 rank = glb_intrp_find_back%recv_pe(i)
838 call mpi_irecv(el_owner_results(this%n_points_offset_pe(rank)+1),&
839 this%n_points_pe(rank), &
840 mpi_integer, rank, 0, &
841 this%comm, glb_intrp_find_back%recv_buf(i)%request, ierr)
842 glb_intrp_find_back%recv_buf(i)%flag = .false.
844 call glb_intrp_find_back%nbwait_no_op()
846 do i = 1,
size(glb_intrp_find_back%recv_pe)
847 point_ids => this%points_at_pe(glb_intrp_find_back%recv_pe(i))%array()
848 do j = 1, this%n_points_pe(glb_intrp_find_back%recv_pe(i))
849 point_id = point_ids(j)
851 if (
rst_cmp(this%rst(:, point_id), rst_results(:, ii), &
852 res%x(:, point_id), res_results(:, ii), this%padding) .or. &
853 this%pe_owner(point_ids(j)) .eq. -1 )
then
854 this%rst(:, point_ids(j)) = rst_results(:, ii)
855 res%x(:, point_ids(j)) = res_results(:, ii)
856 this%pe_owner(point_ids(j)) = glb_intrp_find_back%recv_pe(i)
857 this%el_owner0(point_ids(j)) = el_owner_results(ii)
868 do i = 0, this%pe_size-1
869 call this%points_at_pe(i)%clear()
870 this%n_points_pe(i) = 0
873 do i = 1, this%n_points
875 if (this%pe_owner(i) .eq. -1 .or. this%el_owner0(i) .eq. -1)
then
876 print *,
'No owning rank found for',&
877 ' point ', stupid_intent,
' with coords', this%xyz(:,i), &
878 ' Interpolation will always yield 0.0. Try increase padding.'
880 call this%points_at_pe(this%pe_owner(i))%push(stupid_intent)
881 this%n_points_pe(this%pe_owner(i)) = &
882 this%n_points_pe(this%pe_owner(i)) + 1
885 call mpi_reduce_scatter_block(this%n_points_pe, this%n_points_local, 1, &
886 mpi_integer, mpi_sum, this%comm, ierr)
887 call mpi_alltoall(this%n_points_pe, 1, mpi_integer, &
888 this%n_points_pe_local, 1, mpi_integer, this%comm, ierr)
889 this%n_points_offset_pe_local(0) = 0
890 this%n_points_offset_pe(0) = 0
891 do i = 1, (this%pe_size - 1)
892 this%n_points_offset_pe_local(i) = this%n_points_pe_local(i-1)&
893 + this%n_points_offset_pe_local(i-1)
894 this%n_points_offset_pe(i) = this%n_points_pe(i-1)&
895 + this%n_points_offset_pe(i-1)
897 call send_pe_find%free()
898 call recv_pe_find%free()
899 call glb_intrp_find%free()
900 call send_pe_find%init()
901 call recv_pe_find%init()
902 call glb_intrp_find%init_dofs(this%pe_size)
904 do i = 0, (this%pe_size-1)
905 if (this%n_points_pe(i) .gt. 0)
then
906 call send_pe_find%push(i)
907 point_ids => this%points_at_pe(i)%array()
908 do j = 1, this%n_points_pe(i)
909 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 1)
910 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 2)
911 call glb_intrp_find%send_dof(i)%push(3*(point_ids(j) - 1) + 3)
914 if (this%n_points_pe_local(i) .gt. 0)
then
915 call recv_pe_find%push(i)
916 do j = 1, this%n_points_pe_local(i)
917 call glb_intrp_find%recv_dof(i)%push(3*(j + &
918 this%n_points_offset_pe_local(i) - 1) + 1)
919 call glb_intrp_find%recv_dof(i)%push(3*(j + &
920 this%n_points_offset_pe_local(i) - 1) + 2)
921 call glb_intrp_find%recv_dof(i)%push(3*(j + &
922 this%n_points_offset_pe_local(i) - 1) + 3)
928 call glb_intrp_find%init(send_pe_find, recv_pe_find, this%comm)
929 call glb_intrp_find%sendrecv(this%xyz, this%xyz_local, this%n_points*3, &
930 this%n_points_local*3)
931 call glb_intrp_find%sendrecv(this%rst, this%rst_local, this%n_points*3, &
932 this%n_points_local*3)
934 do i = 1,
size(glb_intrp_find%send_pe)
935 rank = glb_intrp_find%send_pe(i)
936 point_ids => this%points_at_pe(rank)%array()
937 do j = 1, this%n_points_pe(rank)
939 el_owner_results(ii) = this%el_owner0(point_ids(j))
941 call mpi_isend(el_owner_results(this%n_points_offset_pe(rank) + 1),&
942 this%n_points_pe(rank), &
943 mpi_integer, rank, 0, &
944 this%comm, glb_intrp_find%send_buf(i)%request, ierr)
945 glb_intrp_find%send_buf(i)%flag = .false.
947 do i = 1,
size(glb_intrp_find%recv_pe)
948 rank = glb_intrp_find%recv_pe(i)
949 call mpi_irecv(this%el_owner0_local( &
950 this%n_points_offset_pe_local(rank) + 1), &
951 this%n_points_pe_local(rank), &
952 mpi_integer, rank, 0, &
953 this%comm, glb_intrp_find%recv_buf(i)%request, ierr)
954 glb_intrp_find%recv_buf(i)%flag = .false.
956 call glb_intrp_find%nbwait_no_op()
958 call glb_intrp_find%free()
963 call this%glb_intrp_comm%init_dofs(this%pe_size)
964 do i = 0, (this%pe_size-1)
965 if (this%n_points_pe(i) .gt. 0)
then
967 point_ids => this%points_at_pe(i)%array()
968 do j = 1, this%n_points_pe(i)
969 call this%glb_intrp_comm%recv_dof(i)%push(point_ids(j))
972 if (this%n_points_pe_local(i) .gt. 0)
then
974 do j = 1, this%n_points_pe_local(i)
975 call this%glb_intrp_comm%send_dof(i)%push(j + &
976 this%n_points_offset_pe_local(i))
980 call this%glb_intrp_comm%init(send_pe, recv_pe, this%comm)
983 call this%temp_local%init(this%n_points_local)
984 call this%temp%init(this%n_points)
987 call this%local_interp%init(this%Xh, this%rst_local, &
994 call device_map(this%el_owner0_local, this%el_owner0_local_d, &
996 call device_memcpy(this%el_owner0_local, this%el_owner0_local_d, &
1000 call this%check_points(this%x%x, this%y%x, this%z%x)
1005 call glb_intrp_find_back%free()
1006 call send_pe_find%free()
1007 call recv_pe_find%free()
1011 call rst_local_cand%free()
1016 call all_el_candidates%free()
1018 if (
allocated(n_el_cands))
deallocate(n_el_cands)
1019 if (
allocated(rst_results))
deallocate(rst_results)
1020 if (
allocated(res_results))
deallocate(res_results)
1021 if (
allocated(el_owner_results))
deallocate(el_owner_results)
1022 call mpi_barrier(this%comm, ierr)
1024 write(log_buf,
'(A,E15.7)')
'Global interpolation find points ' // &
1025 'done, time (s):', time2-time_start