126 real(kind=
rp),
intent(in),
target :: x(:)
127 real(kind=
rp),
intent(in),
target :: y(:)
128 real(kind=
rp),
intent(in),
target :: z(:)
129 integer,
intent(in) :: nelv
130 type(mpi_comm),
intent(in),
optional :: comm
131 type(
space_t),
intent(in),
target :: Xh
132 integer,
intent(in) :: n_boxes
133 real(kind=
dp),
intent(in) :: padding
135 integer :: i, j, k, e, i2, j2, k2
136 integer :: pe_id, lin_idx
138 integer(kind=i8) :: glob_id, loc_id
139 integer(kind=i8) :: min_id(3), max_id(3)
140 real(kind=
rp) :: center_x, center_y, center_z
141 type(
stack_i8_t),
allocatable :: glob_ids(:), recv_ids(:)
142 integer(i8),
pointer :: glb_ids(:)
143 integer(kind=i8) :: htable_data, temp
144 integer,
allocatable :: n_recv(:), n_send(:)
146 real(kind=
rp) :: min_bb_x, max_bb_x
147 real(kind=
rp) :: min_bb_y, max_bb_y
148 real(kind=
rp) :: min_bb_z, max_bb_z
149 real(kind=
rp) :: el_x(xh%lxyz), el_y(xh%lxyz), el_z(xh%lxyz)
153 this%padding = padding
155 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
156 call mpi_comm_size(this%comm, this%pe_size, ierr)
158 this%glob_n_boxes = int(n_boxes,
i8)**3
159 this%n_boxes = n_boxes
161 this%n_boxes_per_pe = (this%glob_n_boxes+int(this%pe_size-1,
i8))/int(this%pe_size,
i8)
163 allocate(this%send_buf(0:this%pe_size-1))
164 allocate(this%recv_buf(0:this%pe_size-1))
165 allocate(this%pe_map(0:this%n_boxes_per_pe-1))
166 do i = 0, this%n_boxes_per_pe-1
167 call this%pe_map(i)%init()
169 call mpi_exscan(this%nelv, this%offset_el, 1, &
170 mpi_integer, mpi_sum, this%comm, ierr)
171 if (this%nelv .gt. 0)
then
172 this%max_x_global = maxval(x(1:nelv*xh%lxyz))
173 this%max_y_global = maxval(y(1:nelv*xh%lxyz))
174 this%max_z_global = maxval(z(1:nelv*xh%lxyz))
175 this%min_x_global = minval(x(1:nelv*xh%lxyz))
176 this%min_y_global = minval(y(1:nelv*xh%lxyz))
177 this%min_z_global = minval(z(1:nelv*xh%lxyz))
179 this%max_x_global = -1e20
180 this%max_y_global = -1e20
181 this%max_z_global = -1e20
182 this%min_x_global = 1e20
183 this%min_y_global = 1e20
184 this%min_z_global = 1e20
189 mpi_max, this%comm, ierr)
191 mpi_max, this%comm, ierr)
193 mpi_max, this%comm, ierr)
195 mpi_min, this%comm, ierr)
197 mpi_min, this%comm, ierr)
199 mpi_min, this%comm, ierr)
201 center_x = (this%max_x_global + this%min_x_global) / 2.0_dp
202 center_y = (this%max_y_global + this%min_y_global) / 2.0_dp
203 center_z = (this%max_z_global + this%min_z_global) / 2.0_dp
205 this%max_x_global = this%max_x_global - center_x
206 this%max_y_global = this%max_y_global - center_y
207 this%max_z_global = this%max_z_global - center_z
208 this%min_x_global = this%min_x_global - center_x
209 this%min_y_global = this%min_y_global - center_y
210 this%min_z_global = this%min_z_global - center_z
211 this%max_x_global = this%max_x_global*(1.0_xp+this%padding) + center_x
212 this%max_y_global = this%max_y_global*(1.0_xp+this%padding) + center_y
213 this%max_z_global = this%max_z_global*(1.0_xp+this%padding) + center_z
214 this%min_x_global = this%min_x_global*(1.0_xp+this%padding) + center_x
215 this%min_y_global = this%min_y_global*(1.0_xp+this%padding) + center_y
216 this%min_z_global = this%min_z_global*(1.0_xp+this%padding) + center_z
219 this%res_x = (this%max_x_global - this%min_x_global) /
real(this%n_boxes,
xp)
220 this%res_y = (this%max_y_global - this%min_y_global) /
real(this%n_boxes,
xp)
221 this%res_z = (this%max_z_global - this%min_z_global) /
real(this%n_boxes,
xp)
222 if (
allocated(recv_ids))
then
223 do i = 0, this%pe_size-1
224 call recv_ids(i)%free()
228 if (
allocated(glob_ids))
then
229 do i = 0, this%pe_size-1
230 call glob_ids(i)%free()
234 if (
allocated(n_recv))
deallocate(n_recv)
235 if (
allocated(n_send))
deallocate(n_send)
236 allocate(n_recv(0:this%pe_size-1))
237 allocate(n_send(0:this%pe_size-1))
238 allocate(recv_ids(0:this%pe_size-1))
239 allocate(glob_ids(0:this%pe_size-1))
240 do i = 0, this%pe_size-1
241 call recv_ids(i)%init()
242 call glob_ids(i)%init()
243 if (
allocated(this%recv_buf(i)%data))
then
244 deallocate(this%recv_buf(i)%data)
246 if (
allocated(this%send_buf(i)%data))
then
247 deallocate(this%send_buf(i)%data)
249 this%send_buf(i)%size = 0
250 this%recv_buf(i)%size = 0
256 call marked_box%init(this%nelv*lxyz,htable_data)
261 if (mod(xh%lx,2) .eq. 0)
then
262 lin_idx =
linear_index(lx2, lx2, lx2, e, xh%lx, xh%lx, xh%lx)
263 center_x = x(lin_idx)
264 center_y = y(lin_idx)
265 center_z = z(lin_idx)
274 center_x = center_x + x(lin_idx)
275 center_y = center_y + y(lin_idx)
276 center_z = center_z + z(lin_idx)
280 center_x = center_x / 8.0_xp
281 center_y = center_y / 8.0_xp
282 center_z = center_z / 8.0_xp
287 el_x = x((e-1)*lxyz+1:e*lxyz) - center_x
288 el_y = y((e-1)*lxyz+1:e*lxyz) - center_y
289 el_z = z((e-1)*lxyz+1:e*lxyz) - center_z
290 el_x = el_x * (1.0_rp+padding) + center_x
291 el_y = el_y * (1.0_rp+padding) + center_y
292 el_z = el_z * (1.0_rp+padding) + center_z
300 max_bb_x = el_x(lin_idx)
301 min_bb_x = el_x(lin_idx)
302 max_bb_y = el_y(lin_idx)
303 min_bb_y = el_y(lin_idx)
304 max_bb_z = el_z(lin_idx)
305 min_bb_z = el_z(lin_idx)
309 lin_idx =
linear_index(i+i2,j+j2,k+k2, 1, xh%lx, xh%lx, xh%lx)
310 max_bb_x =
max(max_bb_x, el_x(lin_idx))
311 min_bb_x = min(min_bb_x, el_x(lin_idx))
312 max_bb_y =
max(max_bb_y, el_y(lin_idx))
313 min_bb_y = min(min_bb_y, el_y(lin_idx))
314 max_bb_z =
max(max_bb_z, el_z(lin_idx))
315 min_bb_z = min(min_bb_z, el_z(lin_idx))
323 do i2 = min_id(1), max_id(1)
324 do j2 = min_id(2), max_id(2)
325 do k2 = min_id(3), max_id(3)
326 if (i2 .ge. 0 .and. i2 .lt. this%n_boxes .and. &
327 j2 .ge. 0 .and. j2 .lt. this%n_boxes .and. &
328 k2 .ge. 0 .and. k2 .lt. this%n_boxes)
then
329 glob_id = i2 + j2*this%n_boxes + k2*this%n_boxes**2
331 if (marked_box%get(glob_id,htable_data) .ne. 0)
then
332 call glob_ids(pe_id)%push(glob_id)
333 n_send(pe_id) = n_send(pe_id) + 1
334 call marked_box%set(glob_id, htable_data)
357 do i = 0, this%pe_size-1
358 if (
allocated(this%recv_buf(i)%data))
then
359 deallocate(this%recv_buf(i)%data)
361 if (
allocated(this%send_buf(i)%data))
then
362 deallocate(this%send_buf(i)%data)
364 this%send_buf(i)%size = 0
365 this%recv_buf(i)%size = 0
369 call mpi_barrier(this%comm, ierr)
370 do i = 0, this%pe_size-1
371 if (n_recv(i) .gt. 0)
then
372 glb_ids => recv_ids(i)%array()
375 loc_id = glob_id - int(this%pe_rank,
i8) * &
376 int(this%n_boxes_per_pe,
i8)
377 if (loc_id .ge. this%n_boxes_per_pe .or. loc_id < 0)
then
380 call this%pe_map(int(loc_id))%push(i)
385 if (
allocated(recv_ids))
then
386 do i = 0, this%pe_size-1
387 call recv_ids(i)%free()
391 if (
allocated(glob_ids))
then
392 do i = 0, this%pe_size-1
393 call glob_ids(i)%free()
397 if (
allocated(n_recv))
deallocate(n_recv)
398 if (
allocated(n_send))
deallocate(n_send)
461 integer,
intent(in) :: n_points
462 real(kind=
rp),
intent(in) :: points(3,n_points)
464 integer,
intent(inout) :: n_points_pe(0:(this%
pe_size-1))
466 integer(kind=i8) :: glob_id(3)
467 integer(kind=i8) :: pe_id
468 integer(kind=i8) :: lin_glob_id
469 integer(kind=i8) :: loc_id
470 type(
stack_i8_t),
allocatable :: work_pe_ids(:), work_pt_ids(:)
471 type(
stack_i8_t),
allocatable :: temp_pe_ids(:), temp_pt_ids(:)
472 integer,
allocatable :: n_work_ids(:), n_temp_ids(:)
473 integer(i8),
pointer :: ids(:)
474 integer(i8),
pointer :: pt_id(:)
475 integer,
pointer :: pe_cands(:)
476 integer(i8),
pointer :: pe_cands8(:)
477 integer(i8),
pointer :: pt_ids(:)
480 allocate(work_pe_ids(0:this%pe_size-1))
481 allocate(work_pt_ids(0:this%pe_size-1))
482 allocate(temp_pe_ids(0:this%pe_size-1))
483 allocate(temp_pt_ids(0:this%pe_size-1))
484 allocate(n_temp_ids(0:this%pe_size-1))
485 allocate(n_work_ids(0:this%pe_size-1))
487 do i = 0, this%pe_size-1
490 call work_pt_ids(i)%init()
491 call work_pe_ids(i)%init()
492 call temp_pe_ids(i)%init()
493 call temp_pt_ids(i)%init()
496 do i = 0, this%pe_size-1
497 call points_at_pe(i)%clear()
505 glob_id =
get_global_idx(this, points(1,i), points(2,i), points(3,i))
506 lin_glob_id = glob_id(1) + &
507 glob_id(2)*this%n_boxes + &
508 glob_id(3)*this%n_boxes**2
510 if (glob_id(1) .ge. 0 .and. glob_id(1) .lt. this%n_boxes .and. &
511 glob_id(2) .ge. 0 .and. glob_id(2) .lt. this%n_boxes .and. &
512 glob_id(3) .ge. 0 .and. glob_id(3) .lt. this%n_boxes)
then
513 call work_pe_ids(pe_id)%push(lin_glob_id)
514 call work_pt_ids(pe_id)%push(int(i,
i8))
515 n_work_ids(pe_id) = n_work_ids(pe_id) + 1
517 print *,
'Point found outside domain:', points(1,i), &
518 points(2,i), points(3,i), &
519 'Computed global id:', lin_glob_id, &
520 'Global box id (x,y,z):', glob_id(1), glob_id(2), glob_id(3)
528 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
529 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
530 call mpi_barrier(this%comm, ierr)
534 do i = 0, this%pe_size-1
535 call work_pe_ids(i)%clear()
536 call work_pt_ids(i)%clear()
539 do i =0 , this%pe_size-1
541 if (n_temp_ids(i) .gt. 0)
then
542 ids => temp_pe_ids(i)%array()
543 pt_ids => temp_pt_ids(i)%array()
544 do j = 1, n_temp_ids(i)
545 loc_id = ids(j) - int(this%pe_rank,
i8) * &
546 int(this%n_boxes_per_pe,
i8)
547 pe_cands => this%pe_map(int(loc_id))%array()
548 do k = 1, this%pe_map(int(loc_id))%size()
549 call work_pe_ids(i)%push(int(pe_cands(k),
i8))
550 call work_pt_ids(i)%push(pt_ids(j))
551 n_work_ids(i) = n_work_ids(i) + 1
553 if (this%pe_map(int(loc_id))%size() .lt. 1)
then
554 print *,
'No PE candidates found for point:', &
555 points(1,pt_ids(j)), &
556 points(2,pt_ids(j)), points(3,pt_ids(j))
564 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
565 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
569 do i = 0, this%pe_size-1
570 if (n_temp_ids(i) .gt. 0)
then
571 pe_cands8 => temp_pe_ids(i)%array()
572 pt_ids => temp_pt_ids(i)%array()
573 do j = 1, n_temp_ids(i)
575 call points_at_pe(pe_id)%push(int(pt_ids(j)))
576 n_points_pe(pe_id) = n_points_pe(pe_id) + 1
581 if (
allocated(work_pe_ids))
then
582 do i = 0, this%pe_size-1
583 call work_pe_ids(i)%free()
585 deallocate(work_pe_ids)
587 if (
allocated(temp_pe_ids))
then
588 do i = 0, this%pe_size-1
589 call temp_pe_ids(i)%free()
591 deallocate(temp_pe_ids)
593 if (
allocated(temp_pt_ids))
then
594 do i = 0, this%pe_size-1
595 call temp_pt_ids(i)%free()
597 deallocate(temp_pt_ids)
599 if (
allocated(work_pt_ids))
then
600 do i = 0, this%pe_size-1
601 call work_pt_ids(i)%free()
603 deallocate(work_pt_ids)
606 if (
allocated(n_work_ids))
then
607 deallocate(n_work_ids)
610 if (
allocated(n_temp_ids))
then
611 deallocate(n_temp_ids)
617 send_values, n_send_values)
619 type(
stack_i8_t),
intent(inout) :: recv_values(0:this%pe_size-1)
620 type(
stack_i8_t),
intent(inout) :: send_values(0:this%pe_size-1)
621 integer,
intent(inout) :: n_recv_values(0:this%pe_size-1)
622 integer,
intent(inout) :: n_send_values(0:this%pe_size-1)
623 integer :: i, j, ierr
625 integer(i8) ,
pointer :: sp(:)
627 call mpi_alltoall(n_send_values, 1, mpi_integer, &
628 n_recv_values, 1, mpi_integer, this%comm, ierr)
630 do i = 0, this%pe_size-1
631 if (n_recv_values(i) .gt. 0)
then
632 if (this%recv_buf(i)%size .lt. n_recv_values(i))
then
633 if (
allocated(this%recv_buf(i)%data))
deallocate(this%recv_buf(i)%data)
634 allocate(this%recv_buf(i)%data(n_recv_values(i)))
635 this%recv_buf(i)%size = n_recv_values(i)
637 call mpi_irecv(this%recv_buf(i)%data, n_recv_values(i), mpi_integer8, &
638 i, 0, this%comm, this%recv_buf(i)%request, ierr)
642 do i = 0, this%pe_size-1
643 if (n_send_values(i) .gt. 0)
then
644 if (this%send_buf(i)%size .lt. n_send_values(i))
then
645 if (
allocated(this%send_buf(i)%data))
deallocate(this%send_buf(i)%data)
646 allocate(this%send_buf(i)%data(n_send_values(i)))
647 this%send_buf(i)%size = n_send_values(i)
650 sp => send_values(i)%array()
651 do j = 1, n_send_values(i)
652 this%send_buf(i)%data(j) = sp(j)
654 call mpi_isend(this%send_buf(i)%data, n_send_values(i), mpi_integer8, &
655 i, 0, this%comm, this%send_buf(i)%request, ierr)
659 do i = 0, this%pe_size-1
660 call recv_values(i)%clear()
663 do i = 0, this%pe_size-1
664 if (n_recv_values(i) .gt. 0)
then
665 call mpi_wait(this%recv_buf(i)%request, this%recv_buf(i)%status, ierr)
666 do j = 1, n_recv_values(i)
667 idx = this%recv_buf(i)%data(j)
668 call recv_values(i)%push(idx)
672 do i = 0, this%pe_size-1
673 if (n_send_values(i) .gt. 0)
then
674 call mpi_wait(this%send_buf(i)%request, this%send_buf(i)%status, ierr)