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))/ &
162 int(this%pe_size,
i8)
164 allocate(this%send_buf(0:this%pe_size - 1))
165 allocate(this%recv_buf(0:this%pe_size - 1))
166 allocate(this%pe_map(0:this%n_boxes_per_pe - 1))
167 do i = 0, this%n_boxes_per_pe - 1
168 call this%pe_map(i)%init()
170 call mpi_exscan(this%nelv, this%offset_el, 1, &
171 mpi_integer, mpi_sum, this%comm, ierr)
172 if (this%nelv .gt. 0)
then
173 this%max_x_global = maxval(x(1:nelv*xh%lxyz))
174 this%max_y_global = maxval(y(1:nelv*xh%lxyz))
175 this%max_z_global = maxval(z(1:nelv*xh%lxyz))
176 this%min_x_global = minval(x(1:nelv*xh%lxyz))
177 this%min_y_global = minval(y(1:nelv*xh%lxyz))
178 this%min_z_global = minval(z(1:nelv*xh%lxyz))
180 this%max_x_global = -1e20
181 this%max_y_global = -1e20
182 this%max_z_global = -1e20
183 this%min_x_global = 1e20
184 this%min_y_global = 1e20
185 this%min_z_global = 1e20
190 mpi_max, this%comm, ierr)
192 mpi_max, this%comm, ierr)
194 mpi_max, this%comm, ierr)
196 mpi_min, this%comm, ierr)
198 mpi_min, this%comm, ierr)
200 mpi_min, this%comm, ierr)
202 center_x = (this%max_x_global + this%min_x_global) / 2.0_dp
203 center_y = (this%max_y_global + this%min_y_global) / 2.0_dp
204 center_z = (this%max_z_global + this%min_z_global) / 2.0_dp
206 this%max_x_global = this%max_x_global - center_x
207 this%max_y_global = this%max_y_global - center_y
208 this%max_z_global = this%max_z_global - center_z
209 this%min_x_global = this%min_x_global - center_x
210 this%min_y_global = this%min_y_global - center_y
211 this%min_z_global = this%min_z_global - center_z
212 this%max_x_global = this%max_x_global*(1.0_xp+this%padding) + center_x
213 this%max_y_global = this%max_y_global*(1.0_xp+this%padding) + center_y
214 this%max_z_global = this%max_z_global*(1.0_xp+this%padding) + center_z
215 this%min_x_global = this%min_x_global*(1.0_xp+this%padding) + center_x
216 this%min_y_global = this%min_y_global*(1.0_xp+this%padding) + center_y
217 this%min_z_global = this%min_z_global*(1.0_xp+this%padding) + center_z
220 this%res_x = (this%max_x_global - this%min_x_global) /
real(this%n_boxes,
xp)
221 this%res_y = (this%max_y_global - this%min_y_global) /
real(this%n_boxes,
xp)
222 this%res_z = (this%max_z_global - this%min_z_global) /
real(this%n_boxes,
xp)
223 if (
allocated(recv_ids))
then
224 do i = 0, this%pe_size-1
225 call recv_ids(i)%free()
229 if (
allocated(glob_ids))
then
230 do i = 0, this%pe_size-1
231 call glob_ids(i)%free()
235 if (
allocated(n_recv))
deallocate(n_recv)
236 if (
allocated(n_send))
deallocate(n_send)
237 allocate(n_recv(0:this%pe_size-1))
238 allocate(n_send(0:this%pe_size-1))
239 allocate(recv_ids(0:this%pe_size-1))
240 allocate(glob_ids(0:this%pe_size-1))
241 do i = 0, this%pe_size-1
242 call recv_ids(i)%init()
243 call glob_ids(i)%init()
244 if (
allocated(this%recv_buf(i)%data))
then
245 deallocate(this%recv_buf(i)%data)
247 if (
allocated(this%send_buf(i)%data))
then
248 deallocate(this%send_buf(i)%data)
250 this%send_buf(i)%size = 0
251 this%recv_buf(i)%size = 0
257 call marked_box%init(this%nelv*lxyz,htable_data)
262 if (mod(xh%lx,2) .eq. 0)
then
263 lin_idx =
linear_index(lx2, lx2, lx2, e, xh%lx, xh%lx, xh%lx)
264 center_x = x(lin_idx)
265 center_y = y(lin_idx)
266 center_z = z(lin_idx)
275 center_x = center_x + x(lin_idx)
276 center_y = center_y + y(lin_idx)
277 center_z = center_z + z(lin_idx)
281 center_x = center_x / 8.0_xp
282 center_y = center_y / 8.0_xp
283 center_z = center_z / 8.0_xp
288 el_x = x((e-1)*lxyz+1:e*lxyz) - center_x
289 el_y = y((e-1)*lxyz+1:e*lxyz) - center_y
290 el_z = z((e-1)*lxyz+1:e*lxyz) - center_z
291 el_x = el_x * (1.0_rp+padding) + center_x
292 el_y = el_y * (1.0_rp+padding) + center_y
293 el_z = el_z * (1.0_rp+padding) + center_z
301 max_bb_x = el_x(lin_idx)
302 min_bb_x = el_x(lin_idx)
303 max_bb_y = el_y(lin_idx)
304 min_bb_y = el_y(lin_idx)
305 max_bb_z = el_z(lin_idx)
306 min_bb_z = el_z(lin_idx)
310 lin_idx =
linear_index(i+i2,j+j2,k+k2, 1, xh%lx, xh%lx, xh%lx)
311 max_bb_x =
max(max_bb_x, el_x(lin_idx))
312 min_bb_x = min(min_bb_x, el_x(lin_idx))
313 max_bb_y =
max(max_bb_y, el_y(lin_idx))
314 min_bb_y = min(min_bb_y, el_y(lin_idx))
315 max_bb_z =
max(max_bb_z, el_z(lin_idx))
316 min_bb_z = min(min_bb_z, el_z(lin_idx))
324 do i2 = min_id(1), max_id(1)
325 do j2 = min_id(2), max_id(2)
326 do k2 = min_id(3), max_id(3)
327 if (i2 .ge. 0 .and. i2 .lt. this%n_boxes .and. &
328 j2 .ge. 0 .and. j2 .lt. this%n_boxes .and. &
329 k2 .ge. 0 .and. k2 .lt. this%n_boxes)
then
330 glob_id = i2 + j2*this%n_boxes + k2*this%n_boxes**2
332 if (marked_box%get(glob_id,htable_data) .ne. 0)
then
333 call glob_ids(pe_id)%push(glob_id)
334 n_send(pe_id) = n_send(pe_id) + 1
335 call marked_box%set(glob_id, htable_data)
358 do i = 0, this%pe_size-1
359 if (
allocated(this%recv_buf(i)%data))
then
360 deallocate(this%recv_buf(i)%data)
362 if (
allocated(this%send_buf(i)%data))
then
363 deallocate(this%send_buf(i)%data)
365 this%send_buf(i)%size = 0
366 this%recv_buf(i)%size = 0
370 call mpi_barrier(this%comm, ierr)
371 do i = 0, this%pe_size-1
372 if (n_recv(i) .gt. 0)
then
373 glb_ids => recv_ids(i)%array()
376 loc_id = glob_id - int(this%pe_rank,
i8) * &
377 int(this%n_boxes_per_pe,
i8)
378 if (loc_id .ge. this%n_boxes_per_pe .or. loc_id < 0)
then
381 call this%pe_map(int(loc_id))%push(i)
386 if (
allocated(recv_ids))
then
387 do i = 0, this%pe_size-1
388 call recv_ids(i)%free()
392 if (
allocated(glob_ids))
then
393 do i = 0, this%pe_size-1
394 call glob_ids(i)%free()
398 if (
allocated(n_recv))
deallocate(n_recv)
399 if (
allocated(n_send))
deallocate(n_send)
462 integer,
intent(in) :: n_points
463 real(kind=
rp),
intent(in) :: points(3,n_points)
465 integer,
intent(inout) :: n_points_pe(0:(this%
pe_size-1))
467 integer(kind=i8) :: glob_id(3)
468 integer(kind=i8) :: pe_id
469 integer(kind=i8) :: lin_glob_id
470 integer(kind=i8) :: loc_id
471 type(
stack_i8_t),
allocatable :: work_pe_ids(:), work_pt_ids(:)
472 type(
stack_i8_t),
allocatable :: temp_pe_ids(:), temp_pt_ids(:)
473 integer,
allocatable :: n_work_ids(:), n_temp_ids(:)
474 integer(i8),
pointer :: ids(:)
475 integer(i8),
pointer :: pt_id(:)
476 integer,
pointer :: pe_cands(:)
477 integer(i8),
pointer :: pe_cands8(:)
478 integer(i8),
pointer :: pt_ids(:)
481 allocate(work_pe_ids(0:this%pe_size-1))
482 allocate(work_pt_ids(0:this%pe_size-1))
483 allocate(temp_pe_ids(0:this%pe_size-1))
484 allocate(temp_pt_ids(0:this%pe_size-1))
485 allocate(n_temp_ids(0:this%pe_size-1))
486 allocate(n_work_ids(0:this%pe_size-1))
488 do i = 0, this%pe_size-1
491 call work_pt_ids(i)%init()
492 call work_pe_ids(i)%init()
493 call temp_pe_ids(i)%init()
494 call temp_pt_ids(i)%init()
497 do i = 0, this%pe_size-1
498 call points_at_pe(i)%clear()
506 glob_id =
get_global_idx(this, points(1,i), points(2,i), points(3,i))
507 lin_glob_id = glob_id(1) + &
508 glob_id(2)*this%n_boxes + &
509 glob_id(3)*this%n_boxes**2
511 if (glob_id(1) .ge. 0 .and. glob_id(1) .lt. this%n_boxes .and. &
512 glob_id(2) .ge. 0 .and. glob_id(2) .lt. this%n_boxes .and. &
513 glob_id(3) .ge. 0 .and. glob_id(3) .lt. this%n_boxes)
then
514 call work_pe_ids(pe_id)%push(lin_glob_id)
515 call work_pt_ids(pe_id)%push(int(i,
i8))
516 n_work_ids(pe_id) = n_work_ids(pe_id) + 1
518 print *,
'Point found outside domain:', points(1,i), &
519 points(2,i), points(3,i), &
520 'Computed global id:', lin_glob_id, &
521 'Global box id (x,y,z):', glob_id(1), glob_id(2), glob_id(3)
529 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
530 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
531 call mpi_barrier(this%comm, ierr)
535 do i = 0, this%pe_size-1
536 call work_pe_ids(i)%clear()
537 call work_pt_ids(i)%clear()
540 do i =0 , this%pe_size-1
542 if (n_temp_ids(i) .gt. 0)
then
543 ids => temp_pe_ids(i)%array()
544 pt_ids => temp_pt_ids(i)%array()
545 do j = 1, n_temp_ids(i)
546 loc_id = ids(j) - int(this%pe_rank,
i8) * &
547 int(this%n_boxes_per_pe,
i8)
548 pe_cands => this%pe_map(int(loc_id))%array()
549 do k = 1, this%pe_map(int(loc_id))%size()
550 call work_pe_ids(i)%push(int(pe_cands(k),
i8))
551 call work_pt_ids(i)%push(pt_ids(j))
552 n_work_ids(i) = n_work_ids(i) + 1
554 if (this%pe_map(int(loc_id))%size() .lt. 1)
then
555 print *,
'No PE candidates found for point:', &
556 points(1,pt_ids(j)), &
557 points(2,pt_ids(j)), points(3,pt_ids(j))
565 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
566 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
570 do i = 0, this%pe_size-1
571 if (n_temp_ids(i) .gt. 0)
then
572 pe_cands8 => temp_pe_ids(i)%array()
573 pt_ids => temp_pt_ids(i)%array()
574 do j = 1, n_temp_ids(i)
576 call points_at_pe(pe_id)%push(int(pt_ids(j)))
577 n_points_pe(pe_id) = n_points_pe(pe_id) + 1
582 if (
allocated(work_pe_ids))
then
583 do i = 0, this%pe_size-1
584 call work_pe_ids(i)%free()
586 deallocate(work_pe_ids)
588 if (
allocated(temp_pe_ids))
then
589 do i = 0, this%pe_size-1
590 call temp_pe_ids(i)%free()
592 deallocate(temp_pe_ids)
594 if (
allocated(temp_pt_ids))
then
595 do i = 0, this%pe_size-1
596 call temp_pt_ids(i)%free()
598 deallocate(temp_pt_ids)
600 if (
allocated(work_pt_ids))
then
601 do i = 0, this%pe_size-1
602 call work_pt_ids(i)%free()
604 deallocate(work_pt_ids)
607 if (
allocated(n_work_ids))
then
608 deallocate(n_work_ids)
611 if (
allocated(n_temp_ids))
then
612 deallocate(n_temp_ids)
618 send_values, n_send_values)
620 type(
stack_i8_t),
intent(inout) :: recv_values(0:this%pe_size-1)
621 type(
stack_i8_t),
intent(inout) :: send_values(0:this%pe_size-1)
622 integer,
intent(inout) :: n_recv_values(0:this%pe_size-1)
623 integer,
intent(inout) :: n_send_values(0:this%pe_size-1)
624 integer :: i, j, ierr
626 integer(i8) ,
pointer :: sp(:)
628 call mpi_alltoall(n_send_values, 1, mpi_integer, &
629 n_recv_values, 1, mpi_integer, this%comm, ierr)
631 do i = 0, this%pe_size-1
632 if (n_recv_values(i) .gt. 0)
then
633 if (this%recv_buf(i)%size .lt. n_recv_values(i))
then
634 if (
allocated(this%recv_buf(i)%data))
deallocate(this%recv_buf(i)%data)
635 allocate(this%recv_buf(i)%data(n_recv_values(i)))
636 this%recv_buf(i)%size = n_recv_values(i)
638 call mpi_irecv(this%recv_buf(i)%data, n_recv_values(i), mpi_integer8, &
639 i, 0, this%comm, this%recv_buf(i)%request, ierr)
643 do i = 0, this%pe_size-1
644 if (n_send_values(i) .gt. 0)
then
645 if (this%send_buf(i)%size .lt. n_send_values(i))
then
646 if (
allocated(this%send_buf(i)%data))
deallocate(this%send_buf(i)%data)
647 allocate(this%send_buf(i)%data(n_send_values(i)))
648 this%send_buf(i)%size = n_send_values(i)
651 sp => send_values(i)%array()
652 do j = 1, n_send_values(i)
653 this%send_buf(i)%data(j) = sp(j)
655 call mpi_isend(this%send_buf(i)%data, n_send_values(i), mpi_integer8, &
656 i, 0, this%comm, this%send_buf(i)%request, ierr)
660 do i = 0, this%pe_size-1
661 call recv_values(i)%clear()
664 do i = 0, this%pe_size-1
665 if (n_recv_values(i) .gt. 0)
then
666 call mpi_wait(this%recv_buf(i)%request, this%recv_buf(i)%status, ierr)
667 do j = 1, n_recv_values(i)
668 idx = this%recv_buf(i)%data(j)
669 call recv_values(i)%push(idx)
673 do i = 0, this%pe_size-1
674 if (n_send_values(i) .gt. 0)
then
675 call mpi_wait(this%send_buf(i)%request, this%send_buf(i)%status, ierr)