115 real(kind=
rp),
intent(in),
target :: x(:)
116 real(kind=
rp),
intent(in),
target :: y(:)
117 real(kind=
rp),
intent(in),
target :: z(:)
118 integer,
intent(in) :: nelv
119 type(mpi_comm),
intent(in),
optional :: comm
120 type(
space_t),
intent(in),
target :: Xh
121 integer,
intent(in) :: n_boxes
122 real(kind=
dp),
intent(in) :: padding
124 integer :: i, j, k, e, i2, j2, k2
125 integer :: pe_id, lin_idx
127 integer(kind=i8) :: glob_id, loc_id
128 integer(kind=i8) :: min_id(3), max_id(3)
129 real(kind=
rp) :: center_x, center_y, center_z
130 type(
stack_i8_t),
allocatable :: glob_ids(:), recv_ids(:)
131 integer(i8),
pointer :: glb_ids(:)
132 integer(kind=i8) :: htable_data, temp
133 integer,
allocatable :: n_recv(:), n_send(:)
135 real(kind=
rp) :: min_bb_x, max_bb_x
136 real(kind=
rp) :: min_bb_y, max_bb_y
137 real(kind=
rp) :: min_bb_z, max_bb_z
138 real(kind=
rp) :: el_x(xh%lxyz), el_y(xh%lxyz), el_z(xh%lxyz)
142 this%padding = padding
144 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
145 call mpi_comm_size(this%comm, this%pe_size, ierr)
147 this%glob_n_boxes = int(n_boxes,
i8)**3
148 this%n_boxes = n_boxes
150 this%n_boxes_per_pe = (this%glob_n_boxes+int(this%pe_size-1,
i8))/int(this%pe_size,
i8)
152 allocate(this%send_buf(0:this%pe_size-1))
153 allocate(this%recv_buf(0:this%pe_size-1))
154 allocate(this%pe_map(0:this%n_boxes_per_pe-1))
155 do i = 0, this%n_boxes_per_pe-1
156 call this%pe_map(i)%init()
158 call mpi_exscan(this%nelv, this%offset_el, 1, &
159 mpi_integer, mpi_sum, this%comm, ierr)
160 if (this%nelv .gt. 0)
then
161 this%max_x_global = maxval(x(1:nelv*xh%lxyz))
162 this%max_y_global = maxval(y(1:nelv*xh%lxyz))
163 this%max_z_global = maxval(z(1:nelv*xh%lxyz))
164 this%min_x_global = minval(x(1:nelv*xh%lxyz))
165 this%min_y_global = minval(y(1:nelv*xh%lxyz))
166 this%min_z_global = minval(z(1:nelv*xh%lxyz))
168 this%max_x_global = -1e20
169 this%max_y_global = -1e20
170 this%max_z_global = -1e20
171 this%min_x_global = 1e20
172 this%min_y_global = 1e20
173 this%min_z_global = 1e20
178 mpi_max, this%comm, ierr)
180 mpi_max, this%comm, ierr)
182 mpi_max, this%comm, ierr)
184 mpi_min, this%comm, ierr)
186 mpi_min, this%comm, ierr)
188 mpi_min, this%comm, ierr)
190 center_x = (this%max_x_global + this%min_x_global) / 2.0_dp
191 center_y = (this%max_y_global + this%min_y_global) / 2.0_dp
192 center_z = (this%max_z_global + this%min_z_global) / 2.0_dp
194 this%max_x_global = this%max_x_global - center_x
195 this%max_y_global = this%max_y_global - center_y
196 this%max_z_global = this%max_z_global - center_z
197 this%min_x_global = this%min_x_global - center_x
198 this%min_y_global = this%min_y_global - center_y
199 this%min_z_global = this%min_z_global - center_z
200 this%max_x_global = this%max_x_global*(1.0_xp+this%padding) + center_x
201 this%max_y_global = this%max_y_global*(1.0_xp+this%padding) + center_y
202 this%max_z_global = this%max_z_global*(1.0_xp+this%padding) + center_z
203 this%min_x_global = this%min_x_global*(1.0_xp+this%padding) + center_x
204 this%min_y_global = this%min_y_global*(1.0_xp+this%padding) + center_y
205 this%min_z_global = this%min_z_global*(1.0_xp+this%padding) + center_z
208 this%res_x = (this%max_x_global - this%min_x_global) /
real(this%n_boxes,
xp)
209 this%res_y = (this%max_y_global - this%min_y_global) /
real(this%n_boxes,
xp)
210 this%res_z = (this%max_z_global - this%min_z_global) /
real(this%n_boxes,
xp)
211 if (
allocated(recv_ids))
then
212 do i = 0, this%pe_size-1
213 call recv_ids(i)%free()
217 if (
allocated(glob_ids))
then
218 do i = 0, this%pe_size-1
219 call glob_ids(i)%free()
223 if (
allocated(n_recv))
deallocate(n_recv)
224 if (
allocated(n_send))
deallocate(n_send)
225 allocate(n_recv(0:this%pe_size-1))
226 allocate(n_send(0:this%pe_size-1))
227 allocate(recv_ids(0:this%pe_size-1))
228 allocate(glob_ids(0:this%pe_size-1))
229 do i = 0, this%pe_size-1
230 call recv_ids(i)%init()
231 call glob_ids(i)%init()
232 if (
allocated(this%recv_buf(i)%data))
then
233 deallocate(this%recv_buf(i)%data)
235 if (
allocated(this%send_buf(i)%data))
then
236 deallocate(this%send_buf(i)%data)
238 this%send_buf(i)%size = 0
239 this%recv_buf(i)%size = 0
245 call marked_box%init(this%nelv*lxyz,htable_data)
250 if (mod(xh%lx,2) .eq. 0)
then
251 lin_idx =
linear_index(lx2, lx2, lx2, e, xh%lx, xh%lx, xh%lx)
252 center_x = x(lin_idx)
253 center_y = y(lin_idx)
254 center_z = z(lin_idx)
263 center_x = center_x + x(lin_idx)
264 center_y = center_y + y(lin_idx)
265 center_z = center_z + z(lin_idx)
269 center_x = center_x / 8.0_xp
270 center_y = center_y / 8.0_xp
271 center_z = center_z / 8.0_xp
276 el_x = x((e-1)*lxyz+1:e*lxyz) - center_x
277 el_y = y((e-1)*lxyz+1:e*lxyz) - center_y
278 el_z = z((e-1)*lxyz+1:e*lxyz) - center_z
279 el_x = el_x * (1.0_rp+padding) + center_x
280 el_y = el_y * (1.0_rp+padding) + center_y
281 el_z = el_z * (1.0_rp+padding) + center_z
289 max_bb_x = el_x(lin_idx)
290 min_bb_x = el_x(lin_idx)
291 max_bb_y = el_y(lin_idx)
292 min_bb_y = el_y(lin_idx)
293 max_bb_z = el_z(lin_idx)
294 min_bb_z = el_z(lin_idx)
298 lin_idx =
linear_index(i+i2,j+j2,k+k2, 1, xh%lx, xh%lx, xh%lx)
299 max_bb_x =
max(max_bb_x, el_x(lin_idx))
300 min_bb_x = min(min_bb_x, el_x(lin_idx))
301 max_bb_y =
max(max_bb_y, el_y(lin_idx))
302 min_bb_y = min(min_bb_y, el_y(lin_idx))
303 max_bb_z =
max(max_bb_z, el_z(lin_idx))
304 min_bb_z = min(min_bb_z, el_z(lin_idx))
312 do i2 = min_id(1), max_id(1)
313 do j2 = min_id(2), max_id(2)
314 do k2 = min_id(3), max_id(3)
315 if (i2 .ge. 0 .and. i2 .lt. this%n_boxes .and. &
316 j2 .ge. 0 .and. j2 .lt. this%n_boxes .and. &
317 k2 .ge. 0 .and. k2 .lt. this%n_boxes)
then
318 glob_id = i2 + j2*this%n_boxes + k2*this%n_boxes**2
320 if (marked_box%get(glob_id,htable_data) .ne. 0)
then
321 call glob_ids(pe_id)%push(glob_id)
322 n_send(pe_id) = n_send(pe_id) + 1
323 call marked_box%set(glob_id, htable_data)
346 do i = 0, this%pe_size-1
347 if (
allocated(this%recv_buf(i)%data))
then
348 deallocate(this%recv_buf(i)%data)
350 if (
allocated(this%send_buf(i)%data))
then
351 deallocate(this%send_buf(i)%data)
353 this%send_buf(i)%size = 0
354 this%recv_buf(i)%size = 0
358 call mpi_barrier(this%comm, ierr)
359 do i = 0, this%pe_size-1
360 if (n_recv(i) .gt. 0)
then
361 glb_ids => recv_ids(i)%array()
364 loc_id = glob_id - int(this%pe_rank,
i8) * &
365 int(this%n_boxes_per_pe,
i8)
366 if (loc_id .ge. this%n_boxes_per_pe .or. loc_id < 0)
then
369 call this%pe_map(int(loc_id))%push(i)
374 if (
allocated(recv_ids))
then
375 do i = 0, this%pe_size-1
376 call recv_ids(i)%free()
380 if (
allocated(glob_ids))
then
381 do i = 0, this%pe_size-1
382 call glob_ids(i)%free()
386 if (
allocated(n_recv))
deallocate(n_recv)
387 if (
allocated(n_send))
deallocate(n_send)
454 integer,
intent(in) :: n_points
455 real(kind=
rp),
intent(in) :: points(3,n_points)
457 integer,
intent(inout) :: n_points_pe(0:(this%
pe_size-1))
459 integer(kind=i8) :: glob_id(3)
460 integer(kind=i8) :: pe_id
461 integer(kind=i8) :: lin_glob_id
462 integer(kind=i8) :: loc_id
463 type(
stack_i8_t),
allocatable :: work_pe_ids(:), work_pt_ids(:)
464 type(
stack_i8_t),
allocatable :: temp_pe_ids(:), temp_pt_ids(:)
465 integer,
allocatable :: n_work_ids(:), n_temp_ids(:)
466 integer(i8),
pointer :: ids(:)
467 integer(i8),
pointer :: pt_id(:)
468 integer,
pointer :: pe_cands(:)
469 integer(i8),
pointer :: pe_cands8(:)
470 integer(i8),
pointer :: pt_ids(:)
473 allocate(work_pe_ids(0:this%pe_size-1))
474 allocate(work_pt_ids(0:this%pe_size-1))
475 allocate(temp_pe_ids(0:this%pe_size-1))
476 allocate(temp_pt_ids(0:this%pe_size-1))
477 allocate(n_temp_ids(0:this%pe_size-1))
478 allocate(n_work_ids(0:this%pe_size-1))
480 do i = 0, this%pe_size-1
483 call work_pt_ids(i)%init()
484 call work_pe_ids(i)%init()
485 call temp_pe_ids(i)%init()
486 call temp_pt_ids(i)%init()
489 do i = 0, this%pe_size-1
490 call points_at_pe(i)%clear()
498 glob_id =
get_global_idx(this, points(1,i), points(2,i), points(3,i))
499 lin_glob_id = glob_id(1) + &
500 glob_id(2)*this%n_boxes + &
501 glob_id(3)*this%n_boxes**2
503 if (glob_id(1) .ge. 0 .and. glob_id(1) .lt. this%n_boxes .and. &
504 glob_id(2) .ge. 0 .and. glob_id(2) .lt. this%n_boxes .and. &
505 glob_id(3) .ge. 0 .and. glob_id(3) .lt. this%n_boxes)
then
506 call work_pe_ids(pe_id)%push(lin_glob_id)
507 call work_pt_ids(pe_id)%push(int(i,
i8))
508 n_work_ids(pe_id) = n_work_ids(pe_id) + 1
510 print *,
'Point found outside domain:', points(1,i), &
511 points(2,i), points(3,i), &
512 'Computed global id:', lin_glob_id, &
513 'Global box id (x,y,z):', glob_id(1), glob_id(2), glob_id(3)
521 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
522 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
523 call mpi_barrier(this%comm, ierr)
527 do i = 0, this%pe_size-1
528 call work_pe_ids(i)%clear()
529 call work_pt_ids(i)%clear()
532 do i =0 , this%pe_size-1
534 if (n_temp_ids(i) .gt. 0)
then
535 ids => temp_pe_ids(i)%array()
536 pt_ids => temp_pt_ids(i)%array()
537 do j = 1, n_temp_ids(i)
538 loc_id = ids(j) - int(this%pe_rank,
i8) * &
539 int(this%n_boxes_per_pe,
i8)
540 pe_cands => this%pe_map(int(loc_id))%array()
541 do k = 1, this%pe_map(int(loc_id))%size()
542 call work_pe_ids(i)%push(int(pe_cands(k),
i8))
543 call work_pt_ids(i)%push(pt_ids(j))
544 n_work_ids(i) = n_work_ids(i) + 1
546 if (this%pe_map(int(loc_id))%size() .lt. 1)
then
547 print *,
'No PE candidates found for point:', &
548 points(1,pt_ids(j)), &
549 points(2,pt_ids(j)), points(3,pt_ids(j))
557 call send_recv_data(this, temp_pe_ids, n_temp_ids, work_pe_ids, n_work_ids)
558 call send_recv_data(this, temp_pt_ids, n_temp_ids, work_pt_ids, n_work_ids)
562 do i = 0, this%pe_size-1
563 if (n_temp_ids(i) .gt. 0)
then
564 pe_cands8 => temp_pe_ids(i)%array()
565 pt_ids => temp_pt_ids(i)%array()
566 do j = 1, n_temp_ids(i)
568 call points_at_pe(pe_id)%push(int(pt_ids(j)))
569 n_points_pe(pe_id) = n_points_pe(pe_id) + 1
574 if (
allocated(work_pe_ids))
then
575 do i = 0, this%pe_size-1
576 call work_pe_ids(i)%free()
578 deallocate(work_pe_ids)
580 if (
allocated(temp_pe_ids))
then
581 do i = 0, this%pe_size-1
582 call temp_pe_ids(i)%free()
584 deallocate(temp_pe_ids)
586 if (
allocated(temp_pt_ids))
then
587 do i = 0, this%pe_size-1
588 call temp_pt_ids(i)%free()
590 deallocate(temp_pt_ids)
592 if (
allocated(work_pt_ids))
then
593 do i = 0, this%pe_size-1
594 call work_pt_ids(i)%free()
596 deallocate(work_pt_ids)
599 if (
allocated(n_work_ids))
then
600 deallocate(n_work_ids)
603 if (
allocated(n_temp_ids))
then
604 deallocate(n_temp_ids)
610 send_values, n_send_values)
612 type(
stack_i8_t),
intent(inout) :: recv_values(0:this%pe_size-1)
613 type(
stack_i8_t),
intent(inout) :: send_values(0:this%pe_size-1)
614 integer,
intent(inout) :: n_recv_values(0:this%pe_size-1)
615 integer,
intent(inout) :: n_send_values(0:this%pe_size-1)
616 integer :: i, j, ierr
618 integer(i8) ,
pointer :: sp(:)
620 call mpi_alltoall(n_send_values, 1, mpi_integer, &
621 n_recv_values, 1, mpi_integer, this%comm, ierr)
623 do i = 0, this%pe_size-1
624 if (n_recv_values(i) .gt. 0)
then
625 if (this%recv_buf(i)%size .lt. n_recv_values(i))
then
626 if (
allocated(this%recv_buf(i)%data))
deallocate(this%recv_buf(i)%data)
627 allocate(this%recv_buf(i)%data(n_recv_values(i)))
628 this%recv_buf(i)%size = n_recv_values(i)
630 call mpi_irecv(this%recv_buf(i)%data, n_recv_values(i), mpi_integer8, &
631 i, 0, this%comm, this%recv_buf(i)%request, ierr)
635 do i = 0, this%pe_size-1
636 if (n_send_values(i) .gt. 0)
then
637 if (this%send_buf(i)%size .lt. n_send_values(i))
then
638 if (
allocated(this%send_buf(i)%data))
deallocate(this%send_buf(i)%data)
639 allocate(this%send_buf(i)%data(n_send_values(i)))
640 this%send_buf(i)%size = n_send_values(i)
643 sp => send_values(i)%array()
644 do j = 1, n_send_values(i)
645 this%send_buf(i)%data(j) = sp(j)
647 call mpi_isend(this%send_buf(i)%data, n_send_values(i), mpi_integer8, &
648 i, 0, this%comm, this%send_buf(i)%request, ierr)
652 do i = 0, this%pe_size-1
653 call recv_values(i)%clear()
656 do i = 0, this%pe_size-1
657 if (n_recv_values(i) .gt. 0)
then
658 call mpi_wait(this%recv_buf(i)%request, this%recv_buf(i)%status, ierr)
659 do j = 1, n_recv_values(i)
660 idx = this%recv_buf(i)%data(j)
661 call recv_values(i)%push(idx)
665 do i = 0, this%pe_size-1
666 if (n_send_values(i) .gt. 0)
then
667 call mpi_wait(this%send_buf(i)%request, this%send_buf(i)%status, ierr)