125 real(kind=
rp),
intent(in),
target :: x(:)
126 real(kind=
rp),
intent(in),
target :: y(:)
127 real(kind=
rp),
intent(in),
target :: z(:)
128 integer,
intent(in) :: nelv
129 type(mpi_comm),
intent(in),
optional :: comm
130 type(
space_t),
intent(in),
target :: Xh
131 integer,
intent(in) :: n_boxes
132 real(kind=
dp),
intent(in) :: padding
134 integer :: i, j, k, e, i2, j2, k2
135 integer :: pe_id, lin_idx
137 integer(kind=i8) :: glob_id, loc_id
138 integer(kind=i8) :: min_id(3), max_id(3)
139 real(kind=
rp) :: center_x, center_y, center_z
140 type(
stack_i8_t),
allocatable :: glob_ids(:), recv_ids(:)
141 integer(i8),
pointer :: glb_ids(:)
142 integer(kind=i8) :: htable_data
143 integer,
allocatable :: n_recv(:), n_send(:)
145 real(kind=
rp) :: min_bb_x, max_bb_x
146 real(kind=
rp) :: min_bb_y, max_bb_y
147 real(kind=
rp) :: min_bb_z, max_bb_z
148 real(kind=
rp) :: el_x(xh%lxyz), el_y(xh%lxyz), el_z(xh%lxyz)
152 this%padding = padding
154 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
155 call mpi_comm_size(this%comm, this%pe_size, ierr)
157 this%glob_n_boxes = int(n_boxes,
i8)**3
158 this%n_boxes = n_boxes
160 this%n_boxes_per_pe = (this%glob_n_boxes + int(this%pe_size - 1,
i8))/ &
161 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)
456 integer,
intent(in) :: n_points
457 real(kind=
rp),
intent(in) :: points(3,n_points)
459 integer,
intent(inout) :: n_points_pe(0:(this%
pe_size-1))
461 integer(kind=i8) :: glob_id(3)
462 integer(kind=i8) :: pe_id
463 integer(kind=i8) :: lin_glob_id
464 integer(kind=i8) :: loc_id
465 type(
stack_i8_t),
allocatable :: work_pe_ids(:), work_pt_ids(:)
466 type(
stack_i8_t),
allocatable :: temp_pe_ids(:), temp_pt_ids(:)
467 integer,
allocatable :: n_work_ids(:), n_temp_ids(:)
468 integer(i8),
pointer :: ids(:)
469 integer(i8),
pointer :: pt_id(:)
470 integer,
pointer :: pe_cands(:)
471 integer(i8),
pointer :: pe_cands8(:)
472 integer(i8),
pointer :: pt_ids(:)
475 allocate(work_pe_ids(0:this%pe_size-1))
476 allocate(work_pt_ids(0:this%pe_size-1))
477 allocate(temp_pe_ids(0:this%pe_size-1))
478 allocate(temp_pt_ids(0:this%pe_size-1))
479 allocate(n_temp_ids(0:this%pe_size-1))
480 allocate(n_work_ids(0:this%pe_size-1))
482 do i = 0, this%pe_size-1
485 call work_pt_ids(i)%init()
486 call work_pe_ids(i)%init()
487 call temp_pe_ids(i)%init()
488 call temp_pt_ids(i)%init()
491 do i = 0, this%pe_size-1
492 call points_at_pe(i)%clear()
500 glob_id =
get_global_idx(this, points(1,i), points(2,i), points(3,i))
501 lin_glob_id = glob_id(1) + &
502 glob_id(2)*this%n_boxes + &
503 glob_id(3)*this%n_boxes**2
505 if (glob_id(1) .ge. 0 .and. glob_id(1) .lt. this%n_boxes .and. &
506 glob_id(2) .ge. 0 .and. glob_id(2) .lt. this%n_boxes .and. &
507 glob_id(3) .ge. 0 .and. glob_id(3) .lt. this%n_boxes)
then
508 call work_pe_ids(pe_id)%push(lin_glob_id)
509 call work_pt_ids(pe_id)%push(int(i,
i8))
510 n_work_ids(pe_id) = n_work_ids(pe_id) + 1
512 print *,
'Point found outside domain:', points(1,i), &
513 points(2,i), points(3,i), &
514 'Computed global id:', lin_glob_id, &
515 'Global box id (x,y,z):', glob_id(1), glob_id(2), glob_id(3)
523 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
524 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
525 call mpi_barrier(this%comm, ierr)
529 do i = 0, this%pe_size-1
530 call work_pe_ids(i)%clear()
531 call work_pt_ids(i)%clear()
534 do i =0 , this%pe_size-1
536 if (n_temp_ids(i) .gt. 0)
then
537 ids => temp_pe_ids(i)%array()
538 pt_ids => temp_pt_ids(i)%array()
539 do j = 1, n_temp_ids(i)
540 loc_id = ids(j) - int(this%pe_rank,
i8) * &
541 int(this%n_boxes_per_pe,
i8)
542 pe_cands => this%pe_map(int(loc_id))%array()
543 do k = 1, this%pe_map(int(loc_id))%size()
544 call work_pe_ids(i)%push(int(pe_cands(k),
i8))
545 call work_pt_ids(i)%push(pt_ids(j))
546 n_work_ids(i) = n_work_ids(i) + 1
548 if (this%pe_map(int(loc_id))%size() .lt. 1)
then
549 print *,
'No PE candidates found for point:', &
550 points(1,pt_ids(j)), &
551 points(2,pt_ids(j)), points(3,pt_ids(j))
559 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
560 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
564 do i = 0, this%pe_size-1
565 if (n_temp_ids(i) .gt. 0)
then
566 pe_cands8 => temp_pe_ids(i)%array()
567 pt_ids => temp_pt_ids(i)%array()
568 do j = 1, n_temp_ids(i)
570 call points_at_pe(pe_id)%push(int(pt_ids(j)))
571 n_points_pe(pe_id) = n_points_pe(pe_id) + 1
576 if (
allocated(work_pe_ids))
then
577 do i = 0, this%pe_size-1
578 call work_pe_ids(i)%free()
580 deallocate(work_pe_ids)
582 if (
allocated(temp_pe_ids))
then
583 do i = 0, this%pe_size-1
584 call temp_pe_ids(i)%free()
586 deallocate(temp_pe_ids)
588 if (
allocated(temp_pt_ids))
then
589 do i = 0, this%pe_size-1
590 call temp_pt_ids(i)%free()
592 deallocate(temp_pt_ids)
594 if (
allocated(work_pt_ids))
then
595 do i = 0, this%pe_size-1
596 call work_pt_ids(i)%free()
598 deallocate(work_pt_ids)
601 if (
allocated(n_work_ids))
then
602 deallocate(n_work_ids)
605 if (
allocated(n_temp_ids))
then
606 deallocate(n_temp_ids)
612 send_values, n_send_values)
614 type(
stack_i8_t),
intent(inout) :: recv_values(0:this%pe_size-1)
615 type(
stack_i8_t),
intent(inout) :: send_values(0:this%pe_size-1)
616 integer,
intent(inout) :: n_recv_values(0:this%pe_size-1)
617 integer,
intent(inout) :: n_send_values(0:this%pe_size-1)
618 integer :: i, j, ierr
620 integer(i8) ,
pointer :: sp(:)
622 call mpi_alltoall(n_send_values, 1, mpi_integer, &
623 n_recv_values, 1, mpi_integer, this%comm, ierr)
625 do i = 0, this%pe_size-1
626 if (n_recv_values(i) .gt. 0)
then
627 if (this%recv_buf(i)%size .lt. n_recv_values(i))
then
628 if (
allocated(this%recv_buf(i)%data))
deallocate(this%recv_buf(i)%data)
629 allocate(this%recv_buf(i)%data(n_recv_values(i)))
630 this%recv_buf(i)%size = n_recv_values(i)
632 call mpi_irecv(this%recv_buf(i)%data, n_recv_values(i), mpi_integer8, &
633 i, 0, this%comm, this%recv_buf(i)%request, ierr)
637 do i = 0, this%pe_size-1
638 if (n_send_values(i) .gt. 0)
then
639 if (this%send_buf(i)%size .lt. n_send_values(i))
then
640 if (
allocated(this%send_buf(i)%data))
deallocate(this%send_buf(i)%data)
641 allocate(this%send_buf(i)%data(n_send_values(i)))
642 this%send_buf(i)%size = n_send_values(i)
645 sp => send_values(i)%array()
646 do j = 1, n_send_values(i)
647 this%send_buf(i)%data(j) = sp(j)
649 call mpi_isend(this%send_buf(i)%data, n_send_values(i), mpi_integer8, &
650 i, 0, this%comm, this%send_buf(i)%request, ierr)
654 do i = 0, this%pe_size-1
655 call recv_values(i)%clear()
658 do i = 0, this%pe_size-1
659 if (n_recv_values(i) .gt. 0)
then
660 call mpi_wait(this%recv_buf(i)%request, this%recv_buf(i)%status, ierr)
661 do j = 1, n_recv_values(i)
662 idx = this%recv_buf(i)%data(j)
663 call recv_values(i)%push(idx)
667 do i = 0, this%pe_size-1
668 if (n_send_values(i) .gt. 0)
then
669 call mpi_wait(this%send_buf(i)%request, this%send_buf(i)%status, ierr)