Neko 1.99.1
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
aabb_pe_finder.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2023, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
36 use num_types, only : rp, dp, xp
38 use space, only : space_t
39 use pe_finder, only : pe_finder_t
40 use stack, only : stack_i4_t, stack_i4t2_t
41 use utils, only : neko_error, neko_warning
42 use tuple, only : tuple_i4_t
43 use htable, only : htable_i4_t
44 use point, only : point_t
46 use mpi_f08, only : mpi_sum, mpi_reduce, mpi_comm, mpi_comm_rank, &
47 mpi_comm_size, mpi_wtime, mpi_integer, mpi_in_place, &
48 mpi_min, mpi_allgather, mpi_barrier, mpi_double_precision, &
49 mpi_allreduce
50 use aabb, only : aabb_t
52 use math, only : neko_m_ln2, neko_eps
53 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_associated, &
54 c_sizeof, c_bool, c_loc
55 implicit none
56 private
57
59 integer, public, parameter :: glob_map_size = 4096
60
62 type, public, extends(pe_finder_t) :: aabb_pe_finder_t
64 real(kind=dp) :: padding
66 type(aabb_t), allocatable :: global_aabb(:)
67 type(aabb_tree_t) :: global_aabb_tree
69 integer :: pe_box_num
71 integer :: glob_map_size
72
73 contains
74 procedure, pass(this) :: init => aabb_pe_finder_init
75 procedure, pass(this) :: free => aabb_pe_finder_free
76 procedure, pass(this) :: find => aabb_pe_finder_find_candidates
77 procedure, pass(this) :: find_batch => aabb_pe_finder_find_candidates_batch
78
79 end type aabb_pe_finder_t
80
81contains
82
92 subroutine aabb_pe_finder_init(this, x, y, z, nelv, Xh, comm, padding)
93 class(aabb_pe_finder_t), intent(inout) :: this
94 real(kind=rp), intent(in), target :: x(:)
95 real(kind=rp), intent(in), target :: y(:)
96 real(kind=rp), intent(in), target :: z(:)
97 integer, intent(in) :: nelv
98 type(mpi_comm), intent(in), optional :: comm
99 type(space_t), intent(in), target :: Xh
100 real(kind=dp), intent(in) :: padding
101 integer :: lx, ly, lz, max_pts_per_iter, ierr, i, id1, id2, n, j
102 real(kind=dp), allocatable :: rank_xyz_max(:,:), rank_xyz_min(:,:)
103 real(kind=dp), allocatable :: max_xyz(:,:), min_xyz(:,:)
104 type(stack_i4t2_t) :: traverse_stack
105 type(aabb_tree_t) :: local_aabb_tree
106 type(aabb_t), allocatable :: local_aabb(:)
107 integer :: start, last, n_box_el, lvl
108 type(tuple_i4_t) :: id_lvl, temp_id_lvl
109 real(kind=rp) :: time1, time_start
110 type(aabb_node_t) :: node
111
112 call this%free()
113
114 this%comm = comm
115 this%padding = padding
116
117 call mpi_comm_rank(this%comm, this%pe_rank, ierr)
118 call mpi_comm_size(this%comm, this%pe_size, ierr)
119
120
121 time_start = mpi_wtime()
122 lx = xh%lx
123 ly = xh%ly
124 lz = xh%lz
125 n = nelv * lx*ly*lz
126 ! Create a local tree for each element at this rank
127 call local_aabb_tree%init(nelv)
128
129 allocate(local_aabb(nelv))
130
131 do i = 1, nelv
132 id1 = lx*ly*lz*(i-1)+1
133 id2 = lx*ly*lz*(i)
134 call local_aabb(i)%init( real((/minval(x(id1:id2)), &
135 minval(y(id1:id2)), &
136 minval(z(id1:id2))/), dp), &
137 real((/maxval(x(id1:id2)), &
138 maxval(y(id1:id2)), &
139 maxval(z(id1:id2))/), dp))
140 call local_aabb_tree%insert_object(local_aabb(i), i)
141 end do
142
143 this%pe_box_num = min(glob_map_size/this%pe_size, nelv)
144 this%pe_box_num = &
145 max(1, ishft(1, ceiling(log(real(this%pe_box_num, rp)) / neko_m_ln2)))
146
147 call mpi_allreduce(mpi_in_place, this%pe_box_num, 1, mpi_integer, &
148 mpi_min, this%comm, ierr)
149
150 this%pe_box_num = max(this%pe_box_num,2)
151 this%glob_map_size = this%pe_box_num*this%pe_size
152
153 if (pe_rank .eq. 0) then
154 print *, this%pe_box_num, this%glob_map_size
155 end if
156
157 allocate(rank_xyz_max(3,this%glob_map_size))
158 allocate(rank_xyz_min(3,this%glob_map_size))
159 allocate(min_xyz(3,this%pe_box_num))
160 allocate(max_xyz(3,this%pe_box_num))
161
162 i = 1
163 id_lvl = (/local_aabb_tree%get_root_index(), 0/)
164 call traverse_stack%init()
165 call traverse_stack%push(id_lvl)
166
167 lvl = 0
169 do while (traverse_stack%size() .gt. 0)
170 id_lvl = traverse_stack%pop()
171 lvl = id_lvl%x(2)
172 node = local_aabb_tree%get_node(id_lvl%x(1))
173 if (2**lvl .eq. this%pe_box_num .or. node%is_leaf()) then
174 min_xyz(:,i) = node%aabb%get_min()
175 max_xyz(:,i) = node%aabb%get_max()
176 i = i + 1
177 else if (2**lvl < this%pe_box_num) then
178 if (node%get_left_index() .ne. aabb_null_node) then
179 temp_id_lvl = (/node%get_left_index(), lvl+1/)
180 call traverse_stack%push(temp_id_lvl)
181 end if
182 if (node%get_right_index() .ne. aabb_null_node) then
183 temp_id_lvl = (/node%get_right_index(), lvl+1/)
184 call traverse_stack%push(temp_id_lvl)
185 end if
186 end if
187 end do
188 call traverse_stack%free()
189
190 !If somehow we dont need all boxes we just put a point here
191 if (nelv .eq. 0) then
193 do j = 1, this%pe_box_num
194 min_xyz(:,j) = [neko_eps, neko_eps, neko_eps]
195 max_xyz(:,j) = [neko_eps, neko_eps, neko_eps]
196 end do
197 else
198 !Needs to be something in the domain
199 do j = i, this%pe_box_num
200 min_xyz(:,j) = [x(1), y(1), z(1)]
201 max_xyz(:,j) = [x(1), y(1), z(1)]
202 end do
203 end if
205 call mpi_allgather(max_xyz, 3*this%pe_box_num, mpi_double_precision, &
206 rank_xyz_max, 3*this%pe_box_num, mpi_double_precision, this%comm, ierr)
207 call mpi_allgather(min_xyz, 3*this%pe_box_num, mpi_double_precision, &
208 rank_xyz_min, 3*this%pe_box_num, mpi_double_precision, this%comm, ierr)
209 call mpi_barrier(this%comm)
210 if (allocated(this%global_aabb)) deallocate(this%global_aabb)
211 allocate(this%global_aabb(this%glob_map_size))
213 do i = 1, this%glob_map_size
214 call this%global_aabb(i)%init(rank_xyz_min(:,i), rank_xyz_max(:,i))
215 end do
216 call this%global_aabb_tree%build_from_aabb(this%global_aabb,padding)
217 deallocate(local_aabb)
218 deallocate(rank_xyz_max)
219 deallocate(rank_xyz_min)
220 deallocate(min_xyz)
221 deallocate(max_xyz)
222 end subroutine aabb_pe_finder_init
223
224
226 subroutine aabb_pe_finder_free(this)
227 class(aabb_pe_finder_t), intent(inout) :: this
228
229 if (allocated(this%global_aabb)) then
230 deallocate(this%global_aabb)
231 end if
232
233 end subroutine aabb_pe_finder_free
234
238 subroutine aabb_pe_finder_find_candidates(this, my_point, pe_candidates)
239 class(aabb_pe_finder_t), intent(inout) :: this
240 type(point_t), intent(in) :: my_point
241 type(stack_i4_t), intent(inout) :: pe_candidates
242 integer, pointer :: pe_cands(:)
243 integer :: i
244
245 call this%global_aabb_tree%query_overlaps(my_point, -1, pe_candidates)
246 pe_cands => pe_candidates%array()
247 do i = 1, pe_candidates%size()
248 pe_cands(i) = (pe_cands(i)-1) / this%pe_box_num
249 end do
250
251 end subroutine aabb_pe_finder_find_candidates
252
253 subroutine aabb_pe_finder_find_candidates_batch(this, points, &
254 n_points, points_at_pe, n_points_pe)
255 class(aabb_pe_finder_t), intent(inout) :: this
256 integer, intent(in) :: n_points
257 real(kind=rp), intent(in) :: points(3,n_points)
258 type(stack_i4_t), intent(inout) :: points_at_pe(0:(this%pe_size-1))
259 integer, intent(inout) :: n_points_pe(0:(this%pe_size-1))
260 type(stack_i4_t) :: pe_candidates
261 type(point_t) :: my_point
262 integer :: i, j, temp_intent, pe_id, htable_data
263 real(kind=dp) :: pt_xyz(3)
264 integer, pointer :: pe_cands(:)
265 type(htable_i4_t) :: marked_rank
266
267 do i = 0, this%pe_size-1
268 call points_at_pe(i)%clear()
269 n_points_pe(i) = 0
270 end do
271
272 call marked_rank%init(32, htable_data)
273 call pe_candidates%init()
274
276 do i = 1, n_points
277 call marked_rank%clear()
278 pt_xyz = (/ points(1,i), points(2,i), points(3,i) /)
279 call my_point%init(pt_xyz)
280 call pe_candidates%clear()
281 call this%find(my_point, pe_candidates)
282
283 pe_cands => pe_candidates%array()
284 do j = 1, pe_candidates%size()
285 pe_id = pe_cands(j)
286 ! Check if this rank has already been marked
287 if (marked_rank%get(pe_id, htable_data) .ne. 0) then
288 n_points_pe(pe_id) = n_points_pe(pe_id) + 1
289 temp_intent = i
290 call points_at_pe(pe_id)%push(temp_intent)
291 ! Doesnt matter, I use htable as a set
292 htable_data = 100
293 call marked_rank%set(pe_id, htable_data)
294 end if
295 end do
296
297 if (pe_candidates%size() .lt. 1) then
298 write (*,*) 'Point', points(:,i), &
299 'found to be outside domain, try increasing the padding to find rank candidates.'
300 end if
301 end do
302 call marked_rank%free()
303 call pe_candidates%free()
304
306
307end module aabb_pe_finder
double real
Implements aabb_pe_finder given a dofmap.
subroutine aabb_pe_finder_find_candidates_batch(this, points, n_points, points_at_pe, n_points_pe)
subroutine aabb_pe_finder_free(this)
Destructor.
integer, parameter, public glob_map_size
Minimum number of total boxes in the aabb tree.
subroutine aabb_pe_finder_find_candidates(this, my_point, pe_candidates)
Find pe candidates.
subroutine aabb_pe_finder_init(this, x, y, z, nelv, xh, comm, padding)
Initialize the global interpolation object on a set of coordinates.
Axis Aligned Bounding Box (aabb) Tree data structure.
Definition aabb_tree.f90:70
integer, parameter, public aabb_null_node
Definition aabb_tree.f90:79
Axis Aligned Bounding Box (aabb) implementation in Fortran.
Definition aabb.f90:71
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:50
integer, public pe_size
MPI size of communicator.
Definition comm.F90:58
integer, public pe_rank
MPI rank.
Definition comm.F90:55
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:42
Implements a hash table ADT.
Definition htable.f90:36
Definition math.f90:60
real(kind=rp), parameter, public neko_m_ln2
Definition math.f90:72
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.f90:69
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public xp
Definition num_types.f90:14
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements pe_finder given a dofmap.
Definition pe_finder.f90:35
Implements a point.
Definition point.f90:35
Defines a function space.
Definition space.f90:34
Implements a dynamic stack ADT.
Definition stack.f90:35
Implements a n-tuple.
Definition tuple.f90:34
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:346
Axis Aligned Bounding Box (aabb) data structure.
Definition aabb.f90:107
Implements global interpolation for arbitrary points in the domain.
Node type for the Axis Aligned Bounding Box (aabb) Tree.
Definition aabb_tree.f90:86
Axis Aligned Bounding Box (aabb) Tree.
Integer based hash table.
Definition htable.f90:82
Implements global interpolation for arbitrary points in the domain.
Definition pe_finder.f90:45
A point in with coordinates .
Definition point.f90:43
The function space for the SEM solution fields.
Definition space.f90:63
Integer based stack.
Definition stack.f90:63
Integer 2-tuple based stack.
Definition stack.f90:84
Integer based 2-tuple.
Definition tuple.f90:51
#define max(a, b)
Definition tensor.cu:40