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
342 integer :: lx, ly, lz, ierr, i, n
343 character(len=8000) :: log_buf
345 real(kind=
rp) :: time1, time_start
346 character(len=255) :: mode_str
347 integer :: boxdim, envvar_len
349 call neko_log%section(
'Global Interpolation')
350 call neko_log%message(
'Initializing global interpolation')
355 if (
present(
comm))
then
363 if (
present(pad)) this%padding = pad
366 if (
present(tol)) this%tolerance = tol
368 write(log_buf,
'(A,E15.7)') &
369 'Tolerance: ', this%tolerance
371 write(log_buf,
'(A,E15.7)') &
372 'Padding : ', this%padding
375 time_start = mpi_wtime()
376 call mpi_barrier(this%comm)
378 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
379 call mpi_comm_size(this%comm, this%pe_size, ierr)
384 call mpi_allreduce(nelv, this%glb_nelv, 1, mpi_integer, &
385 mpi_sum, this%comm, ierr)
393 call copy(this%x%x, x, n)
395 call copy(this%y%x, y, n)
397 call copy(this%z%x, z, n)
399 call this%Xh%init(xh%t, lx, ly, lz)
402 if (this%n_dof == -1)
then
407 call get_environment_variable(
"NEKO_GLOBAL_INTERP_EL_FINDER", &
408 mode_str, envvar_len)
410 if (envvar_len .gt. 0)
then
411 if (mode_str(1:envvar_len) ==
'AABB')
then
415 call get_environment_variable(
"NEKO_GLOBAL_INTERP_PE_FINDER", &
416 mode_str, envvar_len)
418 if (envvar_len .gt. 0)
then
419 if (mode_str(1:envvar_len) ==
'AABB')
then
424 if (.not.
allocated(this%el_finder))
then
427 if (.not.
allocated(this%pe_finder))
then
430 select type (el_find => this%el_finder)
432 call neko_log%message(
'Using AABB element finder')
433 call el_find%init(x, y, z, nelv, xh, this%padding)
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)
440 call neko_error(
'Unknown element finder type')
443 select type (pe_find => this%pe_finder)
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)
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)
460 call this%rst_finder%init(this%x%x, this%y%x, this%z%x, nelv, xh, &
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()
475 call mpi_barrier(this%comm)
477 write(log_buf,
'(A,E15.7)') &
478 'Global interpolation initialized (s):', time1-time_start
572 character(len=8000) :: log_buf
580 type(c_ptr) :: el_cands_d
582 integer :: i, j, stupid_intent
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
594 type(
stack_i4_t) :: send_pe_find, recv_pe_find
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'
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)
613 write(log_buf,
'(A,E15.7)') &
614 'Found PE candidates time since start of findpts (s):', &
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)
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)
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)
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)
663 call glb_intrp_find%init(send_pe_find, recv_pe_find, this%comm)
665 call glb_intrp_find_back%init_dofs(this%pe_size)
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))
672 send_recv => glb_intrp_find%send_dof(i)%array()
673 do j = 1, glb_intrp_find%send_dof(i)%size()
675 call glb_intrp_find_back%recv_dof(i)%push(ii)
679 call glb_intrp_find_back%init(recv_pe_find, send_pe_find, this%comm)
682 if (
allocated(this%xyz_local))
then
683 deallocate(this%xyz_local)
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)
689 call mpi_barrier(this%comm)
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
697 call all_el_candidates%init()
699 if (
allocated(n_el_cands))
then
700 deallocate(n_el_cands)
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)
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'
714 call x_t%init(n_point_cand)
715 call y_t%init(n_point_cand)
716 call z_t%init(n_point_cand)
719 do i = 1 , this%n_points_local
720 do j = 1, n_el_cands(i)
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)
728 call mpi_barrier(this%comm)
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
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)
740 call mpi_barrier(this%comm)
742 el_cands => all_el_candidates%array()
749 call device_map(el_cands, el_cands_d, n_point_cand)
754 call this%rst_finder%find(rst_local_cand, &
756 el_cands, n_point_cand, &
765 call mpi_barrier(this%comm)
768 write(log_buf,
'(A,E15.7)') &
769 'Found rst with Newton iteration, time (s):', time2-time1
772 write(log_buf,
'(A)') &
773 'Checking validity of points and choosing best candidates.'
775 call mpi_barrier(this%comm, ierr)
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))
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)
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)], &
796 this%rst_local(1, i) = rst_local_cand%x(1, ii)
797 this%rst_local(2, i) = rst_local_cand%x(2, ii)
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)
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))
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.
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.
842 call glb_intrp_find_back%nbwait_no_op()
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)
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)
866 do i = 0, this%pe_size-1
867 call this%points_at_pe(i)%clear()
868 this%n_points_pe(i) = 0
871 do i = 1, this%n_points
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.'
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
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)
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)
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)
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)
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)
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)
937 el_owner_results(ii) = this%el_owner0(point_ids(j))
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.
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.
954 call glb_intrp_find%nbwait_no_op()
956 call glb_intrp_find%free()
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
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))
970 if (this%n_points_pe_local(i) .gt. 0)
then
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))
978 call this%glb_intrp_comm%init(send_pe, recv_pe, this%comm)
981 call this%temp_local%init(this%n_points_local)
982 call this%temp%init(this%n_points)
985 call this%local_interp%init(this%Xh, this%rst_local, &
992 call device_map(this%el_owner0_local, this%el_owner0_local_d, &
994 call device_memcpy(this%el_owner0_local, this%el_owner0_local_d, &
998 call this%check_points(this%x%x, this%y%x, this%z%x)
1003 call glb_intrp_find_back%free()
1004 call send_pe_find%free()
1005 call recv_pe_find%free()
1009 call rst_local_cand%free()
1014 call all_el_candidates%free()
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)
1022 write(log_buf,
'(A,E15.7)')
'Global interpolation find points ' // &
1023 'done, time (s):', time2-time_start